Describing RESTful URLs - http

Here's an example URL:
/users/123/comments
Based on this URL, which term would best describe users? Is users the resource or is it a part of the resource. What would be the name of that part?
The same question goes for the other parts. Which terms would best describe 123 and comments?
Is there a term that would refer to the second part of RESTful URLs? It would describe 123 in /users/123 and purchases in /me/purchases.

REST is a Resource-Oriented. URLs represent resources.
In your example, /users/123/comments:
users is a resource.
123 is the unique identifier of an user.
In this case, comments are a sub-resource of users, but they are probably resources on their own (ex. calling /comments/{id})
About your second question, the format for /me/purchases is not the same as /users/123. And /me/purchases is probably a short URL for something like /users/{myid}/purchases where purchases are a sub-resource of users (and probably a resource on their own also, available by /purchases/{id}).
For more information, here is a video, that is not directly related to your question, but that is very well made and very interesting about REST web services.

In your example, http://example.org/users/123/comments points to a resource. A complete URI is an identifier for a resource.
Let me give you an extreme example,
/users/123/comments.xml
/users/123/comments.json
are two different resources.
The query string also identifies resources, so
/users/123/comments?format=xml
/users/123/comments?format=json
are also two different resources.
Resources do not map to entities. Resources are "some concept" that you wish to expose over HTTP and have identified with a URI.
In RESTful system URIs are opaque to the system design. A client of your system should not try and infer meaning from portions of your URI. A server can setup conventions to help it build a URI space, but these are private implementation details of the server.
There is no such thing as a RESTFul url. The term is a fabrication of framework designers and will just serve to confuse you.

Related

REST: Proper way to handle partially-restricted resources

I’m redesigning the REST API for a small SaaS I built. Currently there’s a route /entries that doesn’t require any authentication. However, if the client authenticates with sufficient privileges, the server will send additional information (ex: the account associated with each entry).
The main problem I see with this is that a client attempting to request protected data with insufficient privileges will still receive a 200 response, but without the expected data, instead of a 401 Unauthorized.
The alternatives I came up with are:
Split the endpoint into two endpoints, ex /entries and /admin/entries. The problem with this approach is that there are now two different endpoints for essentially the same resource. However, it has the advantage of being easy to document with OpenAPI. (Additionally, it allows for the addition of a /entries/:id/account endpoint.)
Accept a query parameter ?admin=true. This option is harder to document. On the other hand, it avoids having multiple URIs for a single entry.
Is there a standard way to structure something like this?
Related question: Different RESTful representations of the same resource
The alternatives I came up with are
Note that, as far as HTTP/REST are concerned, your two alternatives are the same: in both cases you are introducing a new resource.
The fact that in one case you use path segments to distinguish the two identifiers and in the other case you are using the query part doesn't change the fact that you have two resources.
Having two resources with the same information is fine - imagine two web pages built from the same information.
It's a trade off - the HTTP application isn't going to know that these resources have common information, and so won't know that invalidating one cached resource should also invalidate the other. So just like with web pages, you can get into situations where the representations that you have in your cache aren't consistent with each other.
Sometimes, the right answer is to use links between different resources - have "the" information in one place, and everywhere else has links that allow you to find that one place. Again, trade-offs.
HTTP isn't an infinitely flexible application protocol. It's really good at transferring documents over a network, especially at "web scale".
There have been attempts at using Link headers to trigger invalidation of other cached resources, but as far as I have been able to tell, none of them has made it past the proposal stage.

How should I specify the resource database via HTTP Requests

I have a REST API that will be facilitating CRUD from multiple databases. These databases all represent the same data for different locations within the organization (IE We have 20 or so implementations of a software package and we want to read from all of the supporting databases via one API).
I was wondering what the "Best Practice" would be for facilitating what database to access resources from?
For example, right now in my request headers I have a custom "X-" header that would represent the database id. Unfortunately, this sort of thing feels a bit like a workaround.
I was thinking of a few other options:
I could bake the Database Id into the URI (/:db_id/resource/...)
I could modify the Accept Header like someone would with an API version
I could split up the API to be one service per database
Would one of the aforementioned options be considered "better" than the others, and if not what is considered the "best" option for this sort of architecture?
I am, at the moment, using ASP.NET Web API 2.
These databases all represent the same data for different locations within the organization
I think this is the key to your answer - you don't want to expose internal implementation details (like database IDs etc.) outside your API - what if you consolidate? or change your internal implementation one day?
However, this sentence reveals a distinction that is meaningful to the business - the location.
So - I'd make the location part of the URI:
/api/location/{locationId}/resource...
Then map the locationId internally to a database ID. LocationId could also be a name, or a code, or something unique that would be meaningful to the API client.
Then - if you later consolidate multiple locations to the same database or otherwise change your internal implementation, the clients don't have to change.
In addition, whoever is configuring the client applications, can do so thinking about something meaningful to the business - the location they are interested in.

URI in RESTful architecture

I am confused here! I read a blog and it said in RESTful architecture,we can use more than one URI to represent a resource.
Is this right,since URI is use as identifier,it should be unique. Did I misunderstand something?
Sorry I am not going to post the link of that post because it is written in Chinese:)
Yes that is true. REST follows existing standards (aka. uniform interface constraint), now we are talking about the URI standard.
I think the simplest example about this is localhost. So imagine you have a REST service on http://localhost/api on your computer. Now by default you can reach the same service using http://127.0.0.1/api. So even the api root does not have an 1:1 relationship with the URIs in this case. In terms of the URI standard uniqueness means an 1:n relation between the resource and the URIs. This is different to the uniqueness term you are used to by relational databases. So in different words, a single resource can be identified by multiple URIs, but a single URI can identify only a single resource.

Should "/users" and "/users/" point to the same (RESTful) resource?

They do in this and probably any other website, but I'm not sure I understand why.
A popular analogy compares RESTful resources to files in the file system and filename users wouldn't point to the same object as filename users/ static web pages and in a static website users would point to users.html and users/ - to a different file - users/index.html.
Short answer: they may only identify the same resource if one redirects to the other.
URI's identify resources, but they do so differently depending on the response status code to a GET request in HTTP. If one returns a 3xx to the other, then the two URI's identify the same resource. If the two resources each return a 2xx code, then the URI's identify different resources. They may return the same response in reply to a GET request, but they are not therefore the same resource. The two resources may even map to the same handler to produce their reply, but they are not therefore the same resource. To quote Roy Fielding:
The resource is not the storage object. The resource is not a
mechanism that the server uses to handle the storage object. The
resource is a conceptual mapping -- the server receives the identifier
(which identifies the mapping) and applies it to its current mapping
implementation (usually a combination of collection-specific deep tree
traversal and/or hash tables) to find the currently responsible
handler implementation and the handler implementation then selects the
appropriate action+response based on the request content.
So, should /users and /users/ return the same response? No. If one does not redirect to the other, then they should return different responses. However, this is not itself a constraint of REST. It is a constraint, however, which makes networked systems more scalable: information that is duplicated in multiple resources can get out of sync (especially in the presence of caches, which are a constraint of REST) and lead to race conditions. See Pat Helland's Apostate's Opinion for a complete discussion.
Finally, clients may break when attempting to resolve references relative to the given URI. The URI spec makes it clear that resolving the relative reference Jerry/age against /users/ results in /users/Jerry/age, while resolving it against /users (no trailing slash) results in /Jerry/age. It's amazing how much client code has been written to detect and correct the latter to behave like the former (and not always successfully).
For any collection (which /users/ often is), I find it best to always emit /users/ in URI's, redirect /users to /users/ every time, and serve the final response from the /users/ resource: this keeps entities from getting out of sync and makes relative resolution a snap on any client.
filename users wouldn't point to the same object as filename users/.
That is not true. In most filesystems, you cannot have a file named users and a directory named users in the same parent directory.
cd users and cd users/ have the same result.
There are some nuances on this, while "users" represent one resource while "users/" should represent a set of resources, or operations on all resources "users"... But there does not seem to exist a "standard" for this issue.
There is another discussion on this, take a look here: https://softwareengineering.stackexchange.com/questions/186959/trailing-slash-in-restful-api
Technically they are not the same. But a request for /users will probably cause a redirect to /users/ which makes them semantically equal.
In terms of JAX-RS #Path, they can both be used for the same path.

HTTP Verbs and Content Negotiation or GET Strings for REST service?

I am designing a REST service and am trying to weight the pros and cons of using the full array of http verbs and content negotiation vs GET string variables. Does my choice affect cacheability? Neither solution may be right for every area.
Which is best for the crud and queries (e.g. ?action=PUT)?
Which is best for api version picking (e.g. ?version=1.0)?
Which is best for return data type(e.g. ?type=json)?
CRUD/Queries are best represented with HTTP verbs. A create and update is usually a PUT or POST. A retrieve would be a GET. Deletes would be a DELETE. Thats the generally mapping. The main point is that a GET doesn't cause side effects, and that the verbs do what you'd expect them to do.
Putting the action in the URI is OK if thats the -only- way to pass it (e.g, the http client library doesn't allow you to send non-GET/POST requests). Most libraries do, though, so its strongly advised not to pass the verb via the URL.
The "best" way to version the API would be using HTTP headers on a per-request basis; this lets clients upgrade/downgrade specific requests instead of every single one. Of course, that granularity of versioning needs to be baked in at the start and could severely complicate the server-side code. Most people just use the URL used the access the servers. A longer explanation is in a blog post by Peter Williams, "Versioning Rest Web Services"
There is no best return data type; it depends on your app. JSON might be easier for Ajax websites, whereas XML might be easier for complicated structures you want to query with Xpath. Protocol Buffers are a third option. Its also debated whether its better to put the return protocol is best specified in the URL or in the HTTP headers.
For the most part, headers will have the largest affect on caching, since proxies are suppose to respect them when told, as are user agents (obviously UA's behave differently, though). Caching based on URL alone is very dependent on the layers. Some user agents don't cache anything with a query string (Safari, iirc), and proxies are free to cache or not cache as they feel appropriate.

Resources