Proper way to distinguish between multiple services using zeroconf - bonjour

I'm writing a piece of software that will run on computers as well as phones.
The service uses an HTTP API for communication and will be published over the local network using Zeroconf.
Initially I published my service using _http._tcp. as the service type but I quickly discovered that both my NAS and my music receiver(!) also broadcasts themselves with that exact service type.
So the question now arises how to differentiate between my service and other services that are using HTTP.
Alternatives
Using a different service type
The is certainly the most certainly the easiest way and (almost) guarantees no other services will be picked up.
However, according to Apple1 new services should be registered with IANA. This is obviously not required but seeing as they recommend it it feels like it would be the wrong way to do it
Using the TXT record
Apple2 describes the TXT record like this:
When a service is registered, three related DNS records are created: a service (SRV) record, a pointer (PTR) record, and a text (TXT) record. The TXT record contains additional data needed to resolve or use the service, although it is also often empty.
The certainly feels like it could be the right way to do it, but I'm still not sure and it's hard to find a description of what the field should contain.
My first though would be to put something like <service_name>-<version> which will then be parsed to see which service it actually is.
My NAS seems to use this for identifying model and version numbers.
Try talking to the service
After finding a service one could always perform a HEAD request on a known endpoint and look for a known header set by the service.
This feels like a fairly slow approach and who knows what making a HEAD request to my receiver will do.
And just to be clear, this question has nothing to do with a specific language or framework, it's about the concepts of zeroconf.
I could show some code but I don't see how that would help.

First, does the service you're advertising actually meet the qualifications for _http as defined by RFC 2782. Specifically- is it not just using HTTP for a transport but is also:
can be displayed by "typical" web browser client software, and
is intended primarily to be viewed by a human user.
If no, register your own service type (there are a couple other services that use HTTP as a transport but don't meet those qualifications so they have -http as a suffix to the service name, see pgpkey-http, senteo-http, xul-http).
If yes, there are a couple ways to go depending on how strict one's interpretation of the RFC is. The least strict being just adding a TXT record as you've already noted in your question. iTunes registers itself with a TXT record in the format iTSh Version=196618.
If you're feeling a little more strict, the RFC only explicitly states that the u=, p= and path= TXT records exist for HTTP. Perhaps someone can chime in on this, but I haven't seen much discussion on whether adding TXT records to already existing entries is frowned upon or not. So with that, the other way is to just an algorithmic instance name. For example, adding the suffix "-NicklasAService" to the device name. Hopefully giving it a unique name to the local network but still making it so that the service can be easily picked out by the PTR record by just looking for the suffix.

Related

Looking for nomenclature & architecture ideas having to do with server via point of user-data exchange

I have been struggling to find a good architecture, or even any nomenclature for what I'm trying to do here. I'm looking for nomenclature so I can have a starting point for research. And I want the same for architecture, but I'll take whatever anyone wants to help with.
What I'm trying to do & learn about
In a nutshell I need my clients to exchange pub keys, and other security data such as ACL ID's, name etc.
Current architectural attempts
I'm currently using my server as a via point, mainly because I can't see any other way of doing this securely and this method uses many layers of security. I also don't know of any other method of going client app to app securely.
A client creates group and sends pub key to server, opens a live query to receive other users data. Other user (with secrets passed to user) queries server for pub key, then sends own data to admin user via server. Admin then sends remainder of own data. I'm leaving out trivial security details but this is the gist of what I'm doing.
Issues
This is really just logical back and forth, but I honestly don't know what I'm doing. I don't even know if what I'm doing is right or the best way, I've also got a crazy infinity loop I'm trying to solve.
I'm looking for some terminology, description and/or architectural pointers, I'll take any input I can get.
Forget terminology, nomenclature and architecture.
Define the problem you are trying to solve in a simple sentence.
Break down the issues into smaller pieces (bite size).
You send A data to server
What happens to the A data
Any feedback or acknowledgement from the target host?
What sort of application is this? Web, Mobile, traditional client/server?
The most elegant solutions are usually the simplest ones.
Sit down and determine whether you have a problem to solve in the first place.

REST API design for action that is not REST [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
I'm designing REST API for devices management system.
Endpoints:
http://api.example.com/users
http://api.example.com/devices
I want to achieve that there is an endpoint that will do some action on selected device. Something like that:
http://api.example.com/devices/1/send_signal
I know that is not REST compatible and I'm looking for suggestions to make it the right way.
I was thinking about adding another endpoint like:
http://api.example.com/calls
So when user send POST request with let's say deviceId parameter to that endpoint there will be new entry into the database (to have history of all calls and who called the function) and at the same time calls that function on specified device.
Would it be great architecture and REST compatible?
You are right about your hunch. It is not proper REST. Sometimes that is OK, but most often, it is a sign that something in your Domain needs redesigning.
Quite often, there is a domain model waiting to be discovered. Most often, things like "send_signal" are telling you that you've modeled your API too close to some library, backend service or database. An API, after all, is the interface you provide.
AS I've written before: The R in REST stands for resource (which isn't true.... etc).
Think in resources. Not in procedures or calls, or internal tools, backend services or architecture of your system. That is your stuff. The API-user should only be bothered with (clean) abstractions that make senses to the API-user.
Both /call and /.../send_signal bother too much about procedures and internals.
What do you want to do with a device? You want to turn it's camera on? That would be an update to the Camera model on the Device with ID 1337:
PUT /device/1337/camera { power: "on" }
You want a device to bzip up some log files and send them to a debug-server? You're creating a DebugSession model:
POST /device/1337/debug_session { delivery_bucket: 42, compress: "bzip" }
You want a device to send a message to some server? Create a Message on a Device:
POST /device/1337/messages { to: john, body: "Hello World" }
And so on.
That is REST. In REST you model your domain models carefully. Lots of REST servers are really poor because they are very thin wrappers around some relational databases, and suffer from far too much leaky abstractions. Lots of other REST servers are really poor because they are written far too close around backend services, jobs being ran, or other internal details.
If I want to start a new server, I want to say:
POST /server/ { region: eu-1, size: xl, disk: 1MB }
And not:
POST /resources/blockdisks/create { size: 10GB } => 1337 is created
GET /resources/blockdisks/1337?include_attrs=mountpoint,format
GET /servers/available/map_for/eu-1?xl => DB-Zfaa-dd-12
POST /servers/reserve { id: DB-Zfaa-dd-12, attach: { id: 1337, mountpoint: /dev/sdb2, format: zfs }
(I'm not making this up, I had to deal with such API's they are a PIAS to use, and quite certainly an even bigger PIAS to maintain)
The lesson here: the first exposes a domain model of a Server, with few attributes only interesting to the user of the API. The second is modeled far too close around all sorts of internal tooling, and systems.
Edit: and all this completely ignores the even more important REST-part: discovery. Links, headers, redirects, etc. But you were explicitly asking about naming resources, so that's what my answer is about. Once you have your resources, your domain models, architectured, go back to the whiteboard and do it all over: now including Links, headers, or other metadata so that your API-clients can discover what they can do and where they can do that.
http://api.example.com/devices/1/send_signal
I know that is not REST compatible and I'm looking for suggestions to make it the right way.
It is REST compatible. REST doesn't care what spellings you use for your resource identifiers.
Would it be great architecture and REST compatible?
If this is what you want, think about how you would achieve the same result with a website. The client would open a bookmark in a browser, maybe follow some links, fill in a form, and submit it. That would all work because the (generic) browser understands the processing rules for HTML, and how to manage cache meta data in HTTP, and so on. There's no point in the chain where the client needs to compose an identifier -- it either uses one provided by the server as is, or it calculates one using the generic processing rules for HTML forms.
OP clearly uses a verb, to communicate intent and procedures, which is not RESTful.
No; this is a common misunderstanding. There's nothing in the REST architectural style that says anything about human readable semantics in identifiers. URL shorteners work.
It's analogous to saying that a variable name in a program should never be a verb, because that doesn't correctly communicate intent -- the compiler/interpreter doesn't care.
The use of spelling conventions does not make a URI more or less RESTful. See Tilkov. It might even be preferable to avoid using predictable identifiers, as that ensures that consumers read the identifiers provided in the hypermedia representations, which is the point.
I think you are on the right track. Based on what you said about the system, I would probably start with this way of doing it and go from there.
POST http://api.example.com/devices/123/calls
This would send the details of the call to the API and it would intern save the call to a data store and send off an event to the appropriate subsystem or internal library to call out to the device.
Then you could have the following endpoints to get call details.
GET http://api.example.com/devices/123/calls/456
GET http://api.example.com/devices/123/calls -This would also include query parameters to limit the results in some way, probably by date.
If you want to get calls from all devices then you could to this with some query parameters restricting the result set, again maybe by date.
GET http://api.example.com/devices/calls
Just as a side note, if this is an internal API used only by your applications RPC style may be appropriate. But, by following HTTP/REST you will make your software more malleable so you can use it in more ways without making it specific to any one function.
This is a good article on REST vs RPC if you'd like to learn more. https://cloud.google.com/blog/products/application-development/rest-vs-rpc-what-problems-are-you-trying-to-solve-with-your-apis

How to tell between a nonexistent service or a lack of a record?

I'm making some REST services, and as I'm implementing a GET request, I was debating about what I should do if there is no record there, for example /profile/1234. Now, if you tried to use /profiles/1234 (note the s on profiles) it would definitely be a 404 code because that URL definitely isn't found. But when it comes to there just being no 1234 profile, I'm not sure what I should return. I don't want to return {} because that might give the impression there is a record with no data. But if I return a 404 error code, how is the consumer of the API supposed to tell the difference between the two 404s?
How can I be a responsible API designer by communicating programmatically what the difference between a service that doesn't exist and a record that doesn't exist?
You can send a custom status message which will help you differentiate between the "different" 404s.
On the other hand, I wouldn't worry about that distinction. People are used to having to type api endpoints carefully. As long as they manually test their app a tiny bit the issue becomes a non-issue.

HTTP header field for URI deprecation/expiration

I'm building a REST service where I want to implement a way to deprecate certain URIs when they shouldn't be supported anymore for one reason or another. As functions are deprecated, they will be replaced by new ones that work in similar (but not identical) ways. This means that at some point, I will have to start responding with 410 Gone.
The idea is that all client software should be updated, and after say six months all users should have had the chance to upgrade. At this time, the deprecated URIs will start to inform the client that it's out of date, so that the client can display a message to the user. This time is not known in advance, though, and can't explicitly be written in the documentation.
The problem I want to solve is:
Is there an HTTP header field I should use to indicate that a certain URI will cease to work at a certain time and, if so, which?
This can't be the first time someone wants to solve this problem. Is there an unofficial header field already in use, or should I design my own? Note that I don't want to add this information to the content itself, as that would mean that every resource was changed and needs to be refreshed by the client, which is of course not what happened.
Strictly speaking, no. The resources should be driving your applications state, so if there is a change, the uri linking would provide the nessessary changes to your application.
For a HTTP header, you are free to add custom headers. Normally starting with X- but its important to know changes to uri's is only interesting to developers not users.

Connectedness & HATEOAS

It is said that in a well defined RESTful system, the clients only need to know the root URI or few well known URIs and the client shall discover all other links through these initial URIs. I do understand the benefits (decoupled clients) from this approach but the downside for me is that the client needs to discover the links each time it tries access something i.e given the following hierarchy of resources:
/collection1
collection1
|-sub1
|-sub1sub1
|-sub1sub1sub1
|-sub1sub1sub1sub1
|-sub1sub2
|-sub2
|-sub2sub1
|-sub2sub2
|-sub3
|-sub3sub1
|-sub3sub2
If we follow the "Client only need to know the root URI" approach, then a client shall only be aware of the root URI i.e. /collection1 above and the rest of URIs should be discovered by the clients through hypermedia links. I find this cumbersome because each time a client needs to do a GET, say on sub1sub1sub1sub1, should the client first do a GET on /collection1 and the follow link defined in the returned representation and then do several more GETs on sub resources to reach the desired resource? or is my understanding about connectedness completely wrong?
Best regards,
Suresh
You will run into this mismatch when you try and build a REST api that does not match the flow of the user agent that is consuming the API.
Consider when you run a client application, the user is always presented with some initial screen. If you match the content and options on this screen with the root representation then the available links and desired transitions will match nicely. As the user selects options on the screen, you can transition to other representations and the client UI should be updated to reflect the new representation.
If you try and model your REST API as some kind of linked data repository and your client UI as an independent set of transitions then you will find HATEOAS quite painful.
Yes, it's right that the client application should traverse the links, but once it's discovered a resource, there's nothing wrong with keeping a reference to that resource and using it for a longer time than one request. If your client has the possibility of remembering things permanently, it can do so.
consider how a web browser keeps its bookmarks. You probably have maybe ten or a hundred bookmarks in the browser, and you probably found some of these deep in a hierarchy of pages, but the browser dutifully remembers them without requiring remembering the path it took to find them.
A more rich client application could remember the URI of sub1sub1sub1sub1 and reuse it if it still works. It's likely that it still represents the same thing (it ought to). If it no longer exists or fails for any other client reason (4xx) you could retrace your steps to see if you can find a suitable replacement.
And of course what Darrel Miller said :-)
I don't think that that's the strict requirement. From how I understand it, it is legal for a client to access resources directly and start from there. The important thing is that you do not do this for state transitions, i.e. do not automatically proceed with /foo2 after operating on /foo1 and so forth. Retrieving /products/1234 initially to edit it seems perfectly fine. The server could always return, say, a redirect to /shop/products/1234 to remain backwards compatible (which is desirable for search engines, bookmarks and external links as well).