Assume you have some resource behind a REST API. This resource could well be modified using the usual HTTP verbs PUT or PATCH. But let's assume the server behind the API has to check some prerequisites to decide if the modification on the resource can be made or not (e.g. withdraw an amount from a bank account).
In this case there is no use in using POST (because we do not want to add a new resource), nor PUT or PATCH, because only the server knows about the new value of the resources' modified attribute, if he will allow the requested modification at all. In the above example the account's new balance would have to be computed on the server side like so : balance = balance - amount, and to my knowledge all the client can do with PUT or PATCH is to send the already modified resource (the account) or atttribute of that resource (the accounts' balance).
Am I then right in assuming that in this case the API designer has to provide a parameter (e.g. .../account?withdraw=amount) with the URL pointing to the resource ? What would be the correct HTTP verb for this operation ?
there is no use in using POST (because we do not want to add a new resource)
You do. A monetary exchange can be expressed in a transaction, hence: you're creating a new transaction.
So simply perform a POST with the transaction details to a /transaction endpoint.
You certainly don't want to allow users to PUT their new account balance, as that would require atomicity over HTTP, which is all REST stands against: the client would have to know the pre-transaction balance, and make sure in some way no transaction will be carried out before theirs arrives.
Related
We have a service which inserts into dynamodb certain values. For sake of this question let's say its key:value pair i.e., customer_id:customer_email. The inserts don't happen that frequently and once the inserts are done, that specific key doesn't get updated.
What we have done is create a client library which, provided with customer_id will fetch customer_email from dynamodb.
Given that customer_id data is static, what we were thinking is to add cache to the table but one thing which we are not sure that what will happen in the following use-case
client_1 uses our library to fetch customer_email for customer_id = 2.
The customer doesn't exist so API Gateway returns not found
APIGateway will cache this response
For any subsequent calls, this cached response will be sent
Now another system inserts customer_id = 2 with its email id. This system doesn't know if this response has been cached previously or not. It doesn't even know that any other system has fetched this specific data. How can we invalidate cache for this specific customer_id when it gets inserted into dynamodb
You can send a request to the API endpoint with a Cache-Control: max-age=0 header which will cause it to refresh.
This could open your application up to attack as a bad actor can simply flood an expensive endpoint with lots of traffic and buckle your servers/database. In order to safeguard against that it's best to use a signed request.
In case it's useful to people, here's .NET code to create the signed request:
https://gist.github.com/secretorange/905b4811300d7c96c71fa9c6d115ee24
We've built a Lambda which takes care of re-filling cache with updated results. It's a quite manual process, with very little re-usable code, but it works.
Lambda is triggered by the application itself following application needs. For example, in CRUD operations the Lambda is triggered upon successful execution of POST, PATCH and DELETE on a specific resource, in order to clear the general GET request (i.e. clear GET /books whenever POST /book succeeded).
Unfortunately, if you have a View with a server-side paginated table you are going to face all sorts of issues because invalidating /books is not enough since you actually may have /books?page=2, /books?page=3 and so on....a nightmare!
I believe APIG should allow for more granular control of cache entries, otherwise many use cases aren't covered. It would be enough if they would allow to choose a root cache group for each request, so that we could manage cache entries by group rather than by single request (which, imho, is also less common).
Did you look at this https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-caching.html ?
There is way to invalidate entire cache or a particular cache entry
I would like to know how do design the RESTful web service for process methods. For example I want to make a REST Api for ProcessPayroll for given employee id. Since ProcessPayroll is time consuming job, I don't need any response from the method call but just want to invoke the ProcessPayroll method asynchronously and return. I can't use ProcessPayroll in the URL since it is not a resource and it is not a verb. So I thought that, I can go with the below approach
Request 1
http://www.example.com/payroll/v1.0/payroll_processor POST
body
{
"employee" : "123"
}
Request 2
http://www.example.com/payroll/v1.0/payroll_processor?employee=123 GET
Which one of the above approach is correct one? Is there any Restful API Design guidelines to make a Restful service for process methods and functions?
Which one of the above approach is correct one?
Of the two, POST is closest.
The problem with using GET /mumble is that the specification of the GET method restricts its use to operations that are "safe"; which is to say that they don't change the resource in any way. In other words, GET promises that a resource can be pre-fetched, just in case it is needed, by the user agent and the caches along the way.
Is there any Restful API Design guidelines to make a Restful service for process methods and functions?
Jim Webber has a bunch of articles and talks that discuss this sort of thing. Start with How to GET a cup of coffee.
But the rough plot is that your REST api acts as an integration component between the process and the consumer. The protocol is implemented as the manipulation of one or more resources.
So you have some known bookmark that tells you how to submit a payroll request (think web form), and when you submit that request (typically POST, sometimes PUT, details not immediately important) the resource that handles it as a side effect (1) starts an instance of ProcessPayroll from the data in your message, (2) maps that instance to a new resource in its namespace and (3) redirects you to the resource that tracks your payroll instance.
In a simple web api, you just keep refreshing your copy of this new resource to get updates. In a REST api, that resource will be returning a hypermedia representation of the resource that describes what actions are available.
As Webber says, HTTP is a document transport application. Your web api handles document requests, and as a side effect of that handling interacts with your domain application protocol. In other words, a lot of the resources are just messages....
We've come up with the similar solution in my project, so don't blame if my opinion is wrong - I just want to share our experience.
What concerns the resource itself - I'd suggest something like
http://www.example.com/payroll/v1.0/payrollRequest POST
As the job is supposed to be run at the background, the api call should return Accepted (202) http code. That tells the user that the operation will take a lot time. However you should return a payrollRequestId unique identifier (Guid for example) to allow users to get the posted resource later on by calling:
http://www.example.com/payroll/v1.0/payrollRequest/{payrollRequestId} GET
Hope this helps
You decide the post and get on the basis of the API work-
If your Rest API create any new in row DB(means new resource in DB) , then you have to go for POST. In your case if your payroll process method create any resource then you have to choose to POST
If your Rest API do both, create and update the resources. Means ,if your payroll method process the data and update it and create a new data , then go for PUT
If your Rest API just read the data, go for GET. But as I think from your question your payroll method not send any data.So GET is not best for your case.
As I think your payroll method is doing both thing.
Process the data , means updating the data and
Create new Data , means creating the new row in DB
NOTE - One more thing , the PUT is idempotent and POST is not.Follow the link PUT vs POST in REST
So, you have to go for PUT method.
I am developing an application based on REST services. I've read everything about developing REST web service but one thing confusing me. As I read, all the module or functionality must have unique and meaningful resource name like
http://localhost:8080/rest/create-organization
and
http://localhost:8080/rest/add-employee
But one of my colleagues suggested me that we should have only one resource as a single landing point for all modules and we must send some code in request header to recognize which functionality we want to execute. For example:
http://localhost:8080/rest/application
And, in request header, we should add CRTORG parameter for creating organization and ADDEMP for adding an employee.
On the basis of this keywords we will call appropriate method and will return response.
Is it the right way? If no why?
That's not how REST applications are supposed to be. See more details below.
REST resources
REST stands for Representational State Transfer and this architecture was defined by Roy Thomas Fielding in the chapter 5 of his dissertation.
The key concept of this architecture is the resource. See the following quote from the Fielding's dissertation:
5.2.1.1 Resources and Resource Identifiers
The key abstraction of information in REST is a resource. Any information that can be named can be a resource: a document or image, a temporal service (e.g. "today's weather in Los Angeles"), a collection of other resources, a non-virtual object (e.g. a person), and so on. In other words, any concept that might be the target of an author's hypertext reference must fit within the definition of a resource. A resource is a conceptual mapping to a set of entities, not the entity that corresponds to the mapping at any particular point in time. [...]
REST is protocol independent and, when implemented over the HTTP protocol, the resources can be manipulated with HTTP verbs and the resources are identified by theirs URIs. The same resource can have different representations, such as JSON and XML.
For more details regarding resources and resource representations, see this answer.
What your API could be like
Your API could have the following endpoints and operations:
Create an organization (sending the resource representation in the request payload)
POST /api/organizations
Get all organizations
GET /api/organizations
Get an organization using a certain identifier
GET /api/organizations/{organizationId}
Replace an organization using a certain identifier (sending the resource representation in the request payload)
PUT /api/organizations/{organizationId}
Delete an organization using a certain identifier
DELETE /api/organizations/{organizationId}
Create an employee for an organization (sending the resource representation in the request payload)
POST /api/organizations/{organizationId}/employees
Get all employees for an organization
GET /api/organizations/{organizationId}/employees
Get an employee for an organization
GET /api/organizations/{organizationId}/employees/{employeeId}
Replace an employee of an organization (sending the resource representation in the request payload)
PUT /api/organizations/{organizationId}/employees/{employeeId}
Delete an employee from an organization
DELETE /api/organizations/{organizationId}/employees/{employeeId}
I am using IS WSO2 for authorization with XACML. I am am able to achieve authorization for static resource. But I am not sure with the design when it comes to granularization.
Example : if I have method like getCarDetails(Object User) where I should get only those cars which are assigned to this particular user, then how to deal this with XACMl?
Wso2 provides support for PIP where we can use custom classes which can fetch data from database. But I am not sure if we should either make copy of original database at PDP side or give the original database to PIP to get updated with live data.
Because Cars would be dynamic for the application eg. currently 10 cars assigned to user Alice. suddenly supervisor add 20 more car in his list which will be in application level database. Then how these other 20 cars will be automatically assigned in policy at PDP level until it also have this latest information.
I may making some mistake in understanding. But I am not sure how to deal with this as in whole application we can have lots of this kind of complex scenario where some times we will get data for one user from more than 4 or 5 tables then how to handle that scenario?
Your question is a great and the answer will highlight the key benefits of XACML and externalized authorization as a whole.
In XACML, you define generic, global rules, about what is allowed and what isn't using what I would call high-level attributes e.g. attributes of the vehicle (in your case) or the user (role, department, ...)
For instance a simple rule could be (using the ALFA syntax):
policy viewCars{
target clause actionId=="view" and resourceType=="car"
apply firstApplicable
rule allowSameRegion{
permit
condition user.region==car.region
}
}
Both the user's region and the car's region are maintained inside the application's database. The values are read using a PIP or Policy Information Point (details here).
In your example, you talk about direct assignment, i.e. a user has been directly assigned to a vehicle. In that case, the rule would become:
policy viewCars{
target clause actionId=="view" and resourceType=="car"
apply firstApplicable
rule allowAssignedVehicle{
permit
condition user.employeeId==car.assignedUser
}
}
This means that the assigned user information must be kept somewhere, in the application database, a CSV file, a web service, or another source of information. It means that from a management perspective, an administrator would add / remove vehicles from a user's assigned list (or perhaps the other way around: add / remove assigned users from a vehicle's assigned user list).
The XACML rule itself will not change. If the supervisor adds 20 more cars to the employee's list (maintained in the application-level database), then the PDP will be able to use that information via the PIP and access will be granted or denied accordingly.
The key benefit of XACML is that you could add a second rule that would state a supervisor can see the cars he/she is assigned to (the normal rule) as well as the cars assigned to his/her subordinates (a new proxy-delegate rule).
This diagram, taken from the Axiomatics blog, summarizes the XACML flow:
HTH, let me know if you have further questions. You can download ALFA here and you can watch tutorials here.
I have a design question of REST URI.
Suppose i have a Car resource (that is mapped in the database with some properties).
If i want update the Car resource with the information of another Car i know that i can call
PUT /base_url/api/cars/1
I update the car with id == 1 with the informations in the request body
But if i want update the car with id == 1 with the information of the car with id == 2? (i'd like to pass only id because the copy is handled internally by the server)
How can i design this type of request in rest?
You should use PATCH instead.
The difference between the PUT and PATCH requests is reflected in
the way the server processes the enclosed entity to modify the
resource identified by the Request-URI. In a PUT request, the
enclosed entity is considered to be a modified version of the
resource stored on the origin server, and the client is requesting
that the stored version be replaced. With PATCH, however, the
enclosed entity contains a set of instructions describing how a
resource currently residing on the origin server should be modified
to produce a new version. The PATCH method affects the resource
identified by the Request-URI, and it also MAY have side effects on
other resources; i.e., new resources may be created, or existing
ones modified, by the application of a PATCH.
PATCH Method for HTTP
Something like this would be okay:
PATCH /base_url/api/cars/1
{template: {id: 2}}
Don't send the id in the query, because it is part of the URI, which is the identifier of your target resource.
I would make a PUT request to this URI: PUT /base_url/api/cars/1?clone=2, and pass information (in JSON body).
In the backend I would find the data for car #2, and merge it with the data I got from the request.
This way you could clone the resource, and modify its attributes at the same time.