I'm struggling with coming up with the "right" way to capture audit information via a REST service. Let's say I've got an internal REST API for an Employee resource. I want to capture things when an Employee is added/modified/removed such as the user who did the change, the application the user was using, when it was done (assume this could be asynchronous so the user's action may have taken place at a different time than the REST call), etc. Also, the user that initiated the change may not be the authenticated user making the REST call.
My thoughts are that those properties do not belong in the body of the request - meaning that they are not attributes of the Employee object. They are not something that would be retrieved and returned on a GET, so they shouldn't be in the POST/PUT. They also do not belong as a parameter because parameters should be for specifying additional things about Employees or a search/filter critiera on GET requests for Employees.
My current thoughts are to have the client specify this information in the HTTP headers. That keeps the URL parameters & body pure for the Employee resource. Is that an appropriate use of the headers? Are there other options that I'm not seeing?
I'm working on a project with a very similar problem, and we did end up using HTTP headers to track auditing information. Actually, this was a byproduct of requiring an Authorization header which specifies the client user and application, and we use this information inside the REST service to store details in an audit log.
In your case, I don't think it's "wrong" to add custom X headers to specify the original user/application/time the request was made and storing these to an audit history in the service somewhere. Basically proxying on information via extra request headers. I also agree that these should not be part of the request body or URL parameters.
Related
Considering I have a REST API exposing a repository of users :
/users/ -> returns an array of UserModel
/users/{Id} -> returns a UserModel
I needs to implement a client application that support offline mode (API not available) that will display the list of users and the detail of each user.
I am considering to synchronize in the client app the users this way :
Get the full list of users by calling a GET on /users/ and persist the list of users
Each time a user is accessing a user profile, if REST API available, check if the user has been updated by calling the REST API and update the user details if necessary
Display the user profile
I am considering using ETag (https://en.wikipedia.org/wiki/HTTP_ETag) to implement this behavior.
My issue is that I don't want my client application to get user details one by one by calling GET /users/{Id} but in a bulk by calling GET /users/ (with some paging if needed). If I do so, the client application will get a global ETAG of the list of users, but not ETags of each user. Thus it will not be able to verify individually if a user entity is up-to-date.
As a workaround, I am considering to add an ETAG field to the UserModel of the API. This way after calling GET /users/, the client app will be able to check if a specific user has been updated by calling GET /users/{Id} with the If-None-Match <User'sETagValue> header.
I know that the solution do no stick to he HTTP 1.1 standard, and that it adds a little complexity to the ETag generation.
However, I can't find any other post describing such a solution and I am wondering if it presents major issues ? And If there are more elegant solutions ?
Thanks for your help,
Edit : WebDav standard defines a "DAV:getetag" property that looks similar to my approach (http://www.webdav.org/specs/rfc4918.html#cache-control)
The WebDAV spec is also the first thing that came to mind for me.
I don't see an issue with adding etags to the response of your collection. You might even define a collection in a more general way, so that the format is just a list of URIs, their responses and headers so your client can treat it as a list of resources that need to be written to a cache.
I'm trying to figure out best or common practices for API design.
My concern is basically this:
PUT /users/:id
In my view this endpoint could by used for a wide array of functions.
I would use it to change the user name or profile, but what about ex, resetting a password?
From a "model" point of view, that could be flag, a property of the user, so it would "work" to send a modification.
But I would expect more something like
POST /users/:id/reset_password
But that means that almost for each modification I could create a different endpoint according to the meaning of the modification, i.e
POST /users/:id/enable
POST /users/:id/birthday
...
or even
GET /user/:id/birthday
compared to simply
GET /users/:id
So basically I don't understand when to stop using a single POST/GET and creating instead different endpoints.
It looks to me as a simple matter of choice, I just want to know if there is some standard way of doing this or some guideline. After reading and looking at example I'm still not really sure.
Disclaimer: In a lot of cases, people ask about REST when what they really want is an HTTP compliant RPC design with pretty URLs. In what follows, I'm answering about REST.
In my view this endpoint could by used for a wide array of functions. I would use it to change the user name or profile, but what about ex, resetting a password?
Sure, why not?
I don't understand when to stop using a single POST/GET and creating instead different endpoints.
A really good starting point is Jim Webber's talk Domain Driven Design for RESTful systems.
First key idea - your resources are not your domain model entities. Your REST API is really a facade in front of your domain model, which supports the illusion that you are just a website.
So your resources are analogous to documents that represent information. The URI identifies the document.
Second key idea - that URI is used by clients to cache representations of the resource, so that we don't need to send requests back to the server all the time. Instead, we have built into HTTP a bunch of standard ways for communicating caching meta data from the server to the client.
Critical to that is the rule for cache invalidation: a successful unsafe request invalidates previously cached representations of the same resource (ie, the same URI).
So the general rule is, if the client is going to do something that will modify a resource they have already cached, then we want the modification request to go to that same URI.
Your REST API is a facade to make your domain model look like a web site. So if we think about how we might build a web site to do the same thing, it can give us insights to how we arrange our resources.
So to borrow your example, we might have a web page representation of the user. If we were going to allow the client to modify that page, then we might think through a bunch of use cases (enable, change birthday, change name, reset password). For each of these supported cases, we would have a link to a task-specific form. Each of those forms would have fields allowing the client to describe the change, and a url in the form action to decide where the form gets submitted.
Since what the client is trying to achieve is to modify the profile page itself, we would have each of those forms submit back to the profile page URI, so that the client would know to invalidate the previously cached representations if the request were successful.
So your resource identifiers might look like:
/users/:id
/users/:id/forms/enable
/users/:id/forms/changeName
/users/:id/forms/changeBirthday
/users/:id/forms/resetPassword
Where each of the forms submits its information to /users/:id.
That does mean, in your implementation, you are probably going to end up with a lot of different requests routed to the same handler, and so you may need to disambiguate them there.
I'm designing a REST api that allow client side to POST (create) a resource.
Let's call my resource is Subscription and my REST api accepts a Dto called Subscription
The POST request needs to be sent together with a captcha token that will be verified on server side.
My question is where would be the best place to put the captcha token, there're some options that I'm thinking about:
Directly inside Subscription
As a parameter in URL, e.g: /subscriptions?captcha_token=abcd1234
As a HTTP header
Create a new Dto that wraps Subscription and carry field captchaToken
Any other suggestion are welcome.
Thank you.
For anything authentication or authorization related I typically rely on headers or querystring parameters.
Generally I don't like to commingle payload with auth-related material, nor do I like to encapsulate it.
Having it in an HTTP header or as a querystring parameter gives you a good amount of isolation there. Also since it's independent of the request body you can implement broader auth controls for every API call without being dependent on the presence of a request body (important for GET requests which shouldn't carry a request body anyway).
Using a HTTP Header is only an option if your clients can modify / send HTTP Header information. This approach does not work for Standard Browsers.
You are not filtering a resource, so a query parameter from the REST Point of view does not make sense, and you don't want to send the captcha answer as query parameter.
Usually the one submits the captcha information (id, answer) together with the form data (payload). You also usually display captchas together with the form.
So at the end the only useful option is to send the captcha information as part of the payload / form data.
If you should put the data into your Subscription DTO or not depends on your design / preferences.
I'd suggest to use something like a Subscription(Data) and SubscriptionRequest where the SubscriptionRequest contains the SubscriptionDataand the Captha Information (capcha id and answer)
I am supposed to make web services for an app and thought I could do a nice job practicing the good practice. As I found out it's using REST. But there is one thing that makes very little sense in it.
Why use URI to pass any variable?
What we did in our last project is use POST only and pass whatever as raw POST data (which was JSON). That's not very RESTful. But it has some advantages. It was quite simple on the client side - I had a general function that takes URI and data as arguments and then it wraps it up and sends it.
Now, if I used proper REST, I would have to pass some data as part of the URI (user ID, for instance). All the other data (username, email and etc.) would have to go as raw data, like we did, I guess. That means I would have to separate user ID and the other data at some point. That's not so bad but still - why?
EDIT
Here is a more detailed example:
Let's say you want to access (GET) and update (POST) user data. You may have a service accessible under /user but what RESTful service would do is accept user's ID as part of the URI (/user/1234). All the other data (name, email and etc) would go to request content (probably as JSON).
What I pose is that it seems useless to make put user id in the URI. If you wanted to update user data - you would send additional data as content anyway. If you wanted to access it - you could use same generic method to request web service.
I know GET gets cached by a browser but I believe you have to cache it manually anyway if you use AJAX (web) or any HTTP client library (other platforms).
From point of scalability - you can always add more services.
You use the URI to identify the resource (user/document/webpage) you want to work with, and pass the related data inside the request.
It has the advantage that web infrastructure components can find out the location of the resource without having any idea how your content is represented. For example, you can use standard caches and load balancers, all they need to know is the URL and headers (which are always represented the same way) Whether you use JSON, protobuf or WAV audio to communicate with your resource is irrelevant.
This will for example let you keep different resources in totally different places, if you send it all as content you won't have the advantage of being able to place the resources in totally different locations, as for example http://cloud.google.com/resource1 and http://cloud.amazon.com/resource2.
All this will allow you to scale massively, which you won't be able to do if you put it all on http://my.url.com/rest and pass all resource info as content.
Re: Your edit
Passing the user id in the URL is the only way to identify the individual resource (user). Remember, it's the user that's the resource, not the "user store".
For example, a cache that caches http://my.url/user won't be much good, since it would return the same cached page for every user. If the cache can work with http://my.url/user/4711, it can cache every user separately. In the same way, a load balancer could know that users 1-5000 are handled by one machine, 5001-10000 by another etc. and make intelligent decisions based on the URL only.
Imagine a RESTful web service as a database.
To get or modify specific object you need to identify it by providing its primary key.
You identify a user by his ID, not his Name+Nickname+e-mail+mother's maiden name.
The information that identifies an object or selects a set of objects goes to the URL. The information that modifies objects should be POSTed to the corresponding URL.
Is it appropriate to perform actions with REST, other than simple create (POST), read (GET), update (PUT), and delete (DELETE)? I'm kind of new to the whole RESTful theology, so bear with me, but how should I accomplish the following:
I have a web service that needs to talk to another web service. Web service A needs to "reserve" an object on Web service B. This object has a timeout of validity, but can be deleted immediately if need be. It's essentially a glorified permissions system which requires web services to reserve a space on web service B before taking any actions.
My initial thought was to 1. enable authentication of some sort, 2. in the serverside response to a GET call, reserve the space and return the result, and 3. provide immediate "unreservation" of the object via a DELETE call. Is this still being RESTful?
Yes, it's OK to perform actions with rest. What matters is that these actions should be guided by the representations you exchange.
If you think about the way the web works (via a browser), you do this all the time: you get an HTML form that lets you choose a number of actions you can perform. Then, you submit the form (typically via POST) and the action is performed.
It's good to be able to use DELETE via a programmatic client (which is something that non-AJAX requests in browsers wouldn't support), but the overall approach of a RESTful system should be very similar to what you find for websites (i.e. the focus should be on the representations: the equivalent of web pages in your system).
GET shouldn't have side effects, so don't use GET to make the reservation itself, use something like POST instead.
No - unlikely to be restful
From your description ...
2. in the serverside response to a GET call, reserve the space and return the result
GETs should be idempotent. For this reason alone, your service is unlikely to be restful because the state of the system after the first GET is different.
You really need to consider that a Reservation is a resource and should be created with a POST to a reservations container which will return the URI of the new resource in the Location header of the HTTP response. This UrI can be used by Get to return the resource and updated with a PUT
Post should be used to extend an existing resource and Put for replacing the state of a resource. In your case, consider the Post to be updating a list of Reservations and returning the URI of the new resource (not just the I'd). Put can be used for changing the state associated with the resource identified by the UR
You're on the right track, but your reservation of the object should be with a PUT; you're PUTting a reservation on the object, i.e. changing the underlying object.
PUT is the right verb here, since you know what resource you're modifying, and it should be idempotent for multiple requests.