What are the best practices to make a good REST API request cache key? - rest

I am building a simple API service using Ruby on Rails. In production, I would like to integrate Redis/Memcached in order to cache some frequently-used endpoints with key-based caching. For example, I have a Car table with name and color fields.
My question is, what is the best way to define a cache key for a particular endpoint (eg. /cars) when the resource has variety of params that could come in different order? eg. /cars?name=honda&color=white, /cars?color=white&name=honda.
If I use request url as cache key I will have 2 different cache records but technically speaking, if both name and color have the same values, there should only be one cache record in Redis database.

arrange the parameters in alphabetical order and use that as the basis for a cache key.
/cars?name=honda&color=white
/cars?color=white&name=honda
in both cases the cache key would be based on the concatenated alphabetically listed parameters
colorname
So both the above reordered urls would result in the same cache key.

Related

REST API: Resource hierarchy and multiple URI

I work with a banking database, which is structured like this:
Table Primary Key Unique Keys Foreign Keys
-------------------------------------------------------------
BANK ID BIC
CUSTOMER ID CUSTNO, PASS, CARD BANK
ACCOUNT ID IBAN BANK, CUSTOMER
I want to design a clean REST API, but I run into following problems:
Should I put resources in a hierarchy, or rather flat? The problem with the hierarchy might be that the client only knows the ACCOUNT ID, but does not know the CUSTOMER ID, so how is he supposed to get the resource?
/banks/{id}/customers/{id}/accounts{id}
or
/banks/{id}
/customers/{id}
/accounts{id}
The primary key in each table is the database ID. It is an internal ID and has no business meaning. Is it correct to use it as the default URI of the resource?
Each object has its own set of unique keys. For example, CUSTOMER can be identified by his CUSTNO, PASS or CARD. Each client only has a subset of these keys. Should I define a sub-resource per key or provide a lookup service that will give the proper URI back?
/customers/id/{id}
/customers/custno/{custno}
/customers/pass/{pass}
/customers/card/{card}
or
/lookup/customer?keyType=card&keyValue=AB-303555
(gives back customer {id})
I am asking what is the truly RESTful way, what is best practice. I haven't found proper answers yet.
I am asking what is the truly RESTful way, what is best practice.
REST doesn't care what spellings you use for your identifiers.
/ef726381-dd43-4017-9778-83cee2bbbd93
is a perfectly RESTful URI, suitable for any use case.
Outside of some purely mechanical concerns, general purpose consumers treat a URI as a single opaque unit. There's no notion of a consumer extracting semantic information from the URI -- which means that any information encoded into the identifier is done at the server's discretion and for its use alone.
For cases where information known to the client needs to be included in the target-uri of the request, we have URI Templates, which are a sort of generalization of a GET form in HTML. So a way to think about your problem is to consider what information the client has, and how they would put that information into a form.
HTML's form processing rules are pretty limiting -- general URI templates have fewer constraints.
/customers/id/{id}
/customers/custno/{custno}
/customers/pass/{pass}
/customers/card/{card}
Having multiple resources sharing common information is normal in REST -- your resource model is not your data model. So this could be fine. It's even OK to have multiple resources that share representations. You could have them stand alone, or you could have them share a Content-Location, or a canonical link relation, or you could simply have those resources redirect to the canonical resource.
It's all good.
So you mean if a UUID can be a valid URI, then a table autonumber key can be too?
Yes, exactly.
Note that if you want the lifetime of the URI to extend beyond the lifetime of your current implementation, then you need to design your identifiers with that constraint in mind. See Cool URIs Don't Change.
The clients don't care what the URI is, they just want the link to work again when they need it.

REST full API composite key vs primary key

What is the best practice for REST full APIs when I have a primary ID for entity but at the same time this entity can be identified by composite key?
This can be done like this
HTTP GET /entity/333 - DB primary key
HTTP GET
/entity/CODE1/to/CODE2/with/CODE3 - this is example how URL for
composite key could look like
REST doesn't care what spellings you use for your URI; we really only care that the spelling you choose is consistent with the restrictions described in RFC 3986.
If you have two different identifiers, then as far as REST clients are concerned you have two different resources -- the representations returned to the client will be cached under different keys, invalidating one resource will not affect the other in any way.
It is perfectly reasonable two have two (or more) resources that share the same representations.
You can also have the requests for one resource redirected to another.
Part of the point of the hypermedia constraint in REST is that the server(s) control the URI space, so you can freely change them without breaking clients (restriction: breaking the bookmark URI will make a mess). URL shorteners work.
When designing path segments, it is often useful to keep in mind how relative-resolution works, so that your representations can reference other resources relative to a base url, rather than locking into a particular hierarchy.

NDB urlsafe keys and REST api requests

I was wondering what others are doing to expose REST api endpoints with the datastore (using app engine standard). I want to use urlsafe keys but 1 - I'd rather not pass this data directly as it poses a security risk since app-engine to app-engine calls are exposed over a public ip, and 2 - the keys that are generated are very long and would not be great when multiple need to be passed as a query parameter to form a get request (and would probably exceed browser character limits).
I was thinking maybe using compression of some sort to compress the urlsafe keys which would solve both 1 and 2, but want to see if there is a better way to create REST endpoints. Or if some type of compression method is already baked into ndb?
Google uses HTTPS internally so I'm not sure you need to worry about it.
Also, you should probably design your app so that keys are not secret info and such that it is safe to expose them.
I use key IDs for my REST calls, which I believe are 12 digit numbers. That works as long as you know the entity type. If you need to specify the entity type, you could add another parameter to your API call.

What is the best way to handle REST resource proposal generation?

I have this API : GET /travels/generate/{city-departure}/{city-arrival}
It generate a list of possible travels path (with train changes, etc).
Now these are not real resources because they don't have ID (they are only generated for proposal).
What is the best way to select one and save it in a RESTful way ? Should I create a temporary resource for each proposal like "GET /temporary-travel/{id}" ?
A REST resource does not need to have an ID. It must be identifiable. Your URLs
/travels/generate/{city-departure}/{city-arrival}
are completely OK to identify a resource.
A REST resource does not need to have an ID. It must be identifiable.
One solution would be using a list index (e.g. GET /travels/generate/{city-departure}/{city-arrival}/{index} ). This somehow needs you to remember the content and the order of the proposed travel paths.
To overcome the limitation of temporary storing possible travel paths, you may either store them permanently and providing them an static identifier or you may provide a domain specific key that consists of multiple chained static identifiers that provide an identity to your travel path (e.g. chaining all route segment IDs or so).
I somehow prefer the idea of storing all possible travel paths even knowing it is technically somewhat nearly impossible. I like it because the travel paths possibly provided by your system are kind of limited due to the algorithm and the data base you use.

Designing REST API

Currently, I have this resource:
GET /orders/{orderNumber}/{provisionId}/{taxYear}/docs
This returns the given order's documents. An Order is identified by three numbers: orderNumber, provisionId and taxYear. That is the primary key in the database.
I think this is a bad resource design and I want to change it, instead of use different path params for each composite primary key's part.
Is there a standard to model this kind of resources? I don't know how to manage entities that have composite id.
I have thought to do this:
GET /orders/{orderNumber,provisionId,taxYear}/docs
This would be one path param for the order identificator and server would split it to obtain each part.
Another choice I have thought is by query params:
GET /orders/docs?orderNumber=1234&provisionId=1054&taxYear=2015
But I think the last one wouldn't be semantically correct in REST architecture, since in this case query params are required and are not " search filter" params.
Is there any standard to do this? Which is the better choice?
Thanks