I am developing a REST API where users can request data from one or more sensors, using the following scheme:
GET /sensors - returns a list of available sensors
GET /sensors/<sensor_ids>/data - returns data for one or more sensors, specified by sensor_ids
But the client also wants users to be able to send a request without a sensor_id
, which will return all available data for all sensors.
I was thinking there are two ways we could do this:
GET /sensors/all/data - specify sensor_id as "all"
GET /sensors/data - omit the sensor_id altogether
I am not sure which would be the better option and most consistent with REST best practices. Data and sensors are both resources, but data is always associated with a sensor.
Any suggestions would be appreciated.
-
1Not knowing anything about the domain. 'All' is a dangerous concept when it comes to sending data over the wire. Consider baking in paging or some other mechanism for if/when all data in 1 call isn't feasible from a performance perspective.Ian Jacobs– Ian Jacobs2022年05月12日 17:52:46 +00:00Commented May 12, 2022 at 17:52
3 Answers 3
It seems a bit weird to me that sensor ID is a part of resource path yet you mention one or more IDs.
I'd like to think of a single resource /sensors/data
. Sensor IDs can be considered as optional filters of all sensor data, passed through query parameters. You might have:
GET /sensors/data
– return data for all sensors (paginated, as suggested by @Ian Jacobs in the comment).GET /sensors/data?sensorId=1
– return data for sensor with ID = 1.GET /sensors/data?sensorId=1,2,3
or alternativelyGET /sensors/data?sensorId=1&sensorId=2&sensorId=3
– return data for sensors with ID 1, 2, and 3.
This API is also much more flexible/extensible. You can define more filters, like time range, etc. One might imagine the following request:
GET /sensors/data?sensorId=1,2&from=2022年05月01日&to=2022年05月13日
-
Thanks! But if a user sends a GET to
/sensors/<sensor_ids>
they currently receive information about that sensor or collection of sensors (i.e., metadata). For example, the type of sensor, what it measures, where it's located, when it was installed, etc. And a GET to/sensors/<sensor_ids>/data
gives the data recorded by that sensor. I'm not sure how the former case would work under the scheme you proposed.JoshG– JoshG2022年05月13日 01:36:27 +00:00Commented May 13, 2022 at 1:36 -
But we do have filters set up on the Data resource. So similar to your example, passing parameters in the query string is possible. Currently this is just start and end dates but could be expanded upon.JoshG– JoshG2022年05月13日 01:38:13 +00:00Commented May 13, 2022 at 1:38
-
1What stops you from having
/sensors?sensorId=1
for metadata, then? :) You can also extend this filtering by e.g. sensor name, measurement, etc.Archie– Archie2022年05月13日 09:05:54 +00:00Commented May 13, 2022 at 9:05 -
True, that's a good point. I like the idea. Thanks so much for the suggestion!JoshG– JoshG2022年05月13日 20:41:03 +00:00Commented May 13, 2022 at 20:41
Since all
is not a resource, you shouldn't use it in a resource URL but data
, however, is so /sensors/data
is the more correct option.
There is no need to insert a unnecessary /all
in the route. Keep it simple and short. GET /sensors/data
is absolutely fine.
/sensors/all/data
could also cause trouble if all
is a valid id.