I have a REST service that serves Invoice functionality, for example I can create, update and delete an invoice via the REST service.
However I now need to have functionality to split an invoice into several new invoices, i.e. the method needs to create x invoices based on one invoice, and then delete the original invoice in one transaction.
I also need a merge method that does the opposite, i.e. multiple invoices merged into one.
How do I create such architect the RESTful way?
We had a similar issue where we wanted to merge 2 resources. After a long debate we decided that a consumer would POST a merge request resource which contained the 2 resources to be merged. Then after looking at it we decided that there was no need for both the complete source and target resource and instead a POST of just the unique identifier was sufficient. We didn't make the merge request with just the 2 ID's come in the body. It was easier to represent in a URL so that's what we did. The response from the POSTing of a merge request is the merged resource.
I guess I'm not a REST guru enough to tell you this was a good strategy or not, but for us it was a simple solution so we went with it.
When you say that want to implement this functionality in "one transaction" I assume you have already determined that you should combine generation of the new invoices and deletion of the old one, into one API call; which is the correct approach. With web services you do want to reduce chatter and there is probably some business logic on how this functionality will generate the new invoices and delete the old one. So I am assuming when you ask how to architect this in a RESTful way you are wondering which HTTP verb to use (i.e. GET, POST, PUT or DELETE) for this new API method. Usually these verbs map to CRUD type operations in the following manner:
Create -> POST
Read -> GET
Update -> PUT
Delete -> DELETE
So which verb to use when your function both creates and deletes records. A general rule with REST API's is if there is not a clear mapping to CRUD then use POST if there is a change to the server state and a GET if you are just returning information that does not change the server state. So in this case I would go with a POST.
If you are looking for additional guidance on architecting this please be more specific in what you are looking for and I will try to help.
I would do something like,
POST /InvoiceSplitter?sourceInvoiceId=99
and
POST /InvoiceMerger?sourceInvoiceIds=101,87,23,45
Related
I am using rest api. I want to delete all pushes, but I don't know how to write the query.
I know how to delete a specific push.
delete $apiUrl/pushes/$pushId
What I want is to delete all pushes for that user.
$apiUrl/pushes?owner=$ownerId/ ???
thank you
I would recommend 2 approaches
Do it in a non-rest way by sending a custom JSON object containing the ID's marked for deletion. Reference
Mozilla Storage Service SyncStorage API - to delete multiple records using REST. Reference
REST isn't the only way to solve any problem. “REST” is just an architectural style and you don't have to adhere to it (but you lose certain benefits of the internet if you don't). I suggest you look down this list of HTTP API architectures and pick the one that suits you.
So, I'm building a RESTful API, that's like a Parking system, it have ParkingLots and Cars that enter or leave ParkingLots, at this moment, my endpoints looks like this.
POST '/parking-lots' // To create a ParkingLot
POST '/cars' // To create a Car
But, how to name an endpoint that has EnterParkingLot or LeaveParkingLot feature following REST best pratices? I didn't found an article or blog post that answer this question so far.
But, how to name an endpoint that has EnterParkingLot or LeaveParkingLot feature following REST best pratices? I didn't found an article or blog post that answer this question so far.
The key abstraction of information in REST is a resource. Resources are generalizations of documents, not endpoints.
Useful work is a side effect of editing documents (Webber, 2011).
If you are having trouble figuring out the URI, that probably means that you haven't been thinking enough about the documents (aka you don't yet have a clear understanding of your "resource model").
One idea that can sometimes help is to think about a client with cached documents. When they send you one of these messages, which document in the cache is the most important one to invalidate?
In REST, it is normal (not necessarily common) to have a single resource handle many different kinds of edits. For instance, we might submit an EnterParkingLot form, that would update a parking lot resource, and then later submit a LeaveParkingLot form that updates the same parking lot resource (with the code on the server parsing the requests to distinguish the different kinds of edits).
But it would also be fine to add a "parking ticket" resource to your resource model, with a different ticket tracking the arrival and departure of each car.
Domain experts are typically good at telling you what the documents are, and what names make sense.
I would do it like:
POST '/parking-lot/$n/enter'
POST '/parking-lot/$n/leave'
So the general pattern for a RESTful API is to return a single object with embedded links you can use to retrieve related objects. But sometimes for convenience you want to pull back a whole chunk of the object graph at once.
For instance, let's say you have a store application with customers, orders, and returns. You want to display the personal information, all orders, and all returns, together, for customer ID 12345. (Presumably there's good reasons for not always returning orders and returns with customer personal information.)
The purely RESTful way to do this is something like:
GET /
returns a list of link templates, including one to query for customers
GET /customers/12345 (based on link template from /)
returns customer personal information
returns links to get this customer's orders and returns
GET /orders?customerId=12345 (from /customers/12345 response)
gets the orders for customer 12345
GET /returns?customerId=12345 (from /customers/12345 response)
gets the returns for customer 12345
But it'd be nice, once you have the customers URI, to be able to pull this all back in one query. Is there a best practice for this sort of convenience query, where you want to transclude some or all of the links instead of making multiple requests? I'm thinking something like:
GET /customers/12345?include=orders,returns
but if there's a way people are doing this out there I'd rather not just make something up.
(FWIW, I'm not building a store, so let's not quibble about whether these are the right objects for the model, or how you're going to drill down to the actual products, or whatever.)
Updated to add: It looks like in HAL speak these are called 'embedded resources', but in the examples shown, there doesn't seem to be any way to choose which resources to embed. I found one blog post suggesting something like what I described above, using embed as the query parameter:
GET /ticket/12?embed=customer.name,assigned_user
Is this a standard or semi-standard practice, or just something one blogger made up?
Being that the semantics of these types of parameters would have to be documented for each link relation that supported them and that this is more-or-less something you'd have to code to, I don't know that there's anything to gain by having a a standard way of expressing this. The URL structure is more likely to be driven by what's easiest or most prudent for the server to return rather than any particular standard or best practice.
That said, if you're looking for inspiration, you could check out what OData is doing with the $expand parameter and model your link relation from that. Keep in mind that you should still clearly define the contract of your relation, otherwise client programmers may see an OData-like convention and assume (wrongly) that your app is fully OData compliant and will behave like one.
So this question has been asked numerous times in SO and elsewhere.
On SO this is probably the question with the most comprehensive answers and comments.
REST, HTTP DELETE and parameters
In my scenario I want to add information to a delete request, not to identify the resource, but as meta data. Specifically, just some additional data the delete operation should record in a log.
Based on everything I've read putting any parameters as part of the DELETE request goes against best practices. What would be the best practice in this scenario?
Metadata by its very name is data about a Resource. Using HTTP, such data belongs into HTTP headers.
Since the X- prefix is deprecated, just choose sensible header names for your metadata.
Im working on a web service that i want to be RESTful. I know about the CRUD way of doing things, but I have a few things that im not completly clear with. So this is the case:
I have a tracking service that collects some data in the browser (client) and then sends it off to the tracking server. There are 2 cases, one where the profile exists and one where it does not. Finally the service returns some elements that has to be injected to the DOM.
So basically i need 2 web services:
http://mydomain.tld/profiles/
http://mydomain.tld/elements/
Question 1:
Right now im only using GET, but im rewriting the server to support CRUD. So in that case i have to use POST if the profile does not exist. Something like http://mydomain.tld/profiles/ and then POST payload have the information to save. If the profile is existing i use PUT and http://mydomain.tld/profiles// and payload of PUT has data to save. All good, but problem is that as far as i understand, xmlhttp does not support PUT. Now is it ok to use POST even though its an update?
Question 2:
As said my service returns some elements to be injected into the DOM, when a track is made. Logically, to keep it RESTful, i guess that i would have to use POST/PUT to update the profile and then GET to get the elements to inject. But to save bandwidth and resources on the serverside, it makes more sense to return the elements with the POST/PUT to profiles, even though its a different resource. What are your take on this?
BR/Sune
EDIT:
Question 3:
In some cases i only want to update the profile and NOT receive back elements. Could i still use same resource and then using a payload parameter to specify if i want elements, e.g. "dont_receive_elements:true"
On question #1, are you sure that xmlhttp does not support "put"? I just ran http://www.mnot.net/javascript/xmlhttprequest/ on three browsers (Chrome, Firefox, IE) and according to the output, "put" was successful on all browsers. Following the information on http://www.slideshare.net/apigee/rest-design-webinar (and I highly recommend checking out the many Apigee videos and slideshows on restful API), "put" is recommended for the use case you mention.
But you may be able to avoid this issue entirely by thinking a little differently about your data. Is it possible to consider that you have a profile and that for each profile you have 0 or more sets of payload information? In this model the two cases are:
1. No profile exists, create profile with a POST on .../profiles/ Then add elements/tracking data with posts to .../profile/123/tracks/ (or .../profile/123/elements/)
2. Profile exists, just add the elements/tracking data
(Sorry without understanding your model in detail, it is hard to be very precise).
As for question #2 - going with a data model where a profile has 0 or more elements, you could update the profile (adding the necessary elements) and then return the updated profile (and its full graph of elements), saving you any additional gets.
More generally on question #2, as the developer of the API you have a fair amount of freedom in the REST world - if you are focused on making it easy and obvious for the consumers of your API then you are probably fine.
Bottom line: Check out www.apigee.com - they know much more than I.
#Richard - thanks alot for your links and feedback. The solution i came down to is to make the API simple and clean as you suggest in your comment, having seperate calls to each resouce.
Then to be able to save bandwidth and keep performance up, I made a "non-official" function in the API that works like a proxy internally and are called with a single GET, that updates a profile and returns an element. This, i know, is not very restful etc, but it handles my situation and is not part of the official API. The reason i need it to support GET for this i need to call it from javascript and cross domain.
I guess i could have solved the cross domain by using JSONP, but i would still have to make the API "unclean" :)