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.
Related
I was wondering if it is technically RESTful to use an identifier as a grouping and not be a particular resource (no corresponding id).
For example:
get /location/address
get /location/coverage
get /location/region
These things are all a location hence having them behind the location identifier. Is this correct?
Or is it better to rethink the structure of these endpoints or break them into just /address - /coverage - /region?
First and foremost, a URI in a REST architecture is just a URI, a reference to an other resource. The actual spelling used inside the URI is furthermore not of relevance as the URI as a whole is a pointer that shouldn't get segmented or analyzed. While a set of URIs may span a whole tree of available paths to use, there is no requirement actually therefore.
An URI itself also does not necessarily tell anything about the content of the resource it points to. Fielding even claimed that
A REST API should never have “typed” resources that are significant to the client. Specification authors may use resource types for describing server implementation behind the interface, but those types must be irrelevant and invisible to the client. The only types that are significant to a client are the current representation’s media type and standardized relation names. (Source)
This blog post further describes what Fielding meant with this statement which basically just states that proper content type negotiation should be used instead of assuming that a resource has a certain type. On the Web you might retrieve a data page of your preferred car or sports team though you will most-likely receive a page in HTML format that is generic enough and therefore widely spread that plenty of clients (browsers) support it. Through the affordance of each of the defined elements your client (browser) knows how to present these to you for more convenient access of the content.
I'm not sure about you but if I have the choice between reading some line summarizing the content of a link and having to decipher the URI itself, I definitely prefer the former one. Such metadata is usually attached to a link in some way. In HTML the anchor (<a>) tag not only ships with meta data such as href or target but also rel which basically allows to annotate a URI with a set of keywords that tell a client about the purpose of the link. Such a keywords may be something like first, last, prev or next for paging through a sub-set of a collection, or preload for telling a client that it can load the content of the referenced URI early to speed up load times as the client will most likely be interested in the content of that link next. Such keywords should be standardized to gain wider acceptance or at least base off of an extension mechanism defined in Web Linking, as Dublin Core does it i.e.
Looking at your respective URIs they already seem to express what link relation are there for. As such they could make up for good candidates for defining them as link relations such as:
http://www.acme.com/rel/address
http://www.acme.com/rel/coverage
http://www.acme.com/rel/region
A link can basically have multiple relation names assigned simultaneously, depending on the media-type the payload is exchanged for. A client that does not know what a certain link-relation means will simply ignore it, clients that however have the knowledge will act accordingly upon finding URIs with such annotations. I admit that an arbitrary client will not be able to make use of all of the link-relations out of the box, especially the extension ones, but such link-relation names might be enforced by media-types as well or support for such relation names may be added through updates or plug-ins later on.
Media types, after all, are just a human-readable description on how a payload received for such a form will look like and how it has to be processed by some automata. Hence, a generic application/json is usually a bad media-type in a REST API as it just defines that the content should be embedded between curly braces and primarily represents a key-value structure with the addition of objects and arrays, but it lacks to hint a client on what a link is or on the semantics of certain elements found within the payload. application/hal+json is an extension of the basic JSON notation and adds some processing rules and semantic definitions of certain elements such as _links or _embedded, which a client can use. Here, curies could be used a link-relations as well I guess as in the end they also end up with unique URIs as requested by the Web linking extension definition.
Certain media-types also allow to pass along further processing hints in the media-type itself through the use of profiles. As such a server could hint a client i.e. that the collection expressed by the requested resource contains entries that follow a certain logic, i.e. that the collection contains a set of orders, where a processing entity can apply additional checks upon, i.e. that certain fields must be specified or that certain inputs have to be in bound between two values and stuff.
As writing a whole new media-type is quite some effort, investigating into already defined ones is for sure a good idea. If you really think there is no media type available yet that really is applicable to your domain, you should start to write one, probably in a community effort. Keep in mind though that this media-type should be as generic as possible to allow adoption by third parties otherwise hardly any client will really support it and thus limit the number of potential peers your applications can interact with. It is further a good idea to take reference at the HTML spec to see how elements got defined and how they maintained backwards compatibility as you don't want to register a new media-type on each change.
If you just want to implement some filter mechanism to only show locations that represent addresses rather than regions you may take reference on how it is done on the Web. Here usually a server will provide you a form to select a choice among the given set of choices and upon clicking the submit button (or enter key) a request is issued to the server which will return the subset of entries matching the query. Instead of using a form a server may already provide a client with a link that is annotated, as mentioned above, with some hints a client knows that they refer to addresses, regions or whatever options you have available and can chose based on the annotated link relations the URI which is of interest to the client. Again, the actual form of the URI is not of relevance here either as a client should just use the URIs that were provided by the server.
You might ask yourself why all that is needed?! The basic answer to this question is simply to avoid breaking things when stuff changes over time. Think of a case where a client wants to retrieve details on a previously sent order. If it had the knowledge of the URI hardcoded into it and the server changes the URI style the client might not be able to retrieve this data. On the other side if it had the knowledge to look for any URI annotated with http://www.acme/rel/order and just use that URI it couldn't care less if the URI changed as it just uses the given information to send it to the mentioned endpoint. By relying on well-defined media-types and the semantics of the defined elements, any peer supporting this media-type will also be able to process it. Almost every client is able to handle HTML in some way, though hardly any generic HTTP client can really act upon a custom JSON payload format, i.e. present you a clickable link or render a nice form you can update the data of an existing resource. Custom payload makes it also difficult to reuse the same client for different endpoints. I.e. you probably wont be able to use the same client to shop on two different web-shops that expose Web-RPC-based HTTP endpoints.
So, to sum up my post, as mentioned, the form of the URI is not really of relevance in a REST architecture as a server should always provide it to the client anyway and a client shouldn't deduct the meaning from it. Instead link-relations, media-type support and content-type negotiation should be used consistently.
REST doesn't care what spellings you use for your URI, beyond the fact that they should be consistent with the production rules defined in RFC 3986.
GET /location/region
GET /region
Those are both fine.
In my API I should return a list of products. In the client (browser) the user can add this products to a cart, increasing, decreasing, or remove this a product from the cart.
In my response with the products list should I put the URLs actions like this:
{
"alias": 'aliasValue',
"removeUrl": 'domain/product/alias/',
"increaseUrl": 'domain/product/alias/increase/',
"decreaseUrl": 'domain/product/alias/decrease/',
...
}
Is this a good practice, I've searched for this but the only thing that I found about URL and API is about the URL structures.
What do you think?
I would advise against reinventing the wheel. There are many ways to use HATEOAS in your API.
Consider, for example, the HAL (Hypertext Application Language) approach, where you have a _links property:
{
"_links": {
"self": {
"href": "http://example.com/api/books/1"
}
},
"id": "1",
"name": "Hypermedia as First-Class Citizen"
}
What you are trying to achieve as a name HATEOAS that stands for Hypermedia as the Engine of Application State.
So if you search for it you will find a lot of formats:
JSON-LD
HAL
SIREN
ION
JSON API
Spring
Ripozo
Source: https://nordicapis.com/tools-to-make-hateoas-compliance-easier/
As REST is just a generatlization of the browsable Web we all know, you can basically apply the same concepts as if you'd implement your system for the browser. In short, a server should provide a client with all the necessary information the client will need to make educated decisions which resources to invoke next.
In a browser-based Web application the interaction model could be similar to invoking the start page, seeing a section in the response that is of interest to you, click a link to learn further details. The next page might list some items where you are provided with further controls to modify this list, i.e. add a new item, remove one and so forth. Upon clicking some "add" button a form is presented to you which teaches you what fields a request should contain and also where this request should be sent to, even if it might not be visible to you. In the back the browser will take care of that for you. The jumping point here is, the server is actually feeding the client with any information needed to proceed through his task, whether it is the choice of available links to explore or the presentation of some guidelines on how a request should look like.
In order to determine whether a link is of interest to a client a server will use meaningful link relation names "attached" to URIs a client should use instead of parsing and interpreting URIs. This allows a server to change URIs anytime without affecting a client. Fielding mentioned the following in one of his blogposts:
A REST API should spend almost all of its descriptive effort in defining the media type(s) used for representing resources and driving application state, or in defining extended relation names and/or hypertext-enabled mark-up for existing standard media types. (Source)
In addtion to that REST APIs shouldn't have typed resources meaningful to clients as this basically couples the client tightly to the API itself and will lead to failures if the serve ever changes anything in regards to the response returned. Instead content-type negotiation should be used in order to let client and server negotiate about the actual representation format used.
A media type defines the processing rules of some payload that is received for a certain Content-Type HTTP header. These rules define both syntax as well as semantics of the document. Servers in a REST architecture are i.e. allowed to reject any messages sent for a certain content type if the rules outlined in the media type are violated.
While the focus on media-types doesn't prevent changes done to the representations received completly, it still is useful in helping to decouple clients from servers further and reduce out-of-band information needed in order to interact with the service. Instead of coupling a client directly to the API, both couple to the media-type actually, and there might be multiple media types they actually couple to. If there ever needs to be a change done to a media-type you can easily introduce a new media type or, similar to HTML, specify within the media-type how backwards compatibility is achived.
In regards to prior, out-of-band information requirements, which REST doesn't completly remove, Fielding stated
Of course the client has prior knowledge. Every protocol, every media type definition, every URI scheme, and every link relationship type constitutes prior knowledge that the client must know (or learn) in order to make use of that knowledge. REST doesn’t eliminate the need for a clue. What REST does is concentrate that need for prior knowledge into readily standardizable forms. That is the essential distinction between data-oriented and control-oriented integration. (Source)
As REST isn't a focus on one single aspect but a conglomeration of all of the aspects mentioned above, your actual question should be tackled from multiple angles.
First, either use existing link relations, i.e. administered by IANA or other microformats, define new ones which you should register with IANA at best or use some semantic web related tags like schema.org. I.e. if you have collections then next, prev, first and last are pretty meaningful (and already registered at IANA) for pagination or item for a decicated item within the list. This collection might have been returned previously as collection before or specified by the respective item in order to go back to the previous collection. If somethin like an add or edit should be done a link-relation like edit-form can teach the client that the URI will return some kind of form that will tell the client how a request to the API will need to look like.
Next, as basic JSON isn't that great in terms of providing help to a client, as all it does is define the syntactical structure of a document but lack support of given the elements meaning, some more advanced media types should be supported. As already mentioned by Cassio and Exadra37 there are a couple of JSON based document types that provide support for HATEOAS (~ URIs and link relation names). Instead of only going for i.e. application/hal+json a multitude of document types would be preferable as this just increases interoperablility with a magnitude of different clients that might come with support for other media types. Note futher that there is nothing wrong with returning a HTML representation as well. REST isn't restricting you to only specific JSON or XML content. I guess most of the time, instead of specifying an own media-type, simply using HTML would be sufficient to carry the meaning of the content from API to server.
You are of course free to create your own media type and use it. In order to increase interoperability you should however standardize it and probably also provide plugins/libraries for third party frameworks so that they are able to use your format as well.
The best advice, though, for sure is to reuse existing standards as the likelihood of other clients already being familiar with such implementations or concepts is way higher than for your custom format. Besides that, it probably also spares you from a lot of work and effort.
Recently, I've designing a RESTful API, and I want to use the Link header field to implement HATEOAS.
This is all fine and works without any real problem, but I want to make it easier for the clients of the API.
The Link header for example might look like this:
Link: <https://api.domain.com/orders/{id}>; rel="https://docs.domain.com/order"
In this case the client would have to find the link by searching for the https://docs.domain.com/order value in the rel attribute.
This works, but since the URI for the docs could change it's fragile, and because of the length it makes it a bit impractical as a key to search for.
So I want to try and use a CURIE to make it something like this instead:
Link: <https://api.domain.com/orders/{id}>; rel="[rc:order]"
That way the problem of a URI changing is mitigated for the most part, and it's much more compact allowing for easier search by the client.
My problem is, that since I'm using a Link header field to implement HATEOAS I feel it would be most consistent to also include the CURIE as an HTTP header field, rather than introducing meta data in the response body.
Since the entire API uses standard HTTP header fields and status codes for all of it's meta data (pagination, versioning etc), I would rather not introduce meta data into the response body just to define a CURIE.
But if I use HTTP header fields, which field should I use for a CURIE?
Is there even a standard way to do this with HTTP header fields?
If not, should I just use a custom header field, like X-Curie: <https://docs.domain.com>; name="rc", and just document it somewhere for clients?
I've looked around and most resources are either in reference to XML or the HAL standard, so any information on this in relation to HTTP header fields would be appreciated.
No, you can't do that. The link relation is a string - nothing more.
The question that you should ask yourself is why you are using an unstable link relation name in the first place...
Even if you don't use the Link header, CURIE's would not solve the problem you present. Because the CURIE's standard state that a shortened URI must be "unwrapped" before any comparison is performed. This would also apply to comparison agains the link relation in question.
A more pragmatic approach would be to coin your own URI like foo:order. Then you can use some custom url shortening method of resolving the documentation url for the relation in question. This method is used by hypermedia formats like HAL+JSON (the HAL formats use of curies is actually misleading, it should only be used as a method for resolving URL's to documentation).
CURIEs in HTTP Link header's rel properties would not get expanded, because all rel properties are equated with simple string matches, none are treated as URIs.
My main concern would be the phrase "since the URI for the docs could change it's fragile" — then choose a URI which won't change. Even if you use a URL that redirects to some location deep in the docs, the URI you choose for the link relation needs to be permanent if you want client devs to be able to resolve it.
I've been trying to implement a RESTFul architecture, but I've gotten thoroughly confused as to whether custom media-types are good or bad.
Currently my application conveys "links", using the Http Link: header. This is great, I use it with a title attribute, allowing the server to describe what on earth this 'action' actually is, especially when presented to a user.
Where I've gotten confused is whether I should specify a custom mime-type or not. For instance I have the concept of a user. It may be associated with the current resource. I'm going to make up an example and say I have an item on an auction. We may have a user "watching" it. So I would include the link
<http://someuserrelation> rel="http://myapp/watching";title="Joe Blogg", methods="GET"
In the header. If you had the ability to remove that user from watching you would get.
<http://someuserrelation> rel="http://myapp/watching";title="Joe Blogg", methods="GET,DELETE"
I'm pretty happy with this, if the client has the correct role he can remove the relationship. So I'm defining what to do with a relationship. The neat thing is say we call GET on that 'relation' resource, I redirect the client to the user resource.
What's confusing me is whether or not to use a custom mime-type. There's arguments both ways on the internet, and in my head in regards to this.
I've done a sample in which I call HEAD on an unknown url, and the server returns Content-Type: application/vnd.myapp.user. My client then decides whether it can understand this mime-type (it maintains mappings of resources it understands to views), and will either follow it, or explain that it's unable to figure out what is at the end of that link.
Is this bad?. I have to maintain special mime-types. What's particularly odd is I'm more than happy to use a standard application/user format, but can't find one specified anywhere.
I'm beginning to think I should be attempting to completely guess at rendering what in any HTTP response, almost to the point that maybe my RESTFul api should just be rendering html instead of attempting to do anything with json/xml.
I've tried searching (even Roy Fieldings blog), but can't find anything that describes how the client should deal with this sort of situation.
EDIT: the argument I have with including the custom type, is that it may not necessarily be a 'user' watching the item, it could be something with application/vnd.myapp.group. By getting the response a client knows the body has something different, and so change to a view that displays groups. But is this coupling of mime-type to view bad?.
I'd say, you definitely want to have a specific media-type for all representations. If you can find a standard one (html, jpeg, atom, etc.) use that, but if not, you should define one (or multiple ones).
The reason is: representations should be self-contained. That means your client gets a link from somewhere it should know what to do with it. How to display it, how to proceed from there, etc. For example a browser knows how to display text/html. You client should know how to display/handle application/vnd.company.user.
Also, I think you've got content negotiation backwards. You don't need to call HEAD to determine what representations the server supports. You can tell the server what your client supports in the GET/POST/etc requests using the "Accepts" header. Indeed this would be the standard way to do it. The server then responds with the 'best' representation it can give you for your accepted mime-types. You don't need more round-trips.
So, although the links you are providing can contain contextual information, usually given in the 'rel' attribute, like if the link points to a 'next page', 'previous page', 'subscribed user' or 'owner user', etc., the client can not assume any representation under those links. It knows it is semantically a 'user', so it can fill the 'Accepts' header with all supported representations for a user (application/vnd.company.user). If the representation only says text/xml, there is nothing the client can assume either of the content, or semantics of Links that it may receive.
In practice you can of course code any client to just assume what representations are under what links/urls, and you don't have to conform to REST all the time, but you do get a lot of benefits (described in Roy Fielding's paper) if you do.
Another minor point: The links do not need to contain which methods are available for a given resource, that's what OPTIONS is for. Admittedly, it is rarely implemented.
You don't have to send HTML to serve hypermedia. There are many different hypermedia formats which are much easier to parse than HTML. https://sookocheff.com/post/api/on-choosing-a-hypermedia-format/ https://stackoverflow.com/a/13063069/607033
You don't have to use a domain specific MIME type, in my opinion it is better to use a domain specific vocabulary with a general hypermedia type e.g. microformats or schema.org with JSON-LD + Hydra or ATOM/XML + microdata / RDFa, etc... There are many alternatives depending on your taste. https://en.wikipedia.org/wiki/Microdata_(HTML) http://microformats.org/ http://schema.org/ http://www.hydra-cg.com/
I am not sure whether adding the same relation to multiple methods is a good choice. Sending multiple links with different in link headers with d if you want: https://stackoverflow.com/a/25416118/607033
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.