REST performing an action - rest

I'm designing a REST API where I need to give the clients the ability to copy resources.
Say for example you have the following resource: customer/{customerno}/address
And you will provide the client with functionallity for copying the address to shippingaddress.
I could do like this: customer/{customerno}/address/copytoshipping
But then it would be RPC and not REST. What is the correct way to do something like this?

Does that have to be in the REST API? The client could just GET the representation of the (billing?) address and PUT it to the shipping address. Yes, you might well hide the details of that in your client-side code (that seems very reasonable to me) but there's no particular reason to clutter the REST interface with special operations to do the copying.

GET the address using Rel="CustomerAddress"
POST using Rel="CustomerShippingAddress" example URL customer/{customerno}/address/shipping

A different approach could be:
Expose a resource for "customer address" (as you stated above)
GET /customer/{number}/address
Expose a resource for "customer shipping address"
fetch:
GET /customer/{number}/shipping-address
update with actual address:
PUT /customer/{number}/shipping-address
Content-Type: application/xml
(xml/json of a single address)
update using a URI pointer to another address
PUT /customer/number/shipping-address HTTP/1.1
Content-Type: application/atom+xml
(xml/json of an atom:link with href pointer to main address ('/customer/123/address')
Perhaps more complex than you want but puts the copy burden on the server rather than the client.

Related

Is body required in PUT request?

I want to design my REST endpoint for enabling or disabling a user
My thought is to use PUT without body, with this URLs:
PUT /.../users/{userName}/enable
PUT /.../users/{userName}/disable
Is it possible to use PUT without a body?
Do you have any other suggestions?
Is body required in PUT request?
No - a PUT request with an empty body is how we would tell a web server that we want the representation of a resource to be zero bytes long.
PUT /example HTTP/1.0
Content-Type: text/plain
Content-Length: 0
I want to design my REST endpoint for enabling or disabling a user
A bit of prior art that you might consider is the github starring API, which uses PUT with an empty body to turn on a star, and DELETE to turn off a star.
Note that both requests use the same URI - that's appropriate because we want general purpose cache invalidation to "just work".
It may be helpful to be clear in your mind the differences between the semantics of the message ("please save this empty document on the web server") and the business side effects ("enable the user"). See Webber 2011.
Short answer: No.
Personally, I have also used empty PUT requests when merely updating a resource using an idempotent action - like toggling enable/disable.
Possible duplicate of: Is an HTTP PUT request required to include a body?

restful service parameters in headers or body

I am developing a restful web service based on a database query and the tool that i am using tends to generate the parameters as a part of the HTTP Header ?
I always thought the parameters for POST to the restful service should always be passed in HTTP Body ?
Any ideas what should be the best practice or the usual practice ?
For POST requests, you can do either, but generally you'll use the body of the request for content that you are appending, mutating, deleting, etc. or for any data that is simply too large to put in the URI while one generally uses URI parameters for information that identifies the resource that is being accessed or modified (such as the element's ID) or restrictions or other search criteria (e.g. page, limit, etc.).
The primary tradeoffs off the top of my head are linkability (do you need a special POST extension, for example, just for developers to test a particular handler on your server?), URI size limits, and also whether the user would need to perform a click in order to cause the request to be sent (though using POST body is not a substitute for requiring a valid XSRF token/signature on the request).
Did I miss any other tradeoffs?

Using SoapUI to test Login function of REST application

I don't make this very general question post lightly, but I've maxed out what I can figure out on my own.
I'm starting up the QA Test Automation at my new company (they don't automate anything currently) and they've elected to use SoapUI for this procedure.
The application they're developing is a REST application (I don't really have any idea what that means) so I'm trying to build a REST request and Test Suite to reach our internal test server (which gets me XML that I am not allowed to post here - but it does reach the server successfully!) and then try to do a Login/Logout test.
I'm asking for help with methodology, because I have no idea where to start. I;ve Googled and trolled their support forums and looked in every corner of YouTube. Everyone is doing something different enough that I can't relate or use it.
Does anybody out there use SoapUI and test functional login in a REST application? I can write HTML/CSS and I'm pretty Java savvy, so I can do technical stuff if I know what to look for and what to learn.
Feeling overwhelmed. This was not in my job description when I started.
You should start with REST, and after that with SoapUI.
It is hard to catch the essence of REST.
It is like the hybrid of SOAP and a simple HTML driven web application. By SOAP you describe your web service with a WSDL. By a web application you send back hypermedia, so you don't have to write a WSDL or any descriptor to your application. This is convention over configuration...
REST uses the same approach, so it sends back hypermedia as well, but it sends not HTML, because it is not machine processable. The hypermedia sent by a REST API is usually an XML or a JSON derivative, for example ATOM+XML, JSON-LD, etc... If your web service does not send back hyperlinks, then it is not a real REST service just a SOAP web service with some REST constraints. There is a big difference. By SOAP you have to know everything about the operation name and the parameters if you want to send a request. If something changes, then your SOAP client breaks immediately. By REST your automated client follows links, checks their link-relation, or the bound linked data and recognizes which link is what it was looking for. So the modification of the link's url is irrelevant in the client, because it follows the vocabulary of the application, for example: hydra is a project which tries to describe these application level semantics in a general way, and tries to bind it to open linked data.
So at first you have to check that you have a real REST API, which follows the HATEOAS principle, or just a REST like SOAP web service. This is very important if you want to write end to end tests against it. By testing REST, you have to follow the links in your tests returned by the web API. By testing REST like SOAP, you have to build the links yourself in your tests... How to build such a link? I am sure you got a description of your REST API, but a link looks usually something like this in a JSON format:
{
rel: "link-relations",
method: "METHOD",
href: "domain/api-root/version/resource-path?map-reduce",
data: {...},
title: "...",
...
}
Ofc. there is some difference by every hypermedia, so you have to check your XML hypermedia type, how it represents links... The link-relations and maybe other attributes bind your data to the semantics of your REST API. The METHOD is always a verb, usually: GET, POST, PUT, PATCH, DELETE, maybe OPTIONS, and so on... There are only a few REST verbs, each of them has a specific meaning. In the url: The domain is the domain name of your application, e.g. https://example.com. The api-root is the root of your REST API, usually /api. The version is the version number of the currently used API, usually /v1. Only non backward compatible vocabulary changes should affect this version number. The resource-path is the path of your resource, usually /users or /users/inf3rno, etc... By REST you have resources. Each of them has a unique resource-path, and as you can see, every word in that path is a noun. So resources are something you can modify or display with a verb. For example a GET /users/inf3rno should return a representation of my profile page, and a PATCH /users/inf3rno {nick: "Leslie"} will turn my nick name: inf3rno into Leslie. By REST every resource should have only a single resource-path, so this is always a unique identifier, therefore the previous example with PATCH was not so perfect if you want to have multiple users with the same nick... The map-reduce in the queryString of the url, and it contains the sorting, pagination and filtering settings of the resource you want to modify or display. For example you can retrieve some data of every user with a first name: "Leslie" with GET /users?filters="firstName: 'Leslie'"&page=3&count=25. There is a difference between the following url-s: /users?id="inf3rno" and /users/inf3rno. The first one points to a collection resource and filters the result by its representation, the second one points to a single item resource. So a GET should return a collection representation with a single item by the first one, and an item representation by the seconds one. By the resource modifying methods there is no difference between the 2 urls... So it is recommended to add only a unique identifier to the resource-path if you want to select an item resource from a collection. By reducing the collection representation in any other ways, you have to add the filters to the queryString. The data part contains the params from the input fields. The title is the title of the link, and so on... You can use url-templates of you want to put input params to the url as well...
By REST the client maintains the session, and it sends the credentials (username, password) with every request. This is because the REST service is like John Snow, it does not know anything about the session or the identity of the user. It has to authenticate every request. To do that it uses a credentials -> permissions cache. This is a good approach, because the service scales very well if it does not have to maintain the session, which is part of the application state (the state of the client)... The REST service maintains only the resource state, which is not dependent on the clients...
The response to your REST requests is usually a hypermedia which contains the links you can follow and the data you requested. By REST like SOAP web services you get only the data in a JSON or XML format. Every response should contain a proper status header. The most frequent status codes are:
200 - ok (by successful PUT, PATCH and GET)
201 - created (by successful POST)
202 - accepted (by async request with eventual consistency)
204 - no content (by successful DELETE)
206 - partial content (by pagination with range headers)
301 - moved permanently (by migration)
304 - not modified (by cache)
400 - bad request (by invalid input)
401 - unauthorized (if no password given, or wrong username or password)
403 - access denied (if your account does not have permission to perform the task)
404 - not found (by unknown resource)
409 - conflict (by concurrency issues or duplicated request or db constraint problems)
410 - gone (if the resource was present before, but it is already deleted)
415 - unsupported media type (if the client wants the response in an unknown media type)
500 - internal server error (if the request was okay, but something went wrong by processing it)
By any error you have to send a detailed error message with a custom error code, which is understandable for the users, not just the developers...
That's how a REST API looks like.
To test it with e2e tests you have to set fixtures send REST requests and check their response. So it is like any other test... The SoapUI is not necessarily the best tool to do that, I read many complaints about it... I personally never used it, but it is not so hard to write your custom testing system. You need a testing framework, which can compare expected and actual values. You need something to send HTTP requests, or simply mock out the HTTP framework of the REST API. You need something for the fixture. By integration tests you can mock out the business logic and the HTTP framework as well, so by those you just inject the mock dependencies and check the calls. By e2e tests you need a test data set, and compare it with the result XML in your case... If you want to e2e test your client, you can use selenium if it is HTML based, maybe with nightwatch.js. By testing a real REST API, you'll need an automated browser, like selenium for your REST API implementation, which can select and follow the proper links. If you are developing the REST API you would write a browser like that anyways if you want an example client for your 3rd party client developers.

REST Web Services API Design

Just wanted to get feedback on how I am planning to architect my API. Dummy methods below. Here's the structure:
GET http://api.domain.com/1/users/ <-- returns a list of users
POST http://api.domain.com/1/users/add.xml <-- adds user
POST http://api.domain.com/1/users/update.xml <-- updates user
DELETE (or POST?) http://api.domain.com/1/users/delete.xml <-- deletes user
Questions:
Is it OK to use just GET and POST?
Is it a good idea that I plan to rely on the filename to indicate what operation to do (e.g. add.xml to add)? Would it be better to do something like this: POST http://api.domain.com/1/users/add/data.xml?
What's a good way to keep these resources versioned? In my example, I use a /1/ after domain name to indicate version 1. Alternatives would be: http://api1.domain.com... or http://api-1.domain.com... or http://apiv1.domain.com... or http://api-v1.domain.com... or http://api.domain.com/v1/... or
What's the best way to authenticate?
Before you dig into REST, here are some terms you really need to grasp:
Resource - The things/data you want to make available in your API (in your case a "User")
URI - A universally unique ID for a resource. Should mention nothing about the method being performed (e.g. shouldn't contain "add" or "delete"). The structure of your URI however doesn't make your app any more or less RESTful - this is a common misconception.
Uniform Interface - A fixed set of operations you can perform on your resources, in most cases this is HTTP. There are clear definitions for the purpose of each of these HTTP methods.
The most unrestful thing about your URIs as they are right now is that they have information about the operation being performed right in them. URIs are IDs and nothing more!
Let's take a real world example. My name is Nathan. "Nathan" could be considered my ID (or in restful terms URI – for the purpose of this example assume I'm the only "Nathan"). My name/ID doesn't changed based on how you would like to interact with me, e.g. My name wouldn't change to "NathanSayHello" when you wanted to greet me.
It's the same for REST. Your user identified by http://api.domain.com/users/1 doesn't change to http://api.domain.com/users/1/update.xml when you want to update that user. The fact that you want to update that user is implied by the method you're using (e.g. PUT).
Here is my suggestion for your URIs
# Retrieve info about a user
GET http://api.domain.com/user/<id>
# Retrieve set all users
GET http://api.domain.com/users
# Update the user IDed by api.domain.com/user/<id>
PUT http://api.domain.com/user/<id>
# Create a new user. The details (even <id>) are based as the body of the request
POST http://api.domain.com/users
# Delete the user ID'd by api.domain.com/user/<id>
DELETE http://api.domain.com/user/<id>
As for your questions:
Use PUT and DELETE when appropriate and avoid overloading POST to handle these functions as it breaks HTTP's definition of POST. HTTP is your uniform interface. It is your contract with the API user about how they can expect to interact with your service. If you break HTTP, you break this contract.
Remove "add" altogether. Use HTTP's Content-Type header for specifying the mime-type of posted data.
Are you referring to the version of your API or the version of the resource? ETag and other response headers can be used to version the resources.
Many options here. Basic HTTP Auth (easy but insecure), Digest Auth, custom auth like AWS. OAuth is also a possibility. If security is of main importance, I use client side SSL certs.
1) On your design probably not. POST is not idempotent! So you should not use for the update or the delete, instead use PUT and DELETE from Rest
2) A better choice is to use the header Content-Type on the WS call, like: application/xml
3) Also on the header Content-Type u can use it: application-v1.0/xml
4) Not sure if it is the best, but probably the easiest way is to use HTTP's built-in authentication mechanisms in RFC 2617. An example: AWS Authentication
In REST, the HTTP "verb" is used to denote the operation type: you won't be able to express all the CRUD operations with only "GET" and "POST"
no: the URL of the resource is usually where the "document identifier" should appear
The version of the "document" can be transmitted in an HTTP response header upon creation/modification of the said resource. It should be the duty of the server to uniquely identify the resources - trying to do this on the client side will prove a daunting challenge i.e. keeping consistency.
Of course, there are many variations on the topic...
I did authentication based on headers. Something like
X-Username:happy-hamster
X-Password:notmyactualpassword
If you're concerned about security - do it through SSL.
Other implementations exist, of course. For instance, Amazon with their S3:
http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTAuthentication.html
If you don't have ability to make PUT and DELETE requests, it's considered a good practice to tunnel them through POST. In this case the action is specified in URL. If I recall correctly, RoR does exactly this:
POST http://example.com/foos/2.xml/delete
or
POST http://example.com/foos/3.xml/put
...
<foo>
<bar>newbar</bar>
</foo>
It's a bit offtop, but in regards to versioning and REST overall you might want to take a look at CouchDB. Here is a good book available on-line
Using post for create and delete functionality is not a good rest api design strategy. Use Put to create, post to update and delete to delete the resources.
For more information on designing rest apis follow the link - best practices to design rest apis

Can I change the headers of the HTTP request sent by the browser?

I'm looking into a restful design and would like to use the HTTP methods (POST, GET, ...) and HTTP headers as much as possible. I already found out that the HTTP methods PUT and DELETE are not supported from the browser.
Now I'm looking to get different representations of the same resource and would like to do this by changing the Accept header of the request. Depending on this Accept header, the server can serve a different view on the same resource.
Problem is that I didn't find a way to tell my browser to change this header.
The <a..> tag has a type attribute, that can have a mime type, looked like a good candidate but the header was still the browser default (in Firefox it can be changed in about:config with the network.http.accept.default key).
I would partially disagree with Milan's suggestion of embedding the requested representation in the URI.
If anyhow possible, URIs should only be used for addressing resources and not for tunneling HTTP methods/verbs. Eventually, specific business action (edit, lock, etc.) could be embedded in the URI if create (POST) or update (PUT) alone do not serve the purpose:
POST http://shonzilla.com/orders/08/165;edit
In the case of requesting a particular representation in URI you would need to disrupt your URI design eventually making it uglier, mixing two distinct REST concepts in the same place (i.e. URI) and making it harder to generically process requests on the server-side. What Milan is suggesting and many are doing the same, incl. Flickr, is exactly this.
Instead, a more RESTful approach would be using a separate place to encode preferred representation by using Accept HTTP header which is used for content negotiation where client tells to the server which content types it can handle/process and server tries to fulfill client's request. This approach is a part of HTTP 1.1 standard, software compliant and supported by web browsers as well.
Compare this:
GET /orders/08/165.xml HTTP/1.1
or
GET /orders/08/165&format=xml HTTP/1.1
to this:
GET /orders/08/165 HTTP/1.1
Accept: application/xml
From a web browser you can request any content type by using setRequestHeader method of XMLHttpRequest object. For example:
function getOrder(year, yearlyOrderId, contentType) {
var client = new XMLHttpRequest();
client.open("GET", "/order/" + year + "/" + yearlyOrderId);
client.setRequestHeader("Accept", contentType);
client.send(orderDetails);
}
To sum it up: the address, i.e. the URI of a resource should be independent of its representation and XMLHttpRequest.setRequestHeader method allows you to request any representation using the Accept HTTP header.
Cheers!
Shonzilla
I was looking to do exactly the same thing (RESTful web service), and I stumbled upon this firefox addon, which lets you modify the accept headers (actually, any request headers) for requests. It works perfectly.
https://addons.mozilla.org/en-US/firefox/addon/967/
I don't think it's possible to do it in the way you are trying to do it.
Indication of the accepted data format is usually done through adding the extension to the resource name. So, if you have resource like
/resources/resource
and GET /resources/resource returns its HTML representation, to indicate that you want its XML representation instead, you can use following pattern:
/resources/resource.xml
You have to do the accepted content type determination magic on the server side, then.
Or use Javascript as James suggests.
ModHeader extension for Google Chrome, is also a good option. You can just set the Headers you want and just enter the URL in the browser, it will automatically take the headers from the extension when you hit the url. Only thing is, it will send headers for each and every URL you will hit so you have to disable or delete it after use.
Use some javascript!
xmlhttp=new XMLHttpRequest();
xmlhttp.open('PUT',http://www.mydomain.org/documents/standards/browsers/supportlist)
xmlhttp.send("page content goes here");