The proper way to represent ranges in semantic URLs

84 Views Asked by At

Working on a little side project, I have now the opportunity to design my very own API. Event if it is not a business endeavor, it's the occasion for me to learn more about REST, Resources, Collections and URIs.

My service, records data points organized in time-series and will soon provide an API to easily query ranges of data points from specific series. Data points are immutable and as such should be very good candidates for caching. Time-series can be updated only during a limited time window, after which they are archived and readable only (making them also "cachable").

I have been looking into the APIs of some companies that provide the same kind of services, and I found the following two patterns:

  1. Define the series in the path and the range in the query:

    /series/:id?from=2017-01-26&to=2017-01-27

    This is pretty much what most services out there are using. I understand it as the series being the resources/collections that are then sliced to a specific range. This seems to be very easy to use from a consumer point of view, but from a data point of view, the dates in the query are part of some kind of organization or hierarchy and should in this case be part of the path.

  2. Define the series and coordinates in the path:

    /series/:x/:y/:z

    I didn't find examples of this for time-series, but it is the kind of structure used for tile based map services. Which, to me, means that each combination of x, y and z is a different collection, that might, in some cases contain the same resources or not. It also maps directly to some hierarchy, /series/:x contains all the series with a specific value of x and any value of y and z.

I really like the idea of the method 2. and I started with something like:

  • /series/:id (all data points from a specific series)

  • /series/:id/:year (all the data points from a specific series and year)

  • /series/:id/:year/:month

  • /series/:id/:year/:month/:day

  • ...

Which works pretty well for querying predefined ranges such as "all the data points from 2016" or "all the data points from January 2016". Issues arise when trying to query arbitrary ranges like "all the data points from January 2016 to March 2016".

My first trial was to simply add the start and end to the path:

  • /series/:id/:year (all the data points from a specific year)

  • /series/:id/:fromyear/:toyear (all the data points between fromyear and toyear)

But:

  1. It becomes very long, very quick. Example: /series/:id/:fromyear/:frommonth/:fromday/:toyear/:tomonth/:today and potentially very cumbersome depending of the chosen structure /series/:id/:fromyear/:toyear/:frommonth/:tomonth/:fromday/:today

  2. It doesn't make any sense from a hierarchy or structure point of view. In /series/1/2014/2016, 2016 is not a subset of 2014 and this collection is actually going to return data points from 2014, 2015 and 2016.

  3. It is tricky to handle on the server side. Is /series/1/2016/01/02 supposed to return all the data points for the January the 2nd or for the whole January to February range ?

After noticing the way that Github references specific lines or ranges of lines in their fragment, I played with the idea of defining ranges as being different collections, such as:

  • /series/:id/:year/:month (same than before)
  • /series/:id/:year/:frommonth-:tomonth (to get a specific range)
  • /series/:id/:year/-:tomonth (to get everything from the beginning of the year to tomonth)
  • /series/:id/:year/:frommonth- (to get everything from frommonth to the end of the year)

Now, the questions:

  1. Does my solution break any REST or Semantic URL rules/notions/ideas?
  2. Does it improve caching in anyway compared to using ranges in the query?
  3. Does it hurt usability for consumers?
  4. Is it unnatural or going against unwritten rules of some Frontend frameworks?
0

There are 0 best solutions below