In any event, as far as I can tell this is a unique design, so maybe it’s too weird or not properly RESTful? Would love to know of any other patterns designed to solve the problem of supporting arbitrarily-named secondary unique keys. What do you think?
Not that unique. 🙂 And it really has nothing to do with representational state transfer.
This is purely URL design (i.e. purely a server-side concern). So on that note, let’s take a look at the good RFC:
Aside from dot-segments in hierarchical paths, a path segment is considered opaque by the generic syntax. URI-producing applications often use the reserved characters allowed in a segment to delimit scheme-specific or dereference-handler-specific subcomponents. For example, the semicolon (";") and equals ("=") reserved characters are often used to delimit parameters and parameter values applicable to that segment. The comma (",") reserved character is often used for similar purposes. For example, one URI producer might use a segment such as "name;v=1.1" to indicate a reference to version 1.1 of "name", whereas another might use a segment such as "name,1.1" to indicate the same. Parameter types may be defined by scheme-specific semantics, but in most cases the syntax of a parameter is specific to the implementation of the URI's dereferencing algorithm.
So the premise of your design is sound – sound enough, in fact, to show up all the way back in the RFC. 🙂
I would just have used different syntax to match RFC-suggested convention, namely /users/;username={username}
.
Note that the parametrization this section talks about is “applicable to that segment”, which is to say that if you want, it naturally expands to support, in your example, things like /users/;username={username}/profile
.
Oh very nice, appreciate the pointer! I alway know I can count on you to have a solid response to this sort of question.
I can think of two reasons to prefer
/users/username:{username}
, however:;
to demarcate multiple fields:
to create a nice aesthetic variation from the search interface, which uses the equal sign. IOW,/users/username={username}
is just a little too similar to/users?username={username}
, which is the search endpoint for my API. The colon lets the user know that there's something slightly different going on, since it's not used in the search syntax.And yeah, the ability to return something like
/users/username={username}/profile
was one of the ideas I had at the back of my mind.Since I made that post, I've changed things slightly to:
Location
header with the canonical URL for the resource (/users/{uid}
)Appreciate your response and validation of the underlying idea! Now to find out of my co-workers convince me to use gRPC/Protobuf, instead.