Modelling actions in REST - api

I'm making a REST interface to a management system (let's call this system A) for network equipment and I have everything working. A fetches the equipment information from another backend system (let's call this system B) and index it in a database and then whenever a client asks for the information over the REST interface it returns it as JSON.
However sometimes a client needs to forcefully make A refresh some equipment information by requesting it from B (without the client being involved besides asking A to refresh it). Refreshing the information for a single node takes several seconds so the information should probably not be returned in the same request as in which it is requested. Currently we've modeled this as that you create a job of a "refresh information" type using POST /jobs with some data. But this feels very over engineered and we'd much rather want something like POST /equipment/<id>/refresh but this feels to go against the "REST way"?
Is there any other solution to this than the one mentioned with jobs above but still follow the "REST way"?

I would use GET /equipment/<id>?since=<timestamp>, where the since parameter is optional. Semantically this means:
Get the equipment with the given id as of whenever it happened to be last refreshed (when timestamp not given), or
Get the equipment with the given id refreshed no earlier than the given timestamp
Each equipment in your system would have a last_refreshed timestamp. The GET with the since=<timestamp> parameter would refresh the equipment if last_refreshed < since and then return the equipment.
A user of your service could then say GET /equipment/123?since=<15 minutes ago> and be sure they're always getting info that's no older than 15 minutes. GET /equipment/123?since=<now> means "force a refresh."

Keep in mind that POST in Rest services means that you will create some object.
To refresh one object, or update, it's recommended the PUT method.
Like um CRUD, when you have Create, Read, Update, and Delete, in REST will be POST, GET, PUT, DELETE (in order).
Maybe in your case the best URL for this is a PUT to /equipment/<id>.
URLs:
POST to /equipment/ : Create equipment
GET to /equipment/<id>: Read equipment with id <id>
PUT to /equipment/<id>: Update equipment with id <id>
DELETE to /equipment/<id>: Delete the equipment with id <id>
I hope that solve you doubt.
Anyway, a good reference it's the Apigee ebooks

Related

What happens to related resources when a resource receives a DELETE request?

Let's say an API has the method DELETE for the endpoint /authors/:id, which also deletes all posts by said author.
I understand that, when an author is deleted from the database, all GET requests to /authors/:id/posts should respond with 410 GONE, indicating that said resource is no longer available.
How should the API understand that the resource used to exist but no longer does? After all, the query SELECT * FROM posts WHERE author_id = id; is empty.
The only "solution" I thought of was to not delete the posts, but check the existence of the author in the database and act accordingly.
In most business applications, you don't really want to delete records during the normal flow of operation, especially if you then have to cascade those deletes.
For instance, in a finance application, when a customer stops doing business with you, you don't want to delete that customer record and all the sales in the past - you want to set a flag saying "this customer is no longer active".
That's often referred to as a soft delete.
Your REST API can interpret the deleted status to issue the correct status code (GONE, rather than NOT FOUND)

Is it Ok to make a POST endpoint to create an entry in a database idempotent?

I have an endpoint that inserts a stock ticker into a table in a DB. I personally don't care if this endpoint gets hit with a ticker that already exists in the DB. I'd like to just return a 201 no matter what. If it doesn't exists, it gets created. If it does exist, just no op and tell the user it was created.
I feel like this is Ok because it's just a simple lookup table that is being controlled internally. If I had others consuming the API that were trying to create their own stock tickers in an app then that's a scenario when I don't want it to be idempotent and alert the user.
Does this break REST standard though? Should a POST, used in this context, not be idempotent? What are potential downsides to doing this?

Optimizing GraphQL resolvers for SQL databases and in service-oriented architectures

My company has a service-oriented architecture. My app's GraphQL server therefore has to call out to other services to fullfill the data requests from the frontend.
Let's imagine my GraphQL schema defines the type User. The data for this type comes from two sources:
A user account service that exposes a REST endpoint for fetching a user's username, age, and friends.
A SQL database used just by my app to store User-related data that is only relevant to my app: favoriteFood, favoriteSport.
Let's assume that the user account service's endpoint automatically returns the username and age, but you have to pass the query parameter friends=true in order to retrieve the friends data because that is an expensive operation.
Given that background, the following query presents a couple optimization challenges in the getUser resolver:
query GetUser {
getUser {
username
favoriteFood
}
}
Challenge #1
When the getUser resolver makes the request to the user account service, how does it know whether or not it needs to ask for the friends data as well?
Challenge #2
When the resolver queries my app's database for additional user data, how does it know which fields to retrieve from the database?
The only solution I can find to both challenges is to inspect the query in the resolver via the fourth info argument that the resolver receives. This will allow it to find out whether friends should be requested in the REST call to the user account service, and it will be able to build the correct SELECT query to retrieve the needed data from my app's database.
Is this the correct approach? It seems like a use-case that GraphQL implementations must be running into all the time and therefore I'd expect to encounter a widely accepted solution. However, I haven't found many articles that address this, nor does a widely used NPM module appear to exist (graphql-parse-resolve-info is part of PostGraphile but only has ~12k weekly downloads, while graphql-fields has ~18.5k weekly downloads).
I'm therefore concerned that I'm missing something fundamental about how this should be done. Am I? Or is inspecting the info argument the correct way to solve these optimization challenges? In case it matters, I am using Apollo Server.
If you want to modify your resolver based on the requested selection set, there's really only one way to do that and that's to parse the AST of the requested query. In my experience, graphql-parse-resolve-info is the most complete solution for making that parsing less painful.
I imagine this isn't as common of an issue as you'd think because I imagine most folks fall into one of two groups:
Users of frameworks or libraries like Postgraphile, Hasaura, Prisma, Join Monster, etc. which take care of optimizations like these for you (at least on the database side).
Users who are not concerned about overfetching on the server-side and just request all columns regardless of the selection set.
In the latter case, fields that represent associations are given their own resolvers, so those subsequent calls to the database won't be fired unless they are actually requested. Data Loader is then used to help batch all these extra calls to the database. Ditto for fields that end up calling some other data source, like a REST API.
In this particular case, Data Loader would not be much help to you. The best approach is to have a single resolver for getUser that fetches the user details from the database and the REST endpoint. You can then, as you're already planning, adjust those calls (or skip them altogether) based on the requested fields. This can be cumbersome, but will work as expected.
The alternative to this approach is to simple fetch everything, but use caching to reduce the number of calls to your database and REST API. This way, you'll fetch the complete user each time, but you'll do so from memory unless the cache is invalidated or expires. This is more memory-intensive, and cache invalidation is always tricky, but it does simply your resolver logic significantly.

Should an API assign and return a reference number for newly created resources?

I am building a RESTful API where users may create resources on my server using post requests, and later reference them via get requests, etc. One thing I've had trouble deciding on is what IDs the clients should have. I know that there are many ways to do what I'm trying to accomplish, but I'd like to go with a design which follows industry conventions and best design practices.
Should my API decide on the ID for each newly created resource (it would most likely be the primary key for the resource assigned by the database)? Or should I allow users to assign their own reference numbers to their resources?
If I do assign a reference number to each new resource, how should this be returned to the client? The API has some endpoints which allow for bulk item creation, so I would need to list out all of the newly created resources on every response?
I'm conflicted because allowing the user to specify their own IDs is obviously a can of worms - I'd need to verify each ID hasn't been taken, makes database queries a lot weirder as I'd be joining on reference# and userID rather than foreign key. On the other hand, if I assign IDs to each resource it requires clients to have to build some type of response parser and forces them to follow my imposed conventions.
Why not do both? Let the user create there reference and you create your own uid. If the users have to login then you can use there reference and userid unique key. I would also give the uid created back if not needed the client could ignore it.
It wasn't practical (for me) to develop both of the above methods into my application, so I took a leap of faith and allowed the user to choose their own IDs. I quickly found that this complicated development so much that it would have added weeks to my development time, and resulted in much more complex and slow DB queries. So, early on in the project I went back and made it so that I just assign IDs for all created resources.
Life is simple now.
Other popular APIs that I looked at, such as the Instagram API, also assign IDs to certain created resources, which is especially important if you have millions of users who can interact with each-other's resources.

The REST-way to check/uncheck like/unlike favorite/unfavorite a resource

Currently I am developing an API and within that API I want the signed in users to be able to like/unlike or favorite/unfavorite two resources.
My "Like" model (it's a Ruby on Rails 3 application) is polymorphic and belongs to two different resources:
/api/v1/resource-a/:id/likes
and
/api/v1/resource-a/:resource_a_id/resource-b/:id/likes
The thing is: I am in doubt what way to choose to make my resources as RESTful as possible. I already tried the next two ways to implement like/unlike structure in my URL's:
Case A: (like/unlike being the member of the "resource")
PUT /api/v1/resource/:id/like maps to Api::V1::ResourceController#like
PUT /api/v1/resource/:id/unlike maps to Api::V1::ResourceController#unlike
and case B: ("likes" is a resource on it's own)
POST /api/v1/resource/:id/likes maps to Api::V1::LikesController#create
DELETE /api/v1/resource/:id/likes maps to Api::V1::LikesController#destroy
In both cases I already have a user session, so I don't have to mention the id of the corresponding "like"-record when deleting/"unliking".
I would like to know how you guys have implemented such cases!
Update April 15th, 2011: With "session" I mean HTTP Basic Authentication header being sent with each request and providing encrypted username:password combination.
I think the fact that you're maintaining application state on the server (user session that contains the user id) is one of the problems here. It's making this a lot more difficult than it needs to be and it's breaking a REST's statelessness constraint.
In Case A, you've given URIs to operations, which again is not RESTful. URIs identify resources and state transitions should be performed using a uniform interface that is common to all resources. I think Case B is a lot better in this respect.
So, with these two things in mind, I'd propose something like:
PUT /api/v1/resource/:id/likes/:userid
DELETE /api/v1/resource/:id/likes/:userid
We also have the added benefit that a user can only register one 'Like' (they can repeat that 'Like' as many times as they like, and since the PUT is idempotent it has the same result no matter how many times it's performed). DELETE is also idempotent, so if an 'Unlike' operation is repeated many times for some reason then the system remains in a consistent state. Of course you can implement POST in this way, but if we use PUT and DELETE we can see that the rules associated with these verbs seem to fit our use-case really well.
I can also imagine another useful request:
GET /api/v1/resource/:id/likes/:userid
That would return details of a 'Like', such as the date it was made or the ordinal (i.e. 'This was the 50th like!').
case B is better, and here have a good sample from GitHub API.
Star a repo
PUT /user/starred/:owner/:repo
Unstar a repo
DELETE /user/starred/:owner/:repo
You are in effect defining a "like" resource, a fact that a user resource likes some other resource in your system. So in REST, you'll need to pick a resource name scheme that uniquely identifies this fact. I'd suggest (using songs as the example):
/like/user/{user-id}/song/{song-id}
Then PUT establishes a liking, and DELETE removes it. GET of course finds out if someone likes a particular song. And you could define GET /like/user/{user-id} to see a list of the songs a particular user likes, and GET /like/song/{song-id} to see a list of the users who like a particular song.
If you assume the user name is established by the existing session, as #joelittlejohn points out, and is not part of the like resource name, then you're violating REST's statelessness constraint and you lose some very important advantages. For instance, a user can only get their own likes, not their friends' likes. Also, it breaks HTTP caching, because one user's likes are indistinguishable from another's.