RESTful Resource Naming for POST - rest

Giving this naming convention:
http://www.restapitutorial.com/lessons/restfulresourcenaming.html
for the POST (insert) the url of the resource should follow this path/logic:
http://www.example.com/products/X123
{
"color":"something"
}
Is the following path conceptually wrong? and why is it correct/wrong?
http://www.example.com/products
{
"id":"X123"
"color":"something"
}
the ID is generated externally
Also for the PUT is it ok to apply the same logic? (the id naturally must not be changed but used only as ref)
Thank you

For POST (which is usually used to create a new item in collection) use the following:
http://www.example.com/products
{
"color":"something"
}
if you have a requirement where client generated the id, the it is
http://www.example.com/products
{
"id": "abc123"
"color":"something"
}
EDIT:
For PUT it should be:
http://www.example.com/products/abc123
{
"color":"something else"
}

In my opinion your scenario suits best for PUT method, I would always prefer to include id in url if I only know it - that would be the clearest solution for others.
Second part about including id in body, there is nice answer about that: https://stackoverflow.com/a/28108844/3301697
The only thing I would change in this answer is to include id to every PUT request, if you know it, why hide it.

Related

REST URL for transforming one resource into another resource

I am struggling to come with proper REST URL for converting one resource into another. The API method does not do any CRUD operations but instead transform/convert one resource into another type of resource.
I have 2 resources Workunit and Document. I have 3 operations on these two resources
1> trasform Workunit into Document
2> sync Workunit into Document (different logic than transform)
3> transform Document into Workunit
and i have the following urls
[POST] api/v1/workunits/transform
[POST] api/v1/workunits/sync
[POST] api/v1/documents/transform
problem here is action is a part of REST URL
any suggestions?
problem here is action is a part of REST URL
That's not a problem - clients don't depend on the URL for semantics, so you can use any spelling you like; api/v1/4dc233fa-c77c-49d7-b7d6-296ffeb89612 is perfectly satisfactory.
It's analogous to having a verb as a variable name -- it may not be in keeping with your local coding standards, but the compiler doesn't care. So too is it with your URL and the general purpose components that use it.
Choosing a good identifier is like choosing a good name; it requires having a clear understanding of what the thing is. In the case of URI/URL, the thing being identified is a resource, which is to say something that is described by a document. GET/POST/PUT/DELETE and so on are all requests that we do something interesting with the underlying document.
So the usual pattern might be to POST a transform message to the workunit resource, or to POST a transform message to the Document resource, or to POST a sync message to the workunit resource.
Hmm, that last one sounds backwards; if the workunit is unchanged, and the Document is changed by the sync, then you would probably send a sync message to the Document resource.
So if I have /api/v1/documents/1, and I need to sync it, then I would normally use POST /api/v1/documents/1, with the sync semantics described in the message body (on the web, that would usually be an application/x-www-form-urlencoded representation of the sync message).
But it could just as easily be a message that says "Sync documents/1 with workitem/2" that I POST to the todo list for the synchronizer.
We are just putting documents politely into the server's in-tray, so that it can do useful work. The in-tray can have whatever label you want.
It is fine with given situation.
Nevertheless, if I am getting you right it may be a good idea to create two different controllers.
It's up to you but think of changing structure a little bit:
Separate the logic of Transformation and Sync into two different controllers, so you can avoid URL issue.
TransformationController
[Route("api/v1/transformation-controller/")]
TransformationController : ControllerBase
{
[HttpPost("workunits")]
public Task<Response> TransformWorkunits()
{
//logic
}
[HttpPost("documents")]
public Task<Response> TransformDocuments()
{
//logic
}
}
SynchronizationController
[Route("api/v1/synchronization-controller/")]
TransformationController : ControllerBase
{
[HttpPost("workunits")]
public Task<Response> SyncWorkunits()
{
//logic
}
}
So the URLs will be:
[POST] api/v1/transformation-controller/workunits
[POST] api/v1/synchronization-controller/workunits
[POST] api/v1/transformation-controller/documents
So this is a way to avoid verbs and fit REST rules.
If there will be more objects to transform/sync from and into, then you'll have to improve this approach.

REST: Is it considered restful if API sends back two type of response?

We have stock website and we help buyers connect with the sellers. We are creating API to let buyers push their contact details and get back the seller details. This is transaction and get logged in our database. We have created following API:
The request is POST, the URL looks like:
/api/leads
The request body looks like:
{
"buyermobile": "9999999999",
"stockid": "123"
}
The response looks like:
{
"sellermobile" : "8888888888",
"selleraddress": "123 avenue park"
}
We have a new requirement, i.e. we need to send back PDF URL (instead of "sellermobile" & "selleraddress"). This PDF URL would contain the seller details in case it comes from one of our client.
We have modified the same API, now the request body looks like:
{
"buyermobile": "9999999999",
"stockid": "123",
"ispdf": true
}
The response looks like:
{
"sellerdetailspdf" : "https://example.com/sellerdetails-1.pdf",
}
Is it RESTFUL to do this? OR we should create separate API for getting response as PDF?
I wouldn't approach it this way. What happens when you need to add XLS? Do you add "isxls" to the request too?
Things I'd consider:
Use a mime type for content negotiation. Post the same request, and specify in the Accept header what you expect back - JSON, PDF, etc. You're then actually getting the report instead of a link to the report, which may or may not be better.
- or -
Include a link in the typical lead response.
{
"sellermobile" : "8888888888",
"selleraddress": "123 avenue park",
"_links": {
"seller-details-pdf": "https://example.com/sellerdetails-1.pdf"
}
}
- or -
Support a query parameter that specifies the type in the response.
- or -
Have a single property that specifies the type in the response, rather than a boolean. Much cleaner to extend when you add new response types.
The first two options have the bonus that you don't require clients to handle multiple response types to a single request. That's not forbidden by any spec, but it's annoying for clients. Try not to annoy the people who you want to pay you. :)
Again the implementation looks good to me, however you could potentially look at breaking the return of the PDF URL to another endpoint maybe something like api/lead/pdf that way your request body is the same for api/lead and all subsequent endpoints under /lead. Allowing your routes and other code to handle small portioned tasks instead of having a route that handles multiple flags and multiple code routes.
That looks good to me - the same type of input should give the same type of response but in your case you have two different types of input - one with the "ispdf" flag and one without. So it's consistent to responds with two different types of response, one with the PDF link and one without.
That's still something you'll want to document but basically it's a correct implementation.

How to design calculation API in RESTFul way?

I'm trying to design an API to calculate a result based on inputs.
Real business:
The API compares two securities portfolios (source and target) and return the orders, the consumer gets the orders, so he/she can then places those orders to adjust portfolio from source to target.
If this is hard to be understood, then here's a similar scenario:
The API compare two text, then return the difference of the 2 texts.
It is a little bit different from the classic CRUD, because the inputs and output are different resources
My first thought is like this:
POST /api/difference
{
'source': { ... },
'target': { ... }
}
But, it will be conflict with the classic payload:
POST /api/difference
{
'lineNumber': ...,
'isAdded': ...
}
Questions:
Should I use a media-type to distinguish the the input payloads? What a 'resource' should be in this case?
What should the API look like if I also want to place the orders (or apply the text diff) in the same time when the API is called?
Iam not sure whether I understand your problem correctly, but in general it
depends on whether the resources are already persisted in the system. In case
both resources are already available in the system I would simply build an URI
like /portfolio/{source_id}/difference/{target_id} which returns the diff
result. If only the source exists I would probably use something like:
POST /portfolio/{source_id}/difference
{target}
If both resources are not available I would probably consider to first persist
such a resource and make then the comparison.
If I understood you correctly, there already exists the resource POST /api/difference and hence you are looking to change MIME type. Instead, why don't you go with the first approach and change the resource name? For example,
POST /api/compare
{
'source': { ... },
'target': { ... }
}

JAX-RS passing parameters to a PUT request

I've heard that in REST world, POST is recommended to create an entry, while PUT is recommended to update an entry.
First, I'd like a confirmation of this statement.
Then, using this assumptions, let's say I have a #POST method to create a user and a #PUT method to update a user (with a #QueryParam to pass the user ID).
What is the correct way to pass parameters to POST and PUT?
Is #FormParam appropriate for #PUT? Or should I pass a JSON in the body?
Should I pass parameters the same way for both #POST and #PUT or a different way?
Or should I use POST for both?
Edit: This question initially showed an example that did not work for me, but it was because my testing tool was doing it wrong. It works with POSTMAN now.
Yes, with REST, you typically use the following:
The method POST of the element list resource to add an element
The method PUT of the element resource to completely update an element
The method PATCH of the element resource to partially update an element
Since what you must send corresponds to the state of the resource, you have to provide it within the request body.
The two bodies (for adding and updating) is similar but there are some differences. For example, if you expect the RESTful service to autogenerate some fields, you don't have to provide corresponding ones.
Here are sample requests:
POST /contacts
{
"lastName": "my last name",
"firstName": "my first name",
}
(corresponding response status code: 201 - Created)
PUT /contacts/contactid
{
"lastName": "my last name",
"firstName": "my first name",
}
(corresponding response status code: 204 - No content)
You can notice that JSON isn't the only format you can use. XML, YAML, and so on could also be used.
I think that the following link could give you some hints:
Designing a Web API - https://templth.wordpress.com/2014/12/15/designing-a-web-api/
Hope it helps you,
Thierry

REST Url ID Placement for Resources with Collections

Is this a good structure for REST URLs?
Assuming:
GET /account <- get list of accounts
GET /account/1234 <- get account 1234
etc.
If the account resource has a collection that I want to interface, is this a good idea?
GET /account/1234/note <- get notes for account 1234
POST /account/1234/note <- add note to account 1234
DELETE /account/1234/note/321 <- delete note 321 on account 1234
Especially that last one gives me pause; typically I wouldn't require both the entity ID and the parent ID when deleting.
Or maybe something like this would be better?
GET /account-note/1234 <- get notes for account 1234
POST /account-note/1234 <- add note to account 1234
DELETE /account-note/321 <- delete note 321 on account 1234 (b/c note 321 is on account 1234)
But then I'd end up with a pretty shallow URL set.
Thanks
There's nothing wrong with your first api. In large part, the idea of the RESTful interface is to go with the natural tree structure of the web, and your first approach is in keeping with that. It's also going to be a structure that does the API's job of abstracting away implicit constraints of your datastore, because the second approach implicitly assumes that the id of note is globally unique. This may be true now, and will probably remain true, but it's also exactly the kind of bug that suddenly appears with disastrous consequences when, down the line, some kind of major db change happens.
I'd go with your first scheme. It's a familiar rest pattern, it's intuitive, and it's not going to blow up in a weird way down the line. Also, in response to #Corwin01 minimize the query params--they're not so RESTful.
I referenced this question in my comments on another question and between the feedback I got there and my own research this is what I've come up with.
Firstly, the question is sort of flawed. RESTful APIs, or to use the perferable term Hypermedia APIs should include the urls of related actions so that the interface is discoverable and changes won't break existing clients, therefore the exact structure has significantly less importance than I was placing on it, these can be changed later.
Secondly, the note in the example will be retrieved as part of an account query, maybe something like this:
<account>
...
<notes>
<note>
...
<link href="/account-note/123" rel="note">
</note>
</notes>
</account>
The client will never be assembling urls to the account on their own, the client will use the link provided. Since the note ID is globally unique in this case, there is no need to include the key twice. Hence the answer to the question is no, the first example is not a good REST url structure, the second one is better. (Although still maybe not the best...)
Mind you, my experience is with JAX-RS and Jersey, so I'm not sure what the exact differences are.
However, this is what I would do:
#GET
#Path ("/account/note/{id}")
public void displayNotes(#PathParam ("accountId") String accountId)
{
//do stuff
}
#POST
#Path ("/account/note")
public void addNote(#FormParam ("accountId") String accountId)
{
//do stuff
}
#POST
#Path ("/account/note/delete")
public void deleteNote(#FormParam ("accountId") String accountId, #FormParam ("noteId") String noteId)
{
//do stuff
}
This way, you don't have cluttered and confusing URLs that the user doesn't need to see anyways, especially if the user tries to navigate there on their own. Which is ok for displaying the accounts, but would confuse them for the URLs that POST, since they would get a 404 and not understand why.
Keep it simple, and just user #FormParams since the user doesn't need to see that anyways.