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

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.

Related

Hypermedia Restful API using Link Header and Range

I'm trying to develop a RESTful api using the hypertext as an engine of application state principals.
I've settled on using the Link header (RFC5988) for all 'state transitions', it seems natural to place links there, and doesn't make my response types specific on an implementation (eg XML/json/etc all just work).
What I'm struggling with at the moment is the pagination of a collection of resources. In the past I've used the Range header to control this, so the client can send "Range: MyObjects=0-20" and get the first 20 back. It seems natural to want to include a "next" relation to indicate the next 20 items (but maybe it isn't), but I'm unsure how to do it.
Many examples include the range information as part of the URI. eg it would be
Link: <http://test.com/myitems?start=20&end=40>;rel="next"
Using the range header would I do something like the following?
Link: <http://test.com/myitems;rel="next";range="myitems=20-40"
The concern here is that the link feels non-standard. A client would have to be checking the range header to get the next items.
The other thing is, would I just leave this all as somewhat out-of-band information?. Never showing next/previous ranges (as that sort of depends on what the client is doing), and expect the client to just serialize down what it needs when it needs it?. I can use the "accepts-ranges" link hints in the initial link to the collection to let the client know its 'pageable'
eg something like
OPTIONS http://test.com
-> Link:"<http://test.com/myitems";rel="http://test.com/rels/businessconcept";accepts-ranges="myitem""
Then the client would go, oh it accepts ranges, I will only pull down the first X, and then go for the next range as necessary (this sort of feels like implicit states though).
I can seem to figure out what is really in the best spirit of HATEOAS here.
The link header spec doesn't do exactly what you want AFAIK. It has no concept of identifying client supplied parameters. The rel doc's for your link can and should specify how to apply your range implementation.
The link-template header spec https://datatracker.ietf.org/doc/html/draft-nottingham-link-template-00#page-3 does a lot of what you want, but that expired. This specified how to use https://www.rfc-editor.org/rfc/rfc6570 style templates in headers, and if you want to use headers that the direction i'd suggest.
Personally, although I agree having the links in the header abstracts you from the body's content type, i find the link header to be difficult to develop against as you can't just paste a url in a browser and see links immediately.

Graceful Degradation with REST in CakePHP

Alright, so a better title here may have been "Progressive Enhancement with REST in CakePHP", but at least now I'll know you didn't read the question if your answer just refers to the difference between the two ;)
I'm pretty familiar with REST and how to integrate it with CakePHP, but I'm not 100% on board with how to still maintain a conventionally functioning website. Using Router::mapResources sounds like a great idea, but this creates a problem with maintaining the "gracefully degradation" version of the site, because both POST requests to /resource/ AND GET requests for /resource/add will route to the same action (add). Clearly I'll want this action to return a JSON object if they're using the REST api, but if they're using the degraded version of the site (no JS perhaps), it should be a add form, right?
What's the best way to deal with this. Do you route your REST requests to other action names using Router::resourceMap()? Do you do that crazy hack I saw to have the /api/ prefix part of the resourceMap so you can use api_action functions? Do you have the actions handle both REST and conventional requests via checking isAjax()? If so, how do you ensure that you can rely on the browser to properly support the other two request types?
I've searched around quite a bit but haven't found anything about how to keep conventional requests available in Cake along side REST, so if anyone has any advice or experience, I'd love to hear it!
CakePHP uses extension routing as well, via Router::parseExtension() so;
/test/action will render views/test/action.ctp
/test/action.html also
/test/action.json will render views/test/json/action.ctp
/test/action.xml will render views/test/xml/action.ctp
If all views are designed to handle the same data as set by your controller, you'll be able to show a regular HTML form and handle the posted data the same way as you'd handle the AJAX request.
You'll probably might have to add checks if any data is posted/submitted inside the /add, /edit, /delete actions to prevent items being deleted without a form being posted (haven't tested that though, it might be that cake blocks these urls if mapresources is set for the controller)
REST in CakePHP:
http://book.cakephp.org/2.0/en/development/rest.html
(Extension) Routing
http://book.cakephp.org/2.0/en/development/routing.html#file-extensions

REST - entity (hash) version in URL vs etags for client side caching

I am designing a REST API and lately I put some thought on how to make most of caching for dynamic content (after the response that I got on this topic), while respecting the principles of HTTP (and thus REST).
Obviously the canonical solution (at least in my understanding) is to use etags, but this will not decrease the number of requests in any way, just the size.
I was thinking of embedding a version in the URL (it will be server produced, based on the actual content - be it serial number or some hash). I will explain the scheme and the user scenario and how I think it will help, and then ask my questions.
Setup
GET /entity/{id}/
returns temporary redirect to /entity/{id}/{current_version} and no-cache headers.
GET /entity/{latest_version}/
returns OK response with cache forever.
GET /entity/{old_version}/
returns 410 Gone (I don't want to actually keep old versions).
GET /entity/?[query]
is some search that returns a list of links to current versions of result entities. No cache.
Use scenario and how I think it would help
User application (AJAX) will always start with some kind of query, then it has to pull the descriptions of entities. Since it is expected that changes for a single client result set will not be very dynamic, it seems good idea to use the above scheme and client pull fresh results from the query every time, but if most of the entities did not change since last visit, they will be already cached in browser. If this hypothesis is true, this will lead to significant decrease in the number of requests, as well as total size.
Using etags would result in much simpler URI scheme, but probably more complicated and heavy server side implementation.
Notes and questions
1
I know somebody will propose that /entity/{id}/ should be a collection that returns list versions, but versions are not actually stored, useful or desired. It is more a synonym for the latest one. My question here is if somebody sees any problem with that, besides general principles. This is protected API, I do not care about SEO in this case and it is transparent for client. Actually, as API will be more or less hyperlinked, it is not expected to actually call /entity/{id}/ directly normally, but use whatever results returns. It can be used, for example for context free links.
2
I have some doubts for 410 Gone for old versions. On one hand this version is not available anymore and clients should not be accessing it anyway. On the other hand, if client asks for it after all (for whatever reason), it may make sense to return permanent redirect to /entity/{id}/ (probably better that temporary redirect to current version).
3
Speaking of redirects. 301 is cemented for permanent redirect, but is 302 the best choice for temporary? Most important is browser support (it will be AJAX).
4
Of course, the main issue is the usage of URLs instead of etags for caching (hoping on the browser caches). If somebody has real experience under high load (relative to servers capabilities, cough), I will appreciate sharing it.
Additional notes
After some more research there is an issue with versioned resources and it is propagation of updates for linked resources. There are two options:
Link a specific version of the resource. This means that server side logic will be heavy and cumbersome, as updates have to be propagated for linked resources through reverse links;
Link the /latest/ version. This means that even if both resource and linked resourced concrete versions are cached locally, clients (browsers) will have to make a request to /latest/ in order to 'check' latest version of a linked resource. Of course it is a small request (only redirect) and if resource didn't change location is already cached. One problem may be that resources are often pulled from such links (in opposite to query result to particular version). Another (much worse) problem is that actually old version of the resource is linking the newest version of another - it can be data inconsistency (i.e. somebody edited document and also changed a linked attachment - client will have old version of the document and new one for the attachment).
Both options are unsatisfactory. In this light caching of dynamic data is possible only for 'leaf' level resources - ones that do not link to any other, bust just have direct attribute values.
Final notes
After research and discussions, versioned resources are not the brightest idea as general architecture. After measurement and given the opportunity, something can be retrofitted in a canonical API for 'plain' resources. I would accept Roysvork's comment (' It is my opinion that the reason this is difficult is that it is not really a very good idea.') as solution, if it was a separate answer :)

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))

In REST, how should a GET request to a findAll operation be handled when the Resources are paged?

In a RESTful Service, Resources that cannot all be retrieved at once are paginated. For example:
GET /foo?page=1
The question is, how should I handle a getAll request such as:
GET /foo
Taking discoverability/HATEOAS into consideration, I see a few options:
return a 405 Method Not Allowed and include a Link header to the first page:
Link=<http://localhost:8080/rest/foo?page=0>; rel=”first“
return a 400 Bad Request and include the Link header (same as above)
return a 303 See Other to the first paginated page
return a 200 OK but actually return only the first page (and include the URI of the next page into the Link):
Link=<http://localhost:8080/rest/foo?page=1>; rel=”next“
note: I would rather not do this, having learned not to manage anything for the client by default, if they haven't explicitly asked for it.
These are of course only a few options. I'm leaning towards the first, but I'm not sure if there is a best practice on this that I am not aware of.
Any feedback is appreciated.
Thanks.
Lets start with the fact that REST is not a set-in-stone protocol like SOAP, it's simply a means of structuring a service, similar to how languages are described as being Object-Oriented.
That all being said, I'd recommend the handling this as follows.
Treat a RESTful call like a function declaration.
GET /foo
foo()
Some functions require parameters.
GET /foo?start=??&count=??
foo(start, count)
Some languages support default parameters, others don't; you get to decide for yourself how you want to handle parameters.
With default parameters, you could assume that the function was defined as
foo(start = 0, count = 10)
so that a call to GET /foo would actually be equivalent to GET /foo?start=0&count=10, whereas a call to GET /foo?start=100 would be equivalent to GET /foo?start=100&count=10.
If you don't want default parameters, you could force the user of the API to explicitly set start and count:
foo(start, count)
so that a call to GET /foo would return a 400 Bad Request status code, but a call to GET /foo?start=0&count=10 would return a 200 OK status code along with the content contained by the specified range.
In either case you'll have to decide how you'll handle errors, such as
GET /foo?start=-10&count=99999999
If parameters have maximums and minimums, you'll need to decide whether to normalize the parameters, or simply return errors. The previous example might return a 400 Bad Request status code, but it could also be constrained to turn into:
GET /foo?start=0&count=1000
In the end it's up to you to decide what makes the most sense in the context of your application.
From a RESTful point of view, I think it perfectly alright to handle both representations the same. Consider a software with several versions you want to download, the latest one being 3.8. So if you want to get the latest version, you could address it with both GET /software/version/latest.zip and GET /software/version/3.8.zip until there comes a newer version. So two different links point to the same resource.
I like to imagine pagination pretty much the same. On the first page there are always the latest articles. So if no page-parameter is provided, you could simply imply it's 1.
The approach with the rel attribute goes in a slightly different direction. It's a creation of Google to better handle the problem with duplicate content and is primarily considered to be used in order to distinguish between a "main" page and pagination-pages. Here's how to use it:
//first page:
<link rel="next" href="http://www.foo.com/foo?page=2" />
//second page:
<link rel="prev" href="http://www.foo.com/foo?page=1" />
<link rel="next" href="http://www.foo.com/foo?page=3" />
//third and last page:
<link rel="prev" href="http://www.foo.com/foo?page=2" />
So from a SEO point of view it's a good idea (and recommended by Google) to use those elements. They also go perfectly with the resource-orientated idea of REST and the hypermedia representation of the resources.
Choosing one of your suggestions, I think the 303 See Other is the right way to go. It was intended to be used for this kind of purposes and is a good way to canonicalize your resources. You can make them available through many URIs, but have one "real" URI for a representation (like the software with different versions).
According to the specification, the response should look something like this:
303 See Other
Location: http:www.foo.com/foo?page=1
http:www.foo.com/foo?page=1
So you provide a Location-header with the "real" representation, and the body should contain a hypertext document linking to the new URI. Note that according to the specification the client is expected to send a GET request to the value of Location, but it doesn't have to.
//EDIT as answer to your comment (yep, it's really bad practice to claim something without proving it :-) - my bad!):
Google presented the rel="next" and rel="prev" attributes in September 2011 on the Official Webmaster Central Blog. They can be used additionally to (or in some cases instead of) the rel="canonical" tag.
Under those links you can find the differences between them explained:
rel="next" and rel="prev" link elements are "to indicate the relationship between component URLs in a paginated series"
the rel="canonical" "allows you to publicly specify your preferred version of a URL"
So there is a slight difference between them. So you can break down your problem to a canonical issue: There are several URLs pointing to the same resource (/foo and foo?page=1 but you have a preferred version of the URL (foo?page=1). So now there are a few options for a RESTful approach:
If there is no page-parameter given in the query, use a default value (e.g. 1) when processing it. I think in this specific case it is OK to use a default value even though you point it out as bad practice.
Respond with 303 See Other providing the preferred URL in the Location-header (as described above). I think a 3xx-response is the best (and most likely RESTfully intended) way to deal with duplicate/canonical content.
Respond with 400 Bad Request in case you want to force the client to provide a page-parameter (as explained by zzzzBov in his answer). Note that this response does not have something like a Location header (as assumed in your question), so the explanation why the request failed and/or the correct URL (if given) must go to the entity-body of the response. Also, note that according to the specification this response is commonly used when the client submits a bad/malformed representation (! not URL !) along with a PUT or POST request. So keep in mind that this also might be a little ambiguous for the client.
Personally, I don't think your suggestion to respond with 405 Method Not Allowed is a good idea. According to the specification, you must provide an Allow-header listing the allowed methods. But what methods could be allowed on this resource? I can only think of POST. But if you do not want the client to POST to it either, you could also respond with 403 Forbidden with an explanation why it is forbidden, or 404 Not Found if you do not want to tell why it is forbidden. So it might be a little ambiguous, too (in my opinion).
Using link-elements with the mentioned rel-attributes as you propose in your question is not essentially 'RESTful' because it's only hypermedia which is settled in the representation of the resource. But your problem (as far as I understand it) is that you want to decide how to respond to a specific request and which representation to serve. But still it's not absolutely pointless:
You can consider the whole SEO issue as a side effect of using rel="next/prev/canonical", but keep in mind that they also create connectedness (as the quality of having links) which is one of the characteristics of REST (see Roy Fielding's dissertation).
If you want to dive into RESTful Web Services (which is totally worth it) I recommend reading the book RESTful Web Services by Leonard Richardson and Sam Ruby.
In some cases not implicitly managing anything for the client can lead to a overlay complex interface, examples would be where the consumer isn't technical or isn't intending on building on top of interface, for example in a web page. In such cases even a 200 may be appropriate.
In other cases I would agree implicit management would be a bad idea as the where a consumer would want to be able to predict the response correctly and where a simple specification may be required. In such cases 405, 400 and 303.
It's a matter of context.