REST is not a standard, therefore you are free to choose how to use it. It's very hard to say, if you do something "100% right" or "100% wrong". And still there are good RESTful APIs and bad RESTful APIs. Probably the most important part of your RESTful API are the URLs. They identify your resources. Good designed URLs make your API look good.
And here come some practices that I personally believe are best (or just good):
1. URL must uniquely identify the resource - it should be impossible using the same URL to access two different resources based on something else (e.g. header).
Example: suppose we design a RESTful API for a library. Let's say the url /books/ABC returns Winnie the Pooh for a registered user. A very BAD practice would be, if the unregistered user will get a different book for the same url. It should not matter who is the user, the same url should lead to the same book.
Now, of course our application may have security implications, so for example registered user can see the book and unregistered cannot. It's ok, return 404 NOT FOUND for unregistered user. Or eliminate the book from the book search. But NEVER return a different resource.
2. URL should be designed for further API changes - this one is kinda tricky. Suppose a registered user can add some books to a favorite list. What URL will be used?
Option 1: "/user/{userid}/favorites/" will return favorites list of a user. Sounds reasonable. But what happens if we decide to extend this feature and allow a user have multiple list, what will return this url now?
Option 2: "/user/{userid}/favorites/" will return a list of the favorites lists and "/user/{userid}/favorites/{id}" will return the specific list. Sounds reasonable. But what happens if we add a feature that allows user to share lists? Actually here we got to the point I'll discuss in the next bullet, but it's quite clear here that "/user/{userid}" should not be part of the url, right?
Option 3: "/favorites/" will return a list of the favorites lists and "/favorites/{id}" will return the specific list. Both "/favorites/" and "/favorites/{id}" resources will return the lists based on the user's privileges: the system administrator will see all lists, the user will see his lists the ones that were shared with him.
3. Security is not part of the resource identification and therefore should not be a part of the URL - in the previous bullet I have already described why adding a userid to the url is problematic. Let's talk about it a little bit more. First, you cannot rely "userid" present in the url in order to identify the user. You need a different form of authentication (unless you use username+password authentication and you put a password also in url, it's possible, but it's really a VERY BAD practice). Furthermore, the good api should not contain the definition of an authentication method within it at all. It should be possible to change the authentication method without changing the API (for example it quite common in the last few years to move from username+password to OAuth authentication). Basically the API should expect to receive the userid always, but not as an integral part of an API! With HTTP it's quite easy to put the security related stuff in the headers, and to keep the url clean.
4. If you must put additional metadata on URL, put it as a query parameter - In general all metadata you have (like security, content-type, accept content-type) should be in headers. However, sometimes it for some technical reasons it become impossible to put it in a header, so you must use URL. It's ok, but put it after the question mark in the query parameters part. Thus it becomes "optional" part and can be easily changed or removed if not needed later.
Showing posts with label web-services. Show all posts
Showing posts with label web-services. Show all posts
Wednesday, April 11, 2012
Monday, December 1, 2008
Open WebDAV from Windows
WebDAV stands for "Web-based Distributed Authoring and Versioning". It is a set of extensions to the HTTP protocol that lets users collaboratively edit and manage files on a remote web server.
This post summarizes the ways to open WebDAV folders:
1. WebDAV plug-in for Total Commander: http://ghisler.fileburst.com/fsplugins/webdav.zip
2. It's possible to use Window's built-in support: My Network Places / Add Network Place
3. Another option to use IE: File -> Open and check the "Open as Web Folder" checkbox.
This post summarizes the ways to open WebDAV folders:
1. WebDAV plug-in for Total Commander: http://ghisler.fileburst.com/fsplugins/webdav.zip
2. It's possible to use Window's built-in support: My Network Places / Add Network Place
3. Another option to use IE: File -> Open and check the "Open as Web Folder" checkbox.
Tuesday, November 25, 2008
Axis: Creating Stub with custom WSDD file
And here is another Axis (1.4) tip:
In order to create a stub with a custom WSDD file you'll need to do the following:
In the client side there is a bug in parsing wsdd: when the handlers are configured in the service flow and service contains additional configuration (e.g. provider, style, user, mappings, etc.), the handler will not run. This happens since client configuration does not contain className with the service implementation class.
It's possible to put "dummy" class name. But the better solution is to configure handler in the global flow.
In order to create a stub with a custom WSDD file you'll need to do the following:
import org.apache.axis.configuration.FileProvider;
import java.io.File;
import java.io.InputStream;
.
.
InputStream is = new FileInputStream(new File("D:/custom-client-config.wsdd"));
MyServiceLocator locator = new MyServiceLocator(new FileProvider(is));
Pay Attention!
In the client side there is a bug in parsing wsdd: when the handlers are configured in the service flow and service contains additional configuration (e.g. provider, style, user, mappings, etc.), the handler will not run. This happens since client configuration does not contain className with the service implementation class.
It's possible to put "dummy" class name. But the better solution is to configure handler in the global flow.
Wednesday, May 14, 2008
How to use SAML with REST Web Services
The Problem
OASIS Web Services Security describes how to use SAML with SOAP web services. The signed SAML Assertion should be added to the SOAP header... and so on. However, there is no specification that describes how to add SAML to REST web services. The reason that there is no such specification is simple: REST is not a standard, but it's an architectural style. So it's impossible to define standard that is not based on standard.
And still we would like to support SAML for our REST web services. Why? The same reason we support SAML for SOAP web services: it's a standard, it's convenient, many frameworks start to support it and so on.
The Solution
The solution is quite simple. Since REST web services are based on HTTP protocol we can use the HTTP Redirect Binding (see SAML Bindings, 3.4) to send the Unsolicited Responses (see SAML Profiles, 4.1.5). Since there is no problem to add the necessary query parameters to any HTTP method, the HTTP Redirect Binding with Unsolicited Responses covers the same scenario we have with SOAP without defining the additional standards.
Concerns
The only concern I have about this solution is the url length. Theoretically the url length is infinite, but of cause it cannot be supported. Each vendor limits the url length in its way and if the SAML Response will be very long, it may cause the url to be truncated. Which will cause failure to parse or validate the SAML Response.
Conclusion
Unless we send very long messages, we can send SAML with REST web services using the HTTP Redirect Binding. Although it is not a standard, it still a standard way to do things and it should work.
Who do you think?

2. REST in Practice: Hypermedia and Systems Architecture
3. Securing Web Services with WS-Security: Demystifying WS-Security, WS-Policy, SAML, XML Signature, and XML Encryption
OASIS Web Services Security describes how to use SAML with SOAP web services. The signed SAML Assertion should be added to the SOAP header... and so on. However, there is no specification that describes how to add SAML to REST web services. The reason that there is no such specification is simple: REST is not a standard, but it's an architectural style. So it's impossible to define standard that is not based on standard.
And still we would like to support SAML for our REST web services. Why? The same reason we support SAML for SOAP web services: it's a standard, it's convenient, many frameworks start to support it and so on.
The Solution
The solution is quite simple. Since REST web services are based on HTTP protocol we can use the HTTP Redirect Binding (see SAML Bindings, 3.4) to send the Unsolicited Responses (see SAML Profiles, 4.1.5). Since there is no problem to add the necessary query parameters to any HTTP method, the HTTP Redirect Binding with Unsolicited Responses covers the same scenario we have with SOAP without defining the additional standards.
Concerns
The only concern I have about this solution is the url length. Theoretically the url length is infinite, but of cause it cannot be supported. Each vendor limits the url length in its way and if the SAML Response will be very long, it may cause the url to be truncated. Which will cause failure to parse or validate the SAML Response.
Conclusion
Unless we send very long messages, we can send SAML with REST web services using the HTTP Redirect Binding. Although it is not a standard, it still a standard way to do things and it should work.
Who do you think?
Recommended Reading
1. Restful Web Services2. REST in Practice: Hypermedia and Systems Architecture
3. Securing Web Services with WS-Security: Demystifying WS-Security, WS-Policy, SAML, XML Signature, and XML Encryption
Subscribe to:
Posts (Atom)