REST API- Defining proper and intuitive URI - rest

I'm tring to create a little registration app, that will be published as a REST API. It will allow users / systems to create an account on my system. They will pass in a username and a password.
According to the rules that i've read, the "/" in a URI must be used to indicate a hierarchical relationship.
So I'm wondering if this type of a URI follows the rules, and is intuitive enough:
POST http://myregistrations.com/users/user/{user_id},{password}
GET http://myregistrations.com/users/user/{user_id}
PUT http://myregistrations.com/users/user/{user_id},{password}
DELETE http://myregistrations.com/users/user/{user_id}
or should i remove the "users" part from the URI? In that case, if I want to get "all" users, i could just do the following:
GET http://myregistrations.com/user/
DELETE http://myregistrations.com/user/ ** i might not allow this but just for discussion purposes...
And the rest of the methods would look like this:
POST http://myregistrations.com/user/{user_id},{password}
GET http://myregistrations.com/user/{user_id}
PUT http://myregistrations.com/user/{user_id},{password}
DELETE http://myregistrations.com/user/{user_id}
I don't want to over complicate things... but I also want to make sure I follow conventions.
I am leaning towards the second example, where I don't have "users". Given that each part of the URI should map to an addressable resource, and that I won't be allowing batch updates to accounts, having a concept of "users" seems useless at this time. I might be missing something though.
Maybe I'm just splitting hairs. I've been reading other posts here too about defining REST APIs... but I haven't found anything yet.
Thanks.

You can have both concepts (user and users) with a single API. The URI /users/user seems convoluted to me.
Over-simplified example:
Post one user:
POST /user/{user_id,password}
Post multiple users:
POST /user/[{user_id,password},{user_id,password}]
Get one user:
GET /user/{user_id}
Response: {user_name} or [{user_name}]
Get multiple users:
GET /user/{search_user_name}
Response: [{user_name},{user_name},{user_name}]

Typically plural is how you reference a resource so users in this case and not user. This is what you're routes should look like to follow the REST pattern.
POST http://myregistrations.com/users/ --> The post payload should contain: {user_id},{password}
GET http://myregistrations.com/users/{user_id} --> The user_id is in the URL
PUT http://myregistrations.com/users/{user_id} --> The user_id is in the URL
DELETE http://myregistrations.com/users/{user_id} --> The user_id is in the url

I don't want to over complicate things...
I have bad news for you, you've already overcomplicated things. The REST clients know nothing about the URI structure, because they follow hyperlinks annotated with semantic metadata. The clients check this metadata instead of the URI structure.

Related

Is it a good practice to use 'createModel' in REST?

I'm looking for a best way for implementing an endpoint of REST-full application that will be responsible for creating a new library orders. Let's assume that I have the following resources.
If I want to get all books of a particular author I can use the next endpoint:
HTTP GET
api/books/author/123
If I want to fetch all orders of a particular book I can use the endpoint provided below:
HTTP GET
api/books/456/orders
My question is what will be the most suitable URL and a request model for an endpoint that will create orders?
From my perspective it can be
HTTP POST
api/books/456/orders
And one more question. Is it a good practice in REST to use request models like CreateOrder? If I want to create a REST-full web application can I use the following request model:
class CreateOrder
{
AuthorId: number;
BookId: number;
ClientId: number;
}
Sometimes it makes me confused. Should request models look like our resources or not?
Let's assume that I have the following resources.
Your "resources" look suspiciously like "tables". Resources are closer to (logical) documents about information.
what will be the most suitable URL and a request model for an endpoint that will create orders
For the most part, it doesn't matter what URL you use to create orders. In a hypermedia application (think HTML), I'm going to submit a "form", and the meta data associated with that form are going to describe for the client how to compose a request from the form data.
So the human, or the code, that is manipulating the form doesn't need to know anything about the URL (when is the last time that you looked to see where Google was actually sending your search?)
As far as general purpose web components are concerned, the URL/URI is just an opaque identifier - they don't care what the spelling means.
A thing they do care about is whether the spelling is the same as something that they have cached. One of the consequences of a successful POST /x message is that the cached representation(s) of /x are invalidated.
So if you like, you can think about which cached document should be refreshed when an order is created, and send the request to the identifier for that document.
Should request models look like our resources or not?
It's not necessary. Again, think about the web -- what would the representation of create order look like if you were POSTing form data?
clientId=1&bookId=2
or maybe
bookId=2&copies=3
If the "who is creating an order" is answered using the authorization headers.
In our HTTP requests and responses, we are fundamentally sending message representations - sequences of bytes that conform to some schema. There's no particular reason that those sequences of bytes must, or must not, be the same as those we use elsewhere in the implementation.
Your end-point does not need to always start with /books. You can introduce another end-point /orders for creating or getting orders. So , to create an order , you can :
HTTP POST
api/orders
And does the 'request model' that you mean is the HTTP request body structure ? If yes, it does not need to be 100% match with your back-end persisted/domain model. Just include enough parameters that the server needs to know in order to create an order. (e.g. Include bookId rather than the whole book object etc.)
BTW , to get all books for a particular author , it is more common to use query parameter such as :
HTTP GET
api/books?authorId=123
What you are doing is not REST, it is CRUD over HTTP. REST does not care about your URI structures and resources are very far from database tables. If CRUD is all you need, then download a CRUD generator library https://github.com/search?q=crud+generator&type=Repositories, which will generate all the upper and you won't need to write it manually.

What is the best way to design REST URI for nested resources

Say there are users having multiple authorizations having multiple permissions.
Retrieving all authorizations for the specified user (without permissions) could be:
GET users/{id}/authorizations
The "normal" case is to not embed permissions with authorizations for performance reason.
There are cases when authorizations must be returned with their respective permissions for that user.
Suggested solutions are:
GET users/{id}/authorizations/permissions // does not seem clear
GET users/{id}/authorizations?permissions=true // with query string
GET users/{id}/authorizationswithpermissions // new resource
Now what is the best way to design the REST URI in that case?
Your ideas
There are cases when authorizations must be returned with their respective permissions for that user.
GET users/{id}/authorizations/permissions
It is not a good idea to nest collection resource like this. Does it mean "give me all permissions of all authorizations of user id"? This is unclear. Don't do this.
GET users/{id}/authorizations?permissions=true
A query is normally used to query, search, or filter on a collection resource. This URL woud return all authorizations for user id for which permissions is true. But what does that man? This is unclear. Don't do this.
GET users/{id}/authorizationswithpermissions
Authorizations are authorizations. Their representation should not depend on the URI. Don't do this.
Content Negotiation
The solution to your problem is to use content negotiation. You only use one URL:
GET users/{id}/authorizations
This means: Give me a list of all authorizations of user id.
Now if you want to get this list without permissions, you could use the HTTP header
Accepts: application/vnd.mycompany.authorizations+xml
Let's digest this.
application: the first part of the normal MIME type application/xml
vnd: a prefix to define your own type
mycompany.authorizations: your type
xml: the second part of application/xml
Now if you want to get this list with permissions, you could use the HTTP header
Accepts: application/vnd.mycompany.authorizations.permissions+xml
Note that me now use vnd.mycompany.authorizations.permissions. The server should return the authorizatons including the permissions. Only the representations are different, not the resources.
Personnally I can't find any problem with both two last suggestions:
GET users/{id}/authorizations?permissions=true // with query string
GET users/{id}/authorizationswithpermissions // new resource
Except I would change them as follow to be more relevant:
GET users/{id}/authorizations?withPermissions=true // with query string
GET users/{id}/authorizationsANDpermissions // new resource
The first one seems to be quite confusing but your RESTful entities should be documented whatever notation you will opt for.

Posting IDs to REST API

I am designing a REST API for inserting a record to the "solutions" table. A "solution" has a solverID, problemID. I have two different designs in mind:
POST /solutions
and passing the solverID and problemID in JSON with the content of the solution. Or putting the solverID and problemID in the URI:
POST /users/:solver_id/problems/:problem_id/solutions
Which design is better?
It's a good practice to define your resources in a consistent hierarchy, so that they are easily understandable and predictable.
Let's say this is the URL to retrieve a question -
GET /users/{solverId}/problems/{problemId}
It clearly conveys that the problem belongs to the {solverId}.
The following URL would clearly show that the we are retrieving all solutions for problems solved by {solverId}
GET /users/{solverId}/problems/{problemId}/solutions
To create a new solution for the {problemId}, you would do a post on
POST /users/{solverId}/problems/{problemId}/solutions
To retrieve a particular solution you would do a get on
GET /users/{solverId}/problems/{problemId}/solutions/{solutionId}
When to use Ids in path vs query ?
If an ID is definitely required to identify a resource, use it in the path. In the above scenario, since all three Ids are required to uniquely identify a solution, all of them should be in the path.
Let's say you want to retrieve a solution that was given in a particular date range, you would use the following
GET /users/{solverId}/problems/{problemId}/solutions?startDate={}&endDate={}
Here startDate and endDate cannot uniquely identify a resource, they are just parameters that are being used to filter the results.
Go with the first one. I would keep your urls as clean and simple as you can. Here are some other examples off the top my head. Not sure on your entire structure.
POST /solutions
GET /solutions?solverid=123 //query solutions by user
GET /users/555/problems // problems for a given user
GET /users/555/solutions // solutions for a given user
GET /problems/987/solutions // solutions for a given problem
I came up with a scheme: including user ID in the route only when authentication is not needed for the route, otherwise, the user ID can be figured out from the authentication information, and the above route becomes:
POST /problems/:problem_id/solutions

REST API Design links between collections of resources

I have been pondering the correct method of defining resource collections which have interdependence.
For instance, lets consider "documents" and "comments" which are independently accessible via the URI's:
/documents/{doc-uri}
/comments/{comment-id}
However, we typically want the collection of comments related to a specific document. Which creates a design question around how this should be archetected.
I can see a few main options:
1.) Supply an collection uri after the document uri for comments
GET /documents/{doc-uri}/comments/
2.) Provide a parameter to the comments collection to select by document
GET /comments/{comment-id}?related-doc={doc-uri}
3.) Use content negotiation to request the related comments be returned via the Accept header.
// Get all the comments for a document
GET /documents/{doc-uri} Accept: application/vnd.comments+xml
// Create a new comment
POST /documents/{doc-uri} Content-Type: application/vnd.comment+xml <comment>...</comment>
Method 1 has the advantage of automatically putting the comments in context of the document. Which is also nice when creating,updating and deleting comments using POST/PUT. However it does not provide global access to comments outside the context of a document. So if we wanted to do a search over all comments in the system we would need method #2.
Method 2 offers many of the same benefits as #1, however creating a comment without the context of a document makes no sense. Since comments must explicitly be related to a document.
Method 3 is interesting from a GET and POST/create perspective, but gets kinda hairy with update and delete.
I can see pro's and con's to all these methods so I am looking for some more guidance from someone who may have approached and solved this issue before.
I am considering doing both methods 1 & 2, thus I can provide all the functionality needed, but I am concerned I may be over-complicating/duplicating functionality.
REST API must be hypermedia-driven. See Hypermedia as the Engine of Application State (HATEOAS) constraint. So, don't waste your time on URLPatterns, because they are not RESTful. URLPattern implicates tight-coupling between a client and a server; simply, the client must be aware of how URLs look like and has an ability to construct them.
Consider this REST design for your use-case:
The representation of a document contains a link where the client can POST comments or with using of GET get all comments on the document. e.g.
{
...
"comments" : {
"href": ".. url ..",
"rel": ["create-new-comment", "list-comments"]
}
}
A client just takes this URL and performs GET or POST method on the URL; without a knowledge how the URL is, looks like.
See also this post:
http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven
The combination of methods 1 and 2 looks good, as you say in method 2, don't have too much sense create comments without a document context since a parent child relationship exists between both, if you delete a document is acceptable to delete all his comments also, you can make your/comments/ uri a read-only resource in order to avoid his creation without a document.
As filip26 says rest apis should be hypermedia driven but that not means that the url patterns aren't important, you could have a resource with one uri or many, if your resources have multiple uris is easier for clients to find them, the downside is that could be confusing because some clients use one uri instead of another, so you can use a canonical uri for a resource, when a client access a resource throught this canonical uri you can send back a 200 OK, when a client request one of the others uri you can send back a 303 "See also" along with the canonical uri.`

Correct RESTful URL convention for application service calls?

I've seen tons of examples on how to structure URL's for basic CRUD operations but seen very little when talking about more Command-like operations, or application service calls.
For example, let's say in my application service I have a call like RemoveOldOrders(int customerId) that would remove any order from the system that is over 2 years old for a customer with id "customerId". What would the URL look like on my restful service? What would the payload of the call look like? What HTTP method (POST?) would I use?
My thought is it would be something like this:
/Customer/1/RemoveOldOrders as a POST, with an empty body (as the customerID would come from the url).
Are there good guidelines on something like this?
Update: I feel like I need to clarify my question a bit in lieu of the comment about a possible duplicate post (yes, that post is asking essentially the same thing but I don't really feel the question was answered well).
What if I want to perform an operation against a resource but that operation doesn't fit into the standard HTTP verbs?
Another example: my application is hooked into an ESB and there needs to be a way to force a projection of my resource onto the ESB for processing? In my current SOAP-based web service I'd have a method like:
ExportCustomer(int customerId)
Now, in the case of a RESTful service, how could I represent this action in a uri? Option 1 from Brian Kelly's answer seems like the most logical, something like:
POST http://someapp/api/customer/1/export
or would:
POST http://someapi/api/customer/export/1
be better?
Anytime you want to model verbs like "remove", you should think of DELETE. Similarly, for "create" think POST (and/or maybe PUT), for "read" think GET and for "update" think PUT (or maybe PATCH).
So for your example of "remove old orders", you should definitely use DELETE. Now your only remaining challenge is how to identify the orders that should be removed. Once you figure that out, the URI scheme will fall into place with it.
Here are some options:
DELETE http://your-api.com/old-orders
Here, the meaning and range of old-orders will be determined by the server receiving this request. This frees the client from having to do so, but removes their ability to change that range.
GET http://your-api.com/order-query?days-older-than=730
This returns a Location URI of http://your-api.com/order-query-result/{some ID} that represents the set of old appointments. Then you can simply issue a DELETE on that URI to purge the old records in one fell swoop.
Instead of forcing the client to remember to issue deletion commands of this type, offer some kind of configuration resource that can be manipulated via your API to set some field like purgeRecordsOlderThanDays=730, and just let the server do it automatically for you in a cron-like fashion. That would be my preferred approach.
For exporting, then you need to remove the "export" verb and replace it with an ESB representation of the resource: -
GET http://someapp/customer/{id}
The response includes a link to export: GET http://someapp/customer/{id}/ESB
Getting on the export link returns the ESB representation (with appropriate content type)
For example, let's say in my application service I have a call like
RemoveOldOrders(int customerId) that would remove any order from the
system that is over 2 years old for a customer with id "customerId".
What would the URL look like on my restful service? What would the
payload of the call look like? What HTTP method (POST?) would I use?
RemoveOldOrders(int customerId)
DELETE /oldOrders {customerId: id}
DELETE /customer/{id}/orders?old=true
etc...
You should read more about uniform interface / resource identifiers and the HTTP method specification.
The URL does not really matters. What matters that you should have resource with resource identifiers (URLs) and you have to manipulate them by using an uniform (standard) interface, like the call of HTTP methods.