Is it considered RESTful to do additional things in POST api apart from creating a resource? - rest

We have customer registration API that accepts name, email and mobile and generates customerId i.e.:
{
"name": "john",
"email": "john#gmail.com",
"mobile": "+134325325"
}
We create customer record for this API hit. The customer can be created from several clients and forms. We have got a new requirement that if we get this "customer creation" record from particular form, we need to send this information (name,email,mobile)+(customerId) to some third party API as well.
I believe as per resful pratise this API should only create "customer" and not do such extra things which would only be valid for certain clients/forms.
Which is the best alternative in this case:
Create new API for this new requirement: This new API would first create customer and then send it to third party API. This fulfils our requirement here but customer creation logic is now at two APIs.
Use existing "customer registration API" by adding a new flag: We would set this flag from these forms where we have this new requirement to send data to the third party as well. We would first create customer and if flag is set, we would send this data to the third party APIs as well. But is this approach RESTful?
From these forms where we need to send data to third party API, first send request to "customer registration API" and get customerId back and then send these details to third party API: This would be slow as we will have to wait for customerId on the client side.

POST is often used as a catch-all for actions that don't fit into a proper REST API otherwise. Bulk create, update or delete, merging records, logging in, copy, etc, are all common examples. But anything else you need to do that doesn't correspond to PUT, GET or DELETE can generally be overloaded with POST. Just make sure you use a distinct URL for each use of POST.
I.e. POST /foo should create a foo, and POST /bulk_delete should delete several fooa, based on query or form parameters.

I don't feel like separate resource would fit here. Let's imagine we are discussing not API endpoints design but simple class method createCustomer. Exposing a new endpoint is the same as creating a new overload method createCustomerSpecific. This is RPC-style - the number of methods will keep growing.
What REST as a style is suggesting is to use the same method, but encapsulate all the data required to create resource in the input object.
For me your case should be driven by something like repository factory: your application logics knows what repository to call - simple CustomerRepository or CustomerWithNotificationRepository.

I hope that the owner of this question may not need an answer for this. But here are my thoughts.
My assumptions are given below,
You have CustomerService class which contains the methods to perform CRUD operations with Customer Data.
You have an endpoint /api/customers(Method: POST) which will call the CustomerService.create() method to create a customer detail in DB.
With your second approach(Slight modification):
I prefer not to create an another endpoint since we are not doing anything differently apart from calling the 3rd party API. Hence the request JSON would be modified as like below to hold the additional data from client side.
{
"clientData": {
"notify": "true"
},
"customer": {
"name": "john",
"email": "john#gmail.com",
"mobile": "+134325325"
}
}
Post creation of the customer, We have to check whether the notify field is true or not. If its, then the 3rd party API would be called with the customer details for additional processing.

Related

Should an element in a REST API return its own ID?

What is the benefit of returning the ID of the element? Isn't it already part of the url and therefore known? I am not talking about using the REST API with HAL or something similiar.
api/employees/1
{
"Id" : 1
"Name" : "Joe Bloggs",
"Department" : "IT"
}
api/employees/1
{
"Name" : "Joe Bloggs",
"Department" : "IT"
}
I guess it makes sense to add more information regarding the usage of the API:
The API in question is a public API in a closed network (not internet). We provide sample clients but our customer write their own client for our API. The ID of an element is no sensitive information. The data is not about exmployees (as stated in the question) but about asset management.
The reason I am asking is, that customers are complaining that if they use some kind of middleware (whatever this is), they only receive the content of a element but do not have access to the url of the element (how?).
If you write your own client, is there any kind of situation where you can't get the ID based on the URL? Should we add the ID for people, who somehow do not have access to the url?
What is the client actually using the ID for? Presenting a product ID isn't that wrong IMO but does a user has to know the ID you store the user entity at in the DB when she uses an email to authenticate with the API anyways? So to answer the actual question: it depends. If the client, however, is using it to construct the next URI to invoke I strongly recommend to return links with meaningful relation names instead as this helps to decouple the client from the API as the client does not have to have a-priori knowledge of the API itself.
Depending on the resource it might not be benefitial to have an ascending ID as this might favor guessing attacks and also may lead to strange situation if you remove an item in the middle of the collection. Are the IDs of the subsequent items updated? Is a gap exposed between items? Usually UUIDs or the like are a much safer way to expose such information.
One further aspect to consider is that clients in an ideal REST environment should not interpret URIs itself but use the relation name the URI was returned for instead to determine whether to invoke that URI or not. A client which extracts an ID from an URI most likely has some a-priori knowledge of the API and is thus thighly coupled to that API and will with a certainty break if the API is ever going to be changed.
With that being said, there is the concept of URI patterns which should help a client in extracting things like IDs and names from URIs. Personally I'm not that keen on such things as they promote a misleading approach to the application of REST in an API design.
If you write your own client, is there any kind of situation where you can't get the ID based on the URL? Should we add the ID for people, who somehow do not have access to the url?
Extracting the ID of an URI requires knowledge of the URI structure. If you ever, at some later time, want to change the URI structure for whatever reason all clients that were built around that knowledge will break. URIs shouldn't contain content as the body is actually there for. As the ID seems to be content for some of the client include it in the response body. You are of course free to add some of the information to the URI though you shouldn't require clients on parsing that URI and extract the required information of it.

Rest API: path for accessing derived data

It is not clear to me that if I have a micro service that is in place to provide some derived data how the rest api should be designed for this. For instance :-
If I have a customer and I want to access the customer I would define the API as:
/customer/1234
this would return everything we know about the customer
however if I want to provide a microservice that simply tells me if the customer was previously known to the system with another account number what do I do. I want this logic to be in the microservice but how do I define the API
customer/1234/previouslyKnow
customerPreviouslyKnown/1234
Both don't seem correct. In the first case it implies
customer/1234
could be used to get all the customer information but the microservice doesn't offer this.
Confused!
Adding some extra details for clarification.
I suppose my issue is, I don't really want a massive service which handles everything customer related. It would be better if there were lighter weight services that handles customer orders, customer info, customer history, customer status (live, lost, dead....).
It strikes me all of these would start with
/customer/XXXX
so would all the services be expected to provide a customer object back if only customer/XXXX was given with no extra in the path such as /orders
Also some of the data as mentioned isn't actually persisted anywhere it is derived and I want the logic of this hidden in a service and not in the calling code. So how is this requested and returned.
Doing microservices doesn't mean to have a separate artifact for each method. The rules of coupling and cohesion also apply to the microservices world. So if you can query several data all related to a customer, the related resources should probably belong to the same service.
So your resource would be /customers/{id}/previous-customer-numbers whereas /customers (plural!) is the list of customers, /customers/{id} is a single customer and /customers/{id}/previous-customer-numbers the list of customer numbers the customer previously had.
Try to think in resources, not operations. So returning the list of previously used customer numbers is better than returning just a boolean value. /customer/{id}/previous-accounts would be even better, I think...
Back to topic: If the value of previous-accounts is directly derived from the same data, i.e. you don't need to query a second database, etc. I would even recommend just adding the value to the customer representation:
{
"id": "1234",
"firstName": "John",
"lastName": "Doe",
"previouslyKnown": true,
"previousAccounts": [
{
"id": "987",
...
}
]
}
Whether the data is stored or derived shouldn't matter so the service client to it should not be visible on the boundary.
Adding another resource or even another service is unnecessary complexity and complexity kills you in the long run.
You mention other examples:
customer orders, customer info, customer history, customer status (live, lost, dead....)
Orders is clearly different from customer data so it should reside in a separate service. An order typically also has an order id which is globally unique. So there is the resource /orders/{orderId}. Retrieving orders by customer id is also possible:
/orders;customer={customerId}
which reads give me the list of orders for which the customer is identified by the given customer id.
These parameters which filter a list-like rest resource are called matrix parameters. You can also use a query parameter: /orders?customer={customerId} This is also quite common but a matrix parameter has the advantage that it clearly belongs to a specific part of the URL. Consider the following:
/orders;customer=1234/notifications
This would return the list of notifications belonging to the orders of the customer with the id 1234.
With a query parameter it would look like this:
/orders/notifications?customer=1234
It is not clear from the URL that the orders are filtered and not the notifications.
The drawback is that framework support for matrix parameters is varying. Some support them, some don't.
I'd like matrix parameters best here but a query parameter is OK, too.
Going back to your list:
customer orders, customer info, customer history, customer status (live, lost, dead....)
Customer info and customer status most likely belong to the same service (customer core data or the like) or even the same resource. Customer history can also go there. I would place it there as long as there isn't a reason to think of it separately. Maybe customer history is such a complicated domain (and it surely can be) that it's worth a separate service: /customer-history/{id} or maybe just /customer/{id}.
It's no problem that different services use the same paths for providing different information about one customer. They are different services and they have different endpoints so there is no collision whatsoever. Ideally you even have a DNS alias pointing to the corresponding service:
https://customer-core-data.service.lan/customers/1234
https://customer-history.service.lan/customers/1234
I'm not sure if I really understand your question. However, let me show how you can check if a certain resource exist in your server.
Consider the server provides a URL that locates a certain resource (in this situation, the URL locates a customer with the identifier 1): http://example.org/api/customers/1.
When a client perform a GET request to this URL, the client can expect the following results (there may be other situation, like authentication/authorization problems, but let's keep it simple):
If a customer with the identifier 1 exists, the client is supposed to receive a response with the status code 200 and a representation of the resource (for example, a JSON or XML representing the customer) in the response payload.
If the customer with the identifier 1 do not exist, the client is supposed to receive a response with the status code 404.
To check whether a resource exists or not, the client doesn't need the resource representation (the JSON or XML that represents the customer). What's relevant here is the status code: 200 when the resource exists and 404 when the resource do not exist. Besides GET requests, the URL that locates a customer (http://example.org/api/customers/1) could also handle HEAD requests. The HEAD method is identical to the GET method, but the server won't send the resource representation in HEAD requests. Hence, it's useful to check whether a resource exists or not.
See more details regarding the HEAD method:
4.3.2. HEAD
The HEAD method is identical to GET except that the server MUST NOT
send a message body in the response (i.e., the response terminates at
the end of the header section). The server SHOULD send the same
header fields in response to a HEAD request as it would have sent if
the request had been a GET, except that the payload header fields MAY be omitted. This method can be used for obtaining
metadata about the selected representation without transferring the
representation data and is often used for testing hypertext links for
validity, accessibility, and recent modification. [...]
If the difference between resource and resource representation is not clear, please check this answer.
One thing I want to add to the already great answers is: URLS design doesn't really matter that much if you do REST correctly.
One of the important tenets of REST is that urls are discovered. A client that has the customers's information already, and wants to find out what the "previously known" information, should just be able to discover that url on the main customer resource. If it links from there to the "previously known" information, it doesn't matter if the url is on a different domain, path, or even protocol.
So if you application naturally makes more sense if "previouslyKnown" is on a separate base path, then maybe you should just go for that.

REST Partial update with several fields

Lets say I have a rest service that allows applications to create User object
URI: /users
HTTP Method:POST
{
"firstName":"Edward",
"lastName": "Nygma",
"dob": "01011981",
"email": "en#gc.com",
"phone": "0123456789"
}
On the first POST the User object is created and and the User ID is returned
Lets say there is a second service that allows the user to update the lastName and email fields.
URI: /user/1/last-email
HTTP Method: POST
{
"lastName": "scissorhands",
"email": "ec#bc.com"
}
Let's say for the sake of bandwidth sending the full User object is not an option for this update call.
Is this the correct way to do a partial update that involves several fields? Also using PATCH is out of the question.
Edit:
I know that the correct way to do this restfully would be to post an update to each field as a sub resource but lets say for the sake of bandwidth/business requirements that this update has to be done in a single call. Is this the correct way to do so?
Edit 2:
Our implementation does not support the HTTP PATCH method, hence why I indicated in the initial question that using patch is out of the question. That being said, maybe I should rephrase the question.
Since system/business requirements prevent us from implementing this correctly in a RESTful manor. What is the best way to handle this scenario.
Putting the verb "update-" suddenly makes it feel like it's an RPC call. What do you do when you want to delete this email? Doing a DELETE action on this URI looks a bit silly.
URI: /user/1/email and
URI: user/1/lastname would make more sense as EMAIL would just be a subresource and you can use all the verbs on those resources.
Yes, this would take 2 calls in case you want to update 2 resources instead of 1.
For partial updates of a resource use "PATCH" verb on the resource. This way you would not need a new URI at all. (Best practice for partial updates in a RESTful service)
Reference: http://restcookbook.com/HTTP%20Methods/patch/
Quote:
When should we use the PATCH HTTP method?
The HTTP methods PATCH can be used to update partial resources. For instance, when you only need to update one field of the resource, PUTting a complete resource representation might be cumbersome and utilizes more bandwidth
See more at: http://restcookbook.com/HTTP%20Methods/patch/#sthash.jEWLklrg.dpuf

Creation of REST resources: compose or separate?

Suppose I need to create a shipment to a customer and that shipment requires an address. Both resources need to be created.
In REST design, which approach is preferred? And why?
# One request that in-lines the address.
POST /shipments
{
"shipment": {
"customer_id": 1,
"address": {
"city": "Toronto",
...
}
}
}
vs
# Two requests, first creating the address, then passing an id.
POST /addresses
{
"address": {
"customer_id": 1,
"city": "Toronto",
...
}
}
POST /shipment
{
"shipment": {
customer_id: 1,
address_id: 100
}
}
It is important to think first of the business and usability implications, and then use RESTful design practices to implement a reasonable solution.
In your example, if you only implement separate REST calls for creating the shipment and embedded address, the app developer will be unable to create the shipment in an atomic fashion. If creation of the shipment is successful, and then the creation of the address fails or the network connection is lost, you end up with incomplete data at your backend. Even if the app developer is able to roll back the change, you are adding significant complexity to the app design.
So for the create, I would allow the address to be included in the shipment, or force it to be included if a shipment without an address violates your business rules. Other decisions (whether to create separate calls for updates or update all shipment fields at the same time or support both, for example) will also often be suggested by business rules and application design.
This is just my opinion. ButI would allow both methods. To do it I would use two different media-types. But if you are using only application/json media type still possible to allow both.
Most languages have automatic de/serializers from json to model objects and back. But YMMV.
Although the two media types approach is optional and have huge implications (as you would be needing to use specific media types for all your representations instead of application/json) I prefer to be explicit. It allows for early discarding of the request (headers gets first to the server and client).
BUT, if you are asking if there is any "preferred" way, it is not AFAIK. One saves you (or the client) a request and a network roundtrip, but the other states more clearly the structure of your API.
From your descriptions, you want to manipulate/manage two “REST” resources: shipment and address.
Also you're implying that address is a sub-resource under shipment
Use-case-1: to create a shipment with address info
POST /shipments/
BODY: {address {<<address info}}
RETURN: {shipment-id}
Use-case-2: to create a shipment without address info
POST /shipments/
BODY: {}
RETURN: {shipment-id}
Use-case-3: to update a shipment with address info
PUT /shipments/[shipment-id]/address/
BODY: {address {<<address info}}
Use-case-4: if you have use-case to create address independently, you can have
POST /addresses/
BODY: {address-info}
RETURN: {address-id}
Use-case-5: You can update shipment with address-id,
PUT /shipments/[shipment-id]/address/
BODY: {address–id {id-} }
I believe any modern public API (assume your API is public) design should be derived from the most common use cases and not from internal structure of the code. I.e. your API should be as usable as possible for that use cases. Testability and internal structure are important too, but usability is more important because a developer (actually customer of your service) is much more bothered by how easy to use your API than how complex design of internals is.
So, I think, it is impossible to provide certain answer to your question unless your provide a set of the most common use cases for your API. Then, you should consider asking developers who know nothing about your API how they would like to complete the use cases. The most common answers will show the best approaches.

Can REST be used to "call" operations on business objects?

I have a new project coming up, and am intruiged by REST. However, it seems to have a very limited interface. Does REST support object-specific interactions, or is it limited to simple CRUD?
Example:
A school management app has Student objects. It should be able to:
RegisterNewStudent (some data)
Each student object should handle business operations:
Student.FixName(name data)
Student.ChangeSchool(school data)
Student.Graduate(classrank data)
Student.ChangePassword(password data)
I've been implementing CQRS with message queues where each of these things would be a separate Command. However, in REST it appears I'd be limited to:
PUT Student (all data about student)
POST Student/id (update student record with any/all fields changed)
DELETE Student/id
Am I missing something here? Where would lifecycle/statechange logic be implemented in a RESTful solution? Changing a Student's School enrollment involves different logic (and possibly different permissions) than changing her name. Would I have to let the client post an "update" of any/all fields and then have to infer what operations they intend?
//Edit:
Is this the sort of thing I'm struggling toward:
PUT /Students {data about new student}
POST /Students/314/School {data about different school}
POST /Students/314/Name {data to fix name, ie add middle name}
POST /Students/314/Password {data for new password}
etc?
Q: Can REST be used to “call” operations on business objects?
A: Yes, absolutely yes.
Just as you can invoke any operation on any servlet with GET or PUT, you can also invoke any operation in a REST-ful web service.
Including, but not limited to, CRUD operations :)
You will want to create several webservices to do what you want, but if I take one example of yours:
Student.ChangePassword(password data)
And have a POST request /ChangePassword/{student_id}/{password}
then your only trick is to ensure who can call this function. Do you use a session cookie to control access, or have them pass in a username/password then a new password?
You will find that POST and PUT will be useful as these aren't logged in the webserver log file.