URL design for advanced filtering of results in restful API

Let's take a generic example of resources you might model with a restful API built in PHP.

  • A garage has multiple cars and multiple mechanics.
  • A car has only one garage.
  • A mechanic has multiple cars and multiple garages (he's a workaholic ok!).
  • So logic says that our endpoints should be

    /v1/garages  
    /v1/garages/1234
    /v1/mechanics
    /v1/mechanics/1234
    /v1/cars
    /v1/cars/1234
    

    If we wanted to get all cars of garage 1234 we would use GET /v1/garages/1234/cars

    If we wanted all cars for mechanic 12 that are in garage 34 we would use GET /v1/mechanics/12/garage/34/cars

    But what about if we wanted all cars from garages 56 AND 78?
    I have a few ideas in mind but the best I can think of is GET /v1/cars?garage=[id=[56,78]]

    Which would allow us to grab all green cars with two or four doors from any garages that have yellow paint and carbon bonnets via GET /v1/cars?garage=[paint=yellow,bonnet=[material=carbon]]&color=green&doors=[2,4]

    Does this seem like a reasonable idea or am I going to run into issues with this getting to complex with the nesting, should this be easy enough to parse with PHP?

    Another idea I had was Json as far as I am aware all json is valid in a url so

    GET /v1/cars?{"color":"green","doors":[2,4],"garage":{"paint":"yellow","bonnet":{"material":"carbon"}}}

    Which makes it super easy for developers to use then as almost all programming languages now have json support, and on the API end we can just use json_decode($_SERVER[''QUERY_STRING]) so are there any issues with using Json?

    Third Idea "create a search"

    By this I mean we use

    POST /cars/search with the above Json as post data that request will simply return the ID of the search to which the results could then be fetched via GET /cars/search/{id} this would alleviate the complexity on my side and avoid the 8kb limit for requests (this is an API, not meant to be used by browser address bars). but I am concerned that if I do this then it defeats the purpose of the top level GET /v1/cars endpoint?


    Thanks to the helpful guys over at the #laravel irc channel who I had rather an extended conversation with we have an answer that seems to work.

    We chose this answer based on a few thing:

  • Ease of human readability
  • Power of queries
  • Flatness (Ease of parsing)
  • Ease of filtering
  • The basic request would be

    GET /v1/cars?color=green
                &doors=2,4
                &garage[paint]=yellow
                &garage[bonnet][material]=carbon
    

    Which when combined with the following code

    $query = array();
    parse_str($_SERVER['QUERY_STRING'], $query);
    

    Spits out an array like below which can be easily iterated over in the API to do the filtering :)

    Array
    (
      [color] => green
      [doors] => 2,4
      [garage] => Array
        (
          [paint] => yellow
          [bonnet] => Array
            (
              [material] => carbon
            )
        )
    )
    
    链接地址: http://www.djcxy.com/p/40960.html

    上一篇: 在RESTful URL中使用动词和形容词的替代方法

    下一篇: 用于高级过滤静默API结果的URL设计