What should be the default version if I have many versions for a REST api? - http

I have a REST api that will accept a version via a custom HTTP header or a request parameter. I'm doing this because I don't want the URI to contain the version like del.icio.us .e.g http://server/api/v1/...
Now in my design, the HTTP header has a higher priority than the request param.
What happens then if the user does not supply any version at all ?
Should I default to the oldest version, or default to the latest version ?

Don't version the URI at all. Instead just version the representation. This way the client can decide which version of the API they want to use and it degrades well.
Example:
GET /contacts/3 HTTP/1.1
Accept: application/myapp-v2+xml
HTTP/1.1 200 OK
Content-Type: application/myapp-v2+xml

Why not simply make the version required and throw an error if it's not there?
If that's not an option then you have to go with the oldest version, otherwise if you upgrade and don't maintain backwards compatability you'll break existing clients.
Of course, if you don't mind breaking existing clients it might be more convenient to go with the latest version.

If your API defines specific URIs or URI naming conventions for accessing resources, your API is not RESTful. Versioning of URI construction is a non-issue for any REST API. Please see http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven for more information.

Related

How do I discover what content types a HTTP POST service allows?

I am writing a client for OpenTox webservices, but several services they provide have optional support for certain MIME types with only a few obligatory, e.g. this Dataset service. So I need to discover which of those content types are supported by a particular running service dynamically...
Now, for GET services I can use the "Accepts" HTTP header and when I POST content I can use "Content-type" to set what format I am sending in. But I rather not default into trial-and-error, as these data sets can be large. Therefore, I like to know up front the best MIME type I can use.
How do I perform content negotiation with POST services? I am using the Apache HttpClient, but that is not important for the answer.
POSTed Content negotiation is not enshrined in the HTTP specification; instead what is advisable is to use the OPTIONS method. This is exactly the case in the OpenTox framework: OPTIONS has to be implemented by all web services. The service returns an RDF document (according to the Accept Header you specify) and a WADL-like content, i.e. it returns machine-readable documentation specifying the available MIME types, the possible HTTP status codes etc. Unfortunately so far there's only one implementation of OPTIONS in OpenTox, namely JAQPOT3. Check out this wiki entry.

HTTP Status 412 (Precondition Failed) and Database Versioning

I am implementing a RESTful web service that accesses a database. Entities in the database are versioned to detect multiple updates. For instance, if the current value is {"name":"Bill", "comment":"tinker", "version":3}, if one user PUTs {"name":"Bill", "comment":"tailor", "version":3}, the request will succeed (200 OK) and the new value will be {"name":"Bill", "comment":"tailor", "version":4}. If a second user PUTs {"name":"Bill", "comment":"sailor", "version":3"} that request will fail (409 Conflict) because the version number does not match.
There are existing non-RESTful interfaces, so the design of the databases cannot be changed. The RESTful interface calls an existing interface that handles the details of checking the version.
A rule of thumb in RESTful web services is to follow the details of HTTP whenever possible. Would it be better in this case to use a conditional header in the request and return 412 Precondition Failed if the version does not match? The appropriate header appears to be If-Match. This header takes an ETag (Entity Tag) which could be a hash of the representation of the current state of the resource.
If I did this, the ETags would be for appearances' sake, because the version would still be the real thing I'm testing for.
Is there any reason I should do this, other than "making it more RESTful", whatever that is supposed to mean?
The appropriate thing to do is always to follow the HTTP spec if you're using HTTP, and the reason is simply to allow people who understand the spec to function correctly.
412 should only be used if a precondition (e.g. If-Match) caused the version matching to fail, whereas 409 should be used if the entity would cause a conflict (the HTTP spec itself alludes to this behaviour in the definition of 409).
Therefore, a client that doesn't send ETags won't be expecting a 412. Conversely, a client that does send ETags won't understand that it's ETags that are causing a 409.
I would stick with one way. You say that "the database schema can't change", but that doesn't stop you (right in the HTTP server layer) to extract the version from the datbase representation and put it in the ETag, and then on the way in, take the If-Match header and put it back in the version field.
But doing it completely in the entity body itself isn't forbidden. It just requires you to explain the concept and how it works, whereas with the ETag solution you can just point people to the HTTP spec.
Edit: And the version flag doesn't have to be a hash of the current resource; a version is quite acceptable. ETag: "3" is a perfectly valid ETag.

HOWTO override Axis2 request headers for .NET web service?

I have to use a 3rd party web service implemented in .NET 2.0 (on IIS, of course).
I have to make a java client. I am using wsdl2java to generate the SOAP stub.
As the original Apache Axis project now appears unmaintained, and I was having some problems parsing some responses from the service, I converted the client to use the latest (1.5) version of Axis2. Now, the .NET service won't even recognize my requests.
I managed to get the "chunking" turned off (where "stub" is a variable of type MumbleStub generated by wsdl2java, and I am showing what are several lines of code as one horrific line here):
stub._getServiceClient().getOptions().setProperty( HTTPConstants.CHUNKED, Boolean.FALSE);
.. so at least the service recognizes my request AS a request, albeit a bad one: "HTTP/1.1 400 Bad Request" is the response now (as opposed to an "intro / summary" page offering me a link to the WSDL).
I noticed that the Axis ("1") request had a different Content-TYpe header (text/xml, vs application/soap-xml), and I am wondering how to change this request header, if that is in fact the problem.
Alternately, has anybody else had this problem? Is the problem really the (undisplayable here, as it looks like "element injection" to the blog engine) ... xml version-"1.0" ... "XML meta intro tag" that Axis2 added to the beginning of the request?
WS-Deathstar, indeed.
As you mention the different content-type header I guess your client tries to send SOAP 1.2 requests and the 3rd party app only understands SOAP 1.1
Try changing the used soap version as AFAIK AXIS2 uses SOAP 1.2 by default
stub._getServiceClient().getOptions().setSoapVersionURI(org.apache.axiom.soap.SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI);

append conditional html file output with xml response

hey guys i have a restful xml service where client passes current version of html they are viewing. if the version on the server is the same as the client, i just respond with the current server version in xml. example: <Response ServerHTMLVersion="1" />
however if server html version is greater than current client version, i still spit out the same response like above like <Response ServerHTMLVersion="2" />. but problem being my client application needs to do a seperate http request to download the html file incase response xml version is greater than clients version
for performance reasons, i wanted to cut down this http request and i wanted to know what is the best way to do this. should i simply encode the html to make it xml safe and append that with xml response - problem with this being html is FAT and encoding makes it even fatter
OR
is there a better way of managing this? note that i am already gziping my response for both, xml as well as html right now
i wanted to know the way to do this keeping performance in mind. the restful xml service is implemented via asp.net 3.5 and iis 7
Have you thought about using HTTP headers? Since really the primary data here is the HTML, and the ServerHTMLVersion is a sort of "meta data" about that html, it should work.
Personally, I'd make the response to the request 1) blank when the versions match and 2) the HTML for non-matching versions; then, use the Pragma HTTP header to send something like Pragma: "ServerHTMLVersion=2". By doing this, you can easily check if the client and server versions differ, and just grab the full response if they're different.
Some people would debate the idea of returning HTML from a REST service, but I personally would consider this totally valid, and an nice clean way of separating your meta data from the actual user data.
-Jerod

Passing params in the URL when using HTTP POST

Is it allowable to pass parameters to a web page through the URL (after the question mark) when using the POST method? I know that it works (most of the time, anyways) because my company's webapp does it often, but I don't know if it's actually supported in the standard or if I can rely on this behavior. I'm considering implementing a SOAP request handler that uses a parameter after the question mark to indicate that it is a SOAP request and not a normal HTTP request. The reason for this that the webapp is an IIS extension, so everything is accessed via the same URL (ex: example.com/myisapi.dll?command), so to get the SOAP request to be processed, I need to specify that "command" parameter. There would be one generic command for SOAP, not a specific command for each SOAP action -- those would be specified in the SOAP request itself.
Basically, I'm trying to integrate the Apache Axis2/C library into my webapp by letting the webapp handle the HTTP request and then pass off the incoming SOAP XML to Axis2 for handling if it's a SOAP request. Intuitively, I can't see any reason why this wouldn't work, since the URL you're posting to is just an arbitrary URL, as far as all the various components are concerned... it's the server that gives special meaning to the parts after the question mark.
Thanks for any help/insight you can provide.
Lets start with the simple stuff. HTTP GET request variables come from the URI. The URI is a requested resource, and so any webserver should (and apache does) have the entire URI stored in some variable available to the modules or appserver components running within the webserver.
An http POST which is different from an http GET is a separate logical call to the webserver, but it still defines a URI that should process the post. A good webserver (apache being one) will again make the URI available to whatever module or appserver is running within it, then will additionally make available the variables which were sent in the POST headers.
At the point where your application takes control from apache during a POST you should have access to both the GET and POST variables and be able to do whatever control logic you wish, including replying with a SOAP protocol instead of HTML.
If you are asking whether it is possible to send parameters via both GET and POST in a single HTTP request, then the answer is "YES". This is standard functionality that can be used reliably AFAIK.
One such example is sending authentication credentials in two pieces, one over GET and the other through POST so that any attempt to hijack a session would require hijacking both the GET and POST variables.
So in your case, you can use POST to contain the actual SOAP request but test for whether it is a SOAP request based on the parameter passed in GET (or in other words through the URL).
I believe that no standard actually defines the concept of "HTTP parameters" or "request variables". RFC 1738 defines that an URL may have a "search part", which is the substring after the question mark. HTML specifies in the form submission protocol how a browser processing a FORM element should submit it. In either case, how the server-side processes both the search part and the HTTP body is entirely up to the server - discarding both would be conforming to these two specs (but fairly useless).
In order to determine whether you can post a search part to a specific service, you need to study this service's protocol specification. If the service is practically defined by means of a HTML form, then you cannot use a mix - you can't even use POST if the FORM specifies GET (and vice versa). If you post to a web service, you need to look at the web service's WSDL - which will typically mandate POST; with all data in a SOAP message. Etc.
Specific web frameworks may have the notion of "request variables" - whether they will draw these variables both from a search part and a request body, you need to find out in the product documentation.
I deployed a web application with 3 (a mobile network operator) in the UK. It originally used POST parameters, but the 3 gateway stripped them (and X-headers as well!). So beware...
allowable? sure, it's doable, but i'm leaning towards the spec suggesting dual methods isn't necessarily supposed to happen, or be supported. RFC2616 defines HTTP/1.1, and i would argue suggests only one method per request. if you think about your typical HTTP transaction from the client side, you can see the limitation as well:
$ telnet localhost 80
POST /page.html?id=5 HTTP/1.1
host: localhost
as you can see, you can only use one method (POST/GET, etc...), however due to the nature of how various languages operate, they may pick up the query string, and assign it to the GET variable. ultimately though, this is a POST request, and not a GET.
so basically, yes this functionality exists, is it intended? i would say no.

Resources