Is it bad practice to put a period in a URI path? - rest

I am designing a REST API for a web application. I want to clearly version the API, so that the interface can be changed in the future without breaking existing services. So in my v1.0 API, I want to clearly identify it as the v1.0 API, leaving me the freedom to release a future v1.1 version with breaking changes.
My question is, would a period in the path component of a URI be bad practice?
eg. Is there any good reason not to use http://example.com/myapi/v1.0/services as a URI to my service?

Putting a period in the URI is perfectly fine. Putting a version number in an URI is definitely not a best practice.
Here are my reasons why and here is an good article on the subject by someone much smarter than me.

It is perfectly acceptable to use a period in a URI path. It is also valid as per RFC 3986 section 2.3.

its a perfectly valid path character, see page 27 of the spec http://www.ietf.org/rfc/rfc2396.txt
No reason not to use it

I think differently of the others... I don't think it is a good practice to use it on the url.
IMHO it is way better if you version on the Content-Type Header.
As an example, if you are using application/xml:
Content-Type: application/v1.0+xml.
Using the Content-Type, it also indicates that the resource itself is versioned. While if you use it on the url it seems that you are versioning the service (which doesn't seem to be so), and if you are changing the service itself you will probably change the url, so you don't need the version number.
EDIT: You should also use it on the Accept Header, not only on the Content Type.

I think it is a good idea. I've seen several rest services that do this.

Related

If I specify API version in the URL, should I offer an option to have it in the header as well?

I'm designing my API, and I specify an optional API version in the URL
GET /Issuer/{certificate-name}/versions?api-version=2016-10-01[&maxresults]
Should I also have one specified in the HTTP Header (for flexibility)?
What should I do if there is a conflict between the two approaches?
There is no obvious advantage to allowing an input of API version from 2 different input methods (querystring, and Header). However, the disadvantage here is conflict resolution if both are specified by the client.
There is no right or wrong way of where an API version should be specified, whether in the header or the querystring. But keep in mind that URLs require parsing, while mostly done the by framework, but still a compute resource you are spending to parse the URL to extract the value from.
I (personally) prefer using the header out of simplicity. Plus it feels more cleaner to keep the URL as an address only to point to the function/intent of the client.

In general, is it good practice to fail a REST request if the request body includes extra parameters?

e.g. for the following POST request
POST: /someListOfObjects/
BODY: {
correctProperty: 'good value',
extraProperty: "this property doesn't map to the underlying entity"
}
Should the API return a 400: Bad Request, or just ignore the extraProperty
I guess the correct answer is: it depends.
But I would definitely chose to ignore the extraProperty most of the time. The beautiful thing about REST APIs is that they are flexible, and you can make them backward and forward compatible without much trouble. So, if you end up restricting too many things on clients, it will probably be a little bit more difficult to make changes without breaking existing clients.
Also, most of the time I would not use posting a JSON object directly to my API. I would use form encoding, and get the parameters, one by one.
I don't think that's settled in the community. My personal preference would be to return an error code. Whatever you do, be consistent across the entire API.
There are a couple of factors that I use to determine how strict I should be with an API:
Versioning - Is the API supposed to be backwards/forwards compatible? If so, then ignoring extra properties might not only be a good decision, it is probably one of the only ways you can support version compatibility.
Security - Is your API supposed to be a trusted service? If it is an authentication API, for instance, it might not make sense to have such a relaxed input policy.
If I go to a bank to withdraw money but talk constantly about the weather with the cashier while I'm doing it, I should still get my money.
For most applications, extra parameters could easily be ignored. If you want to write a stricter application then put something extra in the response payload that hints to the client that they aren't doing things perfectly correctly.
Cherry pick the ones you want, make sure they're safe and secure, and throw away the rest if you're not using it or them.

Versioning REST API

After having read a lot of material on REST versioning, I am thinking of versioning the calls instead of the API. For example:
http://api.mydomain.com/callfoo/v2.0/param1/param2/param3
http://api.mydomain.com/verifyfoo/v1.0/param1/param2
instead of first having
http://api.mydomain.com/v1.0/callfoo/param1/param2
http://api.mydomain.com/v1.0/verifyfoo/param1/param2
then going to
http://api.mydomain.com/v2.0/callfoo/param1/param2/param3
http://api.mydomain.com/v2.0/verifyfoo/param1/param2
The advantage I see are:
When the calls change, I do not have to rewrite my entire client - only the parts that are affected by the changed calls.
Those parts of the client that work can continue as is (we have a lot of testing hours invested to ensure both the client and the server sides are stable.)
I can use permanent or non-permanent redirects for calls that have changed.
Backward compatibility would be a breeze as I can leave older call versions as is.
Am I missing something? Please advise.
Require an HTTP header.
Version: 1
The Version header is provisionally registered in RFC 4229 and there some legitimate reasons to avoid using an X- prefix or a usage-specific URI. A more typical header was proposed by yfeldblum at https://stackoverflow.com/a/2028664:
X-API-Version: 1
In either case, if the header is missing or doesn't match what the server can deliver, send a 412 Precondition Failed response code along with the reason for the failure. This requires clients to specify the version they support every single time but enforces consistent responses between client and server. (Optionally supporting a ?version= query parameter would give clients an extra bit of flexibility.)
This approach is simple, easy to implement and standards-compliant.
Alternatives
I'm aware that some very smart, well-intentioned people have suggested URL versioning and content negotiation. Both have significant problems in certain cases and in the form that they're usually proposed.
URL Versioning
Endpoint/service URL versioning works if you control all servers and clients. Otherwise, you'll need to handle newer clients falling back to older servers, which you'll end up doing with custom HTTP headers because system administrators of server software deployed on heterogeneous servers outside of your control can do all sorts of things to screw up the URLs you think will be easy to parse if you use something like 302 Moved Temporarily.
Content Negotiation
Content negotiation via the Accept header works if you are deeply concerned about following the HTTP standard but also want to ignore what the HTTP/1.1 standard documents actually say. The proposed MIME Type you tend to see is something of the form application/vnd.example.v1+json. There are a few problems:
There are cases where the vendor extensions are actually appropriate, of course, but slightly different communication behaviors between client and server doesn't really fit the definition of a new 'media type'. Also, RFC 2616 (HTTP/1.1) reads, "Media-type values are registered with the Internet Assigned Number Authority. The media type registration process is outlined in RFC 1590. Use of non-registered media types is discouraged." I don't want to see a separate media type for every version of every software product that has a REST API.
Any subtype ranges (e.g., application/*) don't make sense. For REST APIs that return structured data to clients for processing and formatting, what good is accepting */* ?
The Accept header takes some effort to parse correctly. There's both an implied and explicit precedence that should be followed to minimize the back-and-forth required to actually do content negotiation correctly. If you're concerned about implementing this standard correctly, this is important to get right.
RFC 2616 (HTTP/1.1) describes the behavior for any client that does not include an Accept header: "If no Accept header field is present, then it is assumed that the client accepts all media types." So, for clients you don't write yourself (where you have the least control), the most correct thing to do would be to respond to requests using the newest, most prone-to-breaking-old-versions version that the server knows about. In other words, you could have not implemented versioning at all and those clients would still be breaking in exactly the same way.
Edited, 2014:
I've read a lot of the other answers and everyone's thoughtful comments; I hope I can improve on this with the benefit of a couple of years of feedback:
Don't use an 'X-' prefix. I think Accept-Version is probably more meaningful in 2014, and there are some valid concerns about the semantics of re-using Version raised in the comments. There's overlap with defined headers like Content-Version and the relative opaqueness of the URI for sure, and I try to be careful about confusing the two with variations on content negotiation, which the Version header effectively is. The third 'version' of the URL https://example.com/api/212315c2-668d-11e4-80c7-20c9d048772b is wholly different than the 'second', regardless of whether it contains data or a document.
Regarding what I said above about URL versioning (endpoints like https://example.com/v1/users, for instance) the converse probably holds more truth: if you control all servers and clients, URL/URI versioning is probably what you want. For a large-scale service that could publish a single service URL, I would go with a different endpoint for every version, like most do. My particular take is heavily influenced by the fact that the implementation as described above is most commonly deployed on lots of different servers by lots of different organizations, and, perhaps most importantly, on servers I don't control. I always want a canonical service URL, and if a site is still running the v3 version of the API, I definitely don't want a request to https://example.com/v4/ to come back with their web server's 404 Not Found page (or even worse, 200 OK that returns their homepage as 500k of HTML over cellular data back to an iPhone app.)
If you want very simple /client/ implementations (and wider adoption), it's very hard to argue that requiring a custom header in the HTTP request is as simple for client authors as GET-ting a vanilla URL. (Although authentication often requires your token or credentials to be passed in the headers, anyway. Using Version or Accept-Version as a secret handshake along with an actual secret handshake fits pretty well.)
Content negotiation using the Accept header is good for getting different MIME types for the same content (e.g., XML vs. JSON vs. Adobe PDF), but not defined for versions of those things (Dublin Core 1.1 vs. JSONP vs. PDF/A). If you want to support the Accept header because it's important to respect industry standards, then you won't want a made-up MIME Type interfering with the media type negotiation you might need to use in your requests. A bespoke API version header is guaranteed not to interfere with the heavily-used, oft-cited Accept, whereas conflating them into the same usage will just be confusing for both server and client. That said, namespacing what you expect into a named profile per 2013's RFC6906 is preferable to a separate header for lots of reasons. This is pretty clever, and I think people should seriously consider this approach.
Adding a header for every request is one particular downside to working within a stateless protocol.
Malicious proxy servers can do almost anything to destroy HTTP requests and responses. They shouldn't, and while I don't talk about the Cache-Control or Vary headers in this context, all service creators should carefully consider how their content is consumed in lots of different environments.
This is a matter of opinion; here's mine, along with the motivation behind the opinion.
include the version in the URL.
For those who say, it belongs in the HTTP header, I say: maybe. But putting in the URL is the accepted way to do it according to the early leaders in the field. (Google, yahoo, twitter, and more). This is what developers expect and doing what developers expect, in other words acting in accordance with the principle of least astonishment, is probably a good idea. It absolutely does not make it "harder for clients to upgrade". If the change in URL somehow represents an obstacle to the developer of a consuming application, as suggested in a different answer here, that developer needs to be fired.
Skip the minor version
There are plenty of integers. You're not gonna run out. You don't need the decimal in there. Any change from 1.0 to 1.1 of your API shouldn't break existing clients anyway. So just use the natural numbers. If you like to use separation to imply larger changes, you can start at v100 and do v200 and so on, but even there I think YAGNI and it's overkill.
Put the version leftmost in the URI
Presumably there are going to be multiple resources in your model. They all need to be versioned in synchrony. You can't have people using v1 of resource X, and v2 of resource Y. It's going to break something. If you try to support that it will create a maintenance nightmare as you add versions, and there's no value add for the developer anyway. So, http://api.mydomain.com/v1/Resource/12345 , where Resource is the type of resource, and 12345 gets replaced by the resource id.
You didn't ask, but...
Omit verbs from your URL path
REST is resource oriented. You have things like "CallFoo" in your URL path, which looks suspiciously like a verb, and unlike a noun. This is wrong. Use the Force, Luke. Use the verbs that are part of REST: GET PUT POST DELETE and so on. If you want to get the verification on a resource, then do GET http://domain/v1/Foo/12345/verification. If you want to update it, do POST /v1/Foo/12345.
Put optional params as a query param or payload
The optional params should not be in the URL path (before the first question mark) unless you are suggesting that those optional params constitute a self-standing resource. So, POST /v1/Foo/12345?action=partialUpdate&param1=123&param2=abc.
Don't do either of those things, because they push the version into the URI structure, and that's going to have downsides for your client applications. It will make it harder for them to upgrade to take advantage of new features in your application.
Instead, you should version your media types, not your URIs. This will give you maximum flexibility and evolutionary ability. For more information, see this answer I gave to another question.
I like using the profile media type parameter:
application/json; profile="http://www.myapp.com/schema/entity/v1"
More Info:
https://www.rfc-editor.org/rfc/rfc6906
http://buzzword.org.uk/2009/draft-inkster-profile-parameter-00.html
It depends on what you call versions in your API, if you call versions to different representations (xml, json, etc) of the entities then you should use the accept headers or a custom header. That is the way http is designed for working with representations. It is RESTful because if I call the same resource at the same time but requesting different representations, the returned entities will have exactly the same information and property structure but with different format, this kind of versioning is cosmetic.
In the other hand if you understand 'versions' as changes in entity structure, for example adding a field 'age' to the 'user' entity. Then you should approach this from a resource perspective which is in my opinion the RESTful approach. As described by Roy Fielding in his disseration ...a REST resource is a mapping from an identifier to a set of entities... Therefore makes sense that when changing the structure of an entity you need to have a proper resource that points to that version. This kind of versioning is structural.
I made a similar comment in: http://codebetter.com/howarddierking/2012/11/09/versioning-restful-services/
When working with url versioning the version should come later and not earlier in the url:
GET/DELETE/PUT onlinemall.com/grocery-store/customer/v1/{id}
POST onlinemall.com/grocery-store/customer/v1
Another way of doing that in a cleaner way but which could be problematic when implementing:
GET/DELETE/PUT onlinemall.com/grocery-store/customer.v1/{id}
POST onlinemall.com/grocery-store/customer.v1
Doing it this way allows the client to request specifically the resource they want which maps to the entity they need. Without having to mess with headers and custom media types which is really problematic when implementing in a production environment.
Also having the url late in the url allows the clients to have more granularity when choosing specifically the resources they want, even at method level.
But the most important thing from a developer perspective, you don't need to maintain the whole mappings (paths) for every version to all the resources and methods. Which is very valuable when you have lot of sub-resources (embedded resources).
From an implementation perspective having it at the level of resource is really easy to implement, for example if using Jersey/JAX-RS:
#Path("/customer")
public class CustomerResource {
...
#GET
#Path("/v{version}/{id}")
public IDto getCustomer(#PathParam("version") String version, #PathParam("id") String id) {
return locateVersion(version, customerService.findCustomer(id));
}
...
#POST
#Path("/v1")
#Consumes(MediaType.APPLICATION_JSON)
public IDto insertCustomerV1(CustomerV1Dto customer) {
return customerService.createCustomer(customer);
}
#POST
#Path("/v2")
#Consumes(MediaType.APPLICATION_JSON)
public IDto insertCustomerV2(CustomerV2Dto customer) {
return customerService.createCustomer(customer);
}
...
}
IDto is just an interface for returning a polymorphic object, CustomerV1 and CustomerV2 implement that interface.
Facebook does verisoning in the url. I feel url versioning is cleaner and easier to maintain as well in the real world.
.Net makes it super easy to do versioning this way:
[HttpPost]
[Route("{version}/someCall/{id}")]
public HttpResponseMessage someCall(string version, int id))

REST: Should I redirect to the version URL of an entity?

I am currently working on a REST service. This service has an entity which has different versions, similar to Wikipedia articles.
Now I'm wondering what I should return if for
GET /article/4711
Should I use a (temporary) redirect to the current version, e.g.
GET /article/4711/version/7
Or should I return the current version directly? Using redirects would considerably simplify HTTP caching (using Last-Modified) but has the disadvantages a redirect has (extra request, 'harder' to implement). Therefore I'm not sure whether this is good practice though.
Any suggestions, advise, or experiences to share?
(btw: ever tried search for "REST Version"? Everything you get is about the version of the API rather than entities. So please bear with me if this is a duplicate.)
If you treat versions as entities (which by the looks of it you do) this is what I'd suggest:
GET /article/4711
returns a list of all versions (and links to them). Which makes /article/4711 a container entity.
GET /article/4711/latest
returns contents of the latest version. You might want to consider /version/latest to get in-line with the below.
GET /article/4711/version/7
returns the specific version of the article.
Depends on your intended behavior for GET /article/4711. If it is intended to always point to the latest version, then it should return the latest version directly. Redirecting to a particular version seems problematic as you are relying on the user/client library to not visit that particular URL in the future. To translate into HTML terms, a user might bookmark the version/7 URL and be surprised that they are now accessing an older version instead of the up to date version they originally typed into the address bar.
You might want to look at https://datatracker.ietf.org/doc/html/draft-brown-versioning-link-relations .
Using the CMIS link relations and the HTTP Link header you can make /article/4711 the latest and provide a link to the versions, e.g. Link: </article/4711/versions>;rel=version-history
Article versions and hypertext
If you're really concerned about making the interface RESTful then you should consider how to do this in a HATEOS style.
In my opinion that would mean returning enough information that the user is able to navigate through the list of revisions of your entity. If you read this from Roy ...
"The interface doesn’t need to be discovered. It is defined right there in the hypertext. The representation tells the client how to compose all transitions to the next application state"
... you'll get a feel for how your GET /article/4711 should return enough information to
Get the latest version of the article
Get the next/previous versions
You'll know what works best for your model but as a pointer you could consider using tags
<link rel="older"
type="text/html"
href="http://www.yourdomain.com/article/4711?version=6"/>
...
I think it would be more restful to return a list of the revisions for:
GET /article/4711
You could also have:
GET /article/4711/current
Which returns the current version directly.

Is this a bad REST URL?

I've just been reading about REST URLs and seen the following example:
/API/User/GetUser
Now if this is accessed over HTTP with a verb GET isn't this a bad URL becuase it describes the action (GET) in the URL?
It's more of a convention, than a hard rule, but I would rather see something like /API/User/7123. The GET/POST/etc describes the action verb, so also putting it in the url makes it redundant.
And in this situation there's no reason not to follow good proven practices.
Here's some good stuff: Understanding REST: Verbs, error codes, and authentication
There is no such thing as a REST URL. In fact, the word REST URL is pretty much an oxymoron. The Hypermedia As The Engine Of Application State Constraint guarantees that URLs are irrelevant: you are only ever following links presented to you by the server, anyway. You never see, read or type a URI anywhere. (Just like browsing the web: you don't look at the URL of a link, read it, memorize it and then type it into the address bar; you just click on it and don't care what it actually says.)
The term REST URL implies that you care about your URLs in your REST architecture. However, if you care about your URLs in your REST architecture, you are not RESTful. Therefore, REST URL is an oxymoron.
[Note: Proper URI design is very important for the URI-ness of a URI, especially the I part. Also, there's plenty of good usability reasons for pretty URLs. But both of these have nothing whatsoever to do with REST.]
Better way would be to have /API/User/7123 and use GET/POST method to signify operations
This is not necessarily bad... it has more to do with the framework you are using to generate your rest URLs. The link #Infinity posted is a good resource, but don't limit yourself to a set theory because it can cause an excessive amount of work in certain frameworks.
For example, there is no reason why you wouldn't want to run a GET on /API/Users/{id}/Delete to display an "are you sure" type of message before using the DELETE method.
/API/User/GetUser is not RESTful. Using a verb to identify a resource is not good thing. The example url is still valid but that doesn't make it right either. It is as wrong as the following declaration
String phoneNumber = "jhon#gmail.com";