How do you GET a RESTful resource by something oth

2019-03-30 08:23发布

问题:

There may be situations where I would need to find an object by parameters other than ID. What is the proper RESTful way to do that?

For example I might want to find a User by username and password, so the strictly RESTful "GET /users/1" wouldn't work.

According to the Rails docs this is the URL pattern for getting all the instances of a resource: "GET /users". I could add parameters to that: "GET /users?username=joe&password=topsecret", but that would be perverting the official purpose of the GET request.

回答1:

"GET /users?username=joe&password=topsecret", but that would be perverting the official purpose of the GET request."

No it isn't perverting anything. That's absolutely the correct and RESTful way to do it, and is the reccomended way of retrieving dynamic results in the http spec. REST doesn't care what's in the URL, only that it's unique. The url for that page could be http://3f778a9b8a7c778696e for all REST architecture cares, so long as that's the only way to get there, and it doesn't ever lead anywhere else.

http defines a query string protocol for returning dynamic results. Given the current state of your database, the query string that you give your application ought to always return the same result. Then it will be RESTFUL. URL aesthetics are a different issue from REST altogether.

according to the REST architecture, the rules of the GET request are that it always returns the same results (or maintains the same results for reasonably long periods of time, so that caching works), and that GET Doesn't have side effects. GET needs to be idempotent (always return the same results, regardless of how many times you call it) and not cause the system to change state. That is it.

Of course you don't have to use the query protocol. You can put parameters into forward slashes, inbetween semicolons, or it could be a base64 encoded GUID. It's entirely up to you, as long as it follows those simple rules.



回答2:

Multiple keys is not restful, is it? Perhaps /users/[username]?password=secret. Also, you don't want to use the password there, but some kind of API key, so that an url looks like this:

/users/leethal?secret=da01930adfe82810092

In order to use the username instead of the id, do this:

# controller
@user = User.find_by_username!(params[:id])

# model
def to_param
  username
end