In XMPP (i.e. gtalk) we can set resource to our wanting (specifying machine/location/etc) and this works well with all/most servers and clients. But in case of google it doesn't exactly work as expected because each time user connect google appends random string to the resource set by user. This is particularly annoying because many clients differentiate user chats by jid AND resource part which results in multiple windows/tabs open after one is reconnected (and new resource is generated).
tl;dr - is there a way to prevent google from appending random string to resource set by user?
Short answer, there is no way. A resource should be unpredictable for security reasons. And The GTalk server enforces this by adding a random string to your resource.
In addition to #Alex's correct answer, don't use resources semantically. For chats, clients really shouldn't treat each resource as a separate conversation anymore. We learned that lesson over a decade ago. For identifying the client, use XEP-0115 instead of a hard-coded resource.
Related
I am designing an API for domain admin to manage user cookie sessions, specifically
GET users/{userKey}/sessions to get a list of a user's all sessions
DELETE users/{userKey}/sessions/{sessionId} to delete a user's specific session
I want to expose another method for the admin to delete (reset) a user's all sessions. I am considering 2 options, I wonder which one is more Restful
DELETE users/{userKey}/sessions - {sessionId} left blank to delete all sessions
POST users/{userKey}/sessions/reset
REST was never designed for bulk transaction support, it's for representing the state of individual objects. That said, API design is very opinionated and you have to balance REST "pureness" with functionality. If I were designing this, I would go with option 1 and use delete at the "sessions" endpoint since you are removing all of the user sessions and not just a single or subset.
This answer may be opinion based, so take it as such.
I would use DELETE if you are removing the resource (since you are going to be removing sessions).
If you keep the sessions (but change some data in those resources eg sliding expiration) then I would consider using PATCH as you're modifying (resetting and not replacing) existing sessions.
I would go with DELETE # users/sessions
If you think about it, a reset is simply an admin dropping a session. The user gets their new session when/if they return. So a reset route does not make much sense as you are not reissuing sessions to all of your users in this action.
My preference is users/sessions rather then users/{*}/sessions. The later route suggests that you are wanting to remove all sessions of the parent resource, in this case being a single user.
I want to expose another method for the admin to delete (reset) a user's all sessions. I am considering 2 options, I wonder which one is more Restful....
You probably want to be using POST.
POST serves many useful purposes in HTTP, including the general purpose of “this action isn’t worth standardizing.” -- Fielding, 2008.
HTTP DELETE isn't often the right answer
Relatively few resources allow the DELETE method -- its primary use is for remote authoring environments, where the user has some direction regarding its effect. -- RFC 7231
HTTP Methods belong to the "transfer documents over a network" domain, not to your domain.
REST doesn't actually care about the spelling of the target-uri -- that's part of the point. General-purpose HTTP components don't assume that the uri has any specific semantics encoded into it. It is just a opaque identifier.
That means that you can apply whatever URI design heuristics you like. It's a lot like choosing a name for a variable or a namespace in a general-purpose programming language; the compiler/interpreter don't usual care if the symbol "means" anything or not. We choose names that make things easier for the human beings that interact with the code.
And so it is with URI as well. You'll probably want to use a spelling that is consistent with other identifiers in your API, so that it looks as though the api were designed by "one mind".
A common approach starts from the notion that a resource is any information that can be named (Fielding, 2000). Therefore, it's our job to first (a) figure out the name of the resource that handles this request, then (b) figure out an identifier that "matches", that name. Resources are closely analogous to documents, so if you can think of the name of the document in which you would write this message, you are a good ways toward figuring out the name (ex: we write expiring sessions into the "security log", or into the "sessions log". Great, now figure out the corresponding URI.)
If I ran the zoo: I imagine that
GET /users/{userKey}/sessions
would probably return a representation of the users cookie sessions. Because this representation would be something that changes when we delete all of the users sessions, I would want to post the delete request to this same target URI
POST /users/{userKey}/sessions
because doing it that way makes the cache invalidation story a bit easier.
I'm new to designing RESTful APIs and currently developing APIs to manage students in a school.
Each student has a unique roll number that clients provide while adding/creating a user. Service creates an internal id that is unique for every user that is added.
If clients make multiple POST calls for the same user, what are the recommended options in this scenario? Success with an existing resource id? or an error? or something else.
If clients make multiple POST calls for the same user, what are the recommended options in this scenario? Success with an existing resource id? or an error? or something else.
One important thing to remember is that, on an unreliable network, the client cannot distinguish between a lost request and a lost response. So you will probably benefit from having a clear protocol in place to handle that condition.
Idempotent request handling is probably your best bet: tell the client that the user was created successfully as many times as it takes.
There's an edge case where you get two messages with the same unique identifier, but the other data is different, and you should work through the protocol to figure out the correct behavior in that case (first writer wins? last writer wins? raise a conflict?) keeping in mind that you have no guarantees that requests arrive in the order that they were sent.
Note: because you are using POST, general purpose components will not know that the request is idempotent, and won't be able to take advantage of that, which is fine. A resource model that supports PUT, rather than POST, would allow the general purpose components to handle lost messages, but there are other trade offs (for instance, HTML forms don't support PUT).
You have two options, POST and PUT, you can choose one of these or both based on your requirement.
If you choose POST, and if the resource already exists, throw an error saying the resource exists.
If you choose PUT, and if the resource already exists, then update the resource and return the existing resource id.
These are widely followed conventions which are intuitive for the api consumers. If you are deviating from these for any special cases then you have to make sure that the api consumers are aware of your convention.
This link might be super useful - PUT vs. POST in REST
Take this design of an API:
/articles/{id} - Returns an article. Client provides a token in the header to identify them.
/updated-articles - Returns collection of articles that have been updated since the client's last call to this endpoint, and only includes articles that this client previously requested. Client provides a token in the header to identify them.
The second enpoint doesn't fit very well with me. The design motivation of that second enpoint is that the client does not need to track the time of their last requests. Is this breaking the "statelessness" constraint of RESTful APIs? An alternative approach would be /updated-articles?since=YYYY-MM-DD but this would require clients to remember
Your "token" is basically a client id, and the fact of remembering the date of their last access is keeping a client-state on the server.
Think about it : If you had to scale up your service, could you simply plug-in a new server, copy your service's files, and redirect via a round-robin algorithm on one or another of the two server (without having them sharing informations) ? Clearly no, because you would need your table tokens<->date of last consultation shared between the two servers. So no it's definitely not stateless.
Plus, I don't understand your point :
An alternative approach would be /updated-articles?since=YYYY-MM-DD
but this would require clients to remember
Wouldn't a token require a client to remember ? On the contrary, this way would be RESTful, since the client-state (the date of last consultation) would be kept on the client side.
Basically, no, I don't think your second resource would break statelessness.
I think it's okay to have your client's keep track of their own 'updated at' time stamp. Your api should be stateless. The client doesn't have to be stateless.
If anything the client should retain a lot of state. The client will be a device central to one user and their specific needs. It's responsible for keeping track of the user's needs and current state. In this situation someone will have to store that time stamp. I think it should be your clients, not your server.
This is just my opinion though.
I did find a write up over the true meaning of statelessness that I think could benefit you as well here.
We should avoid creating endpoints with no related entity. So instead of /updated-articles?since=<timestamp> a better approach should be:
/articles?updated=true&since-last-request=true or
/articles?updated-since-last-request=true
If the intended result should affect all clients. Meaning every request time stamp must be kept on the server. Or
/articles?updated-since=<timestamp>
If the intended result depends on each client behavior. That seems to be your case.
The choice between the former or the latter (or both) depends on the use case. But the main point is to avoid creating endpoints with no related entity and having special cases being defined by parameters.
As a guideline:
Endpoints are substantives, adjectives are parameters and verbs are the HTTP request methods
This also means a simple 'GET /articles' means returning ALL articles. To avoid abuse you may issue proper 4xx codes depending on the case.
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.
One of our web site is a common "Announce for free your apartment".
Revenues are directly associated to number of public usage and announces
registered (argument of our marketing department).
On the other side, REST pushes to maintain a clear api when designing your
api (argument of our software department) which is a data stealing
invitation to any competitors. In this view, the web server becomes
almost an intelligent database.
We clearly identified our problem, but have no idea how to resolve these
contraints. Any tips would help?
Throttle the calls to the data rich elements by IP to say 1000 per day (or triple what a normal user would use)
If you expose data then it can be stolen. And think about search elements that return large datasets even if they are instigated by javascript or forms - I personally have written trawlers that circumvent these issues.
You may also think (if data is that important) about decrypting it in the client based on keys and authentication sent from the server (but this only raises the bar not the ability to steal.
Add captcha/re-captcha for users who are scanning too quickly or too much.
In short:
As always only expose the minimum API to do the job (attack surface minimisation)
Log and throttle
Force sign in(?). This at least MAY put off some scanners
Use capthca mechanism for users you think may be bots trawling your data