I have a RESTful API spec for a new project from another company and it refers to RFC6570 and the use of Fragment Expansion {#var}
in the URI Template when making requests to their API.
The URI templates look like:
PUT https://api.acme.com/order{#meta*}{?order_number}
or GET https://api.acme.com/orders{#meta*}
(note the difference with order/orders).
They mention 'if the metadata stored on your system looks like this:'
{
"meta": {
"customer": "1234",
"state": "open"
},
"order_number": "0003"
}
This is then translated into requests like PUT https://api.acme.com/order#customer=1234,state=open?order_number=0003
or GET https://api.acme.com/orders#customer=1234,state=open
.
The URL fragments, e.g. #customer=1234,state=open
are meant to be used as some kind of metadata filtering or context for the request?
Postman, curl
and browser requests appear to strip out everything after the #
before sending to the server. Is that expected behaviour and described in an RFC somewhere? Does that mean these RESTful URLs are invalid?
What is the proper use case for the {#var}
fragment expansion in URL Templates?
Postman, curl and browser requests appear to strip out everything after the # before sending to the server. Is that expected behaviour and described in an RFC somewhere?
Yes, it is described in RFC 3896
the fragment identifier is not used in the scheme-specific processing of a URI; instead, the fragment identifier is separated from the rest of the URI prior to a dereference, and thus the identifying information within the fragment itself is dereferenced solely by the user agent, regardless of the URI scheme.
The same idea, as described by RFC 7230
Does that mean these RESTful URLs are invalid?
Sort of.
https://api.acme.com/orders#customer=1234,state=open
That's a perfectly valid URL (see the production rules in RFC 3986 appendix A).
Let's review the specification for fragments:
The fragment identifier component of a URI allows indirect identification of a secondary resource by reference to a primary resource and additional identifying information. The identified secondary resource may be some portion or subset of the primary resource, some view on representations of the primary resource, or some other resource defined or described by those representations.
The HTTP definition is a bit clearer:
The optional fragment component allows for indirect identification of a secondary resource
So for practice, let's look at the identifier for the fragment specification itself
https://www.rfc-editor.org/rfc/rfc3986#section-3.5
What we have here are identifiers for two resources: the "primary resource" is the web page itself, which is identified by the sequence of characters prior to the fragment delimiter -- https://www.rfc-editor.org/rfc/rfc3986 ; then we have the secondary resource within that primary resource, section-3.5
tells us what to look for in the primary resource. So the browser knows to (a) download the primary resource, and then (b) upon discovering that the primary resource has a text/html
representation, knows how to dig through the html tags to find the tag that matches the fragment. The browser can then jump directly to the correct location in the document.
In your example, https://api.acme.com/orders is the primary resource, and customer=1234,state=open
is the fragment used to identify some resource within the representation of the primary resource.
BUT
RFC 7230 defines the request line of HTTP
method SP request-target SP HTTP-version CRLF
Where request-target is in turn defined as
request-target = origin-form
/ absolute-form
/ authority-form
/ asterisk-form
The two that are of interest to us are origin-form and absolute-form. Both are defined by RFC 7230
origin-form = absolute-path [ "?" query ]
absolute-form = absolute-URI
where absolute-URI is defined in RFC 3986
Some protocol elements allow only the absolute form of a URI without a fragment identifier.
absolute-URI = scheme ":" hier-part [ "?" query ]
This is all consistent with the restriction on target-uri
The target URI excludes the reference's fragment component, if any, since fragment identifiers are reserved for client-side processing
What is the proper use case for the {#var} fragment expansion in URL Templates?
Trying to construct a link to a secondary resource, in particular as a collaboration of two pieces of code; one piece of coding knowing the values for the template variables but not knowing where they are supposed to go (and in particular, which variables belong in the fragment), and another piece of code knowing where in the URI each of the different variables is supposed to appear, but not knowing what the values are.
In other words, it's exactly the same sort of thing we are doing when we create a URI template to allow the production of the identifier of a primary resource, but also allowing variable expansion in the fragment element as well.
http://example.org/people/bob
http://example.org/people#bob