Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
Was arguing with someone about REST API Design.
I have the routes GET /customers and GET /customers/<c-id> where c-id is the id of a customer.
Now the question is about adding a route for projects.
GET /customers/<c-id>/projects gives all projects of a customer. That someone suggested now to add GET /customers/<c-id>/projects/<p-id> to get information about one specific project. I have a bad feeling about that. Since p-id is a unique id for all projects, the c-id is not needed in the request at all. GET /projects/<p-id> should just do. c-id also is an attribute of the returned project json (every project belongs to just one customer). So this is the main question here: is it consistent with good practice to have the in my opinion superfluous c-id in the request?
One argument from the other side was this example from a blog:
GET /cars/711/drivers/4
But as far a I understand this only applies as good practice if 4 is not a unique identifier, but rather an enumeration in the example (the fourth driver of this car).
Further information:
Actually GET /projects is not used at the moment. So I also thought about adding it and using GET /projects?customerid=<c-id> instead of GET /customers/<c-id>/projects. What do you think about that?
Also the application in question has a permissions layer. So someone who's not allowed to access a specific customer should not be allowed to access projects of this customer, even if he knows the project-id. It was argued that this restriction is better expressed in the GET /customers/<c-id>/projects/<p-id> route. (The permission is actually decided upon a user-id attribute which is a property of customer and project likewise.) Would this change your answer to the question?
So this is the main question here: is it consistent with good practice to have the in my opinion superfluous c-id in the request?
Sure, why not?
REST doesn't care what spellings you use for URI.
Where I think you are getting tangled up; there is no rule that says each entity in your domain model must have one and only one resource associated with it.
It is perfectly acceptable to have resources like
/customers/<c-id>/projects/<p-id>
/customers/<c-id>/projects/<local-index>
/projects/<p-id>
/9e7b964a-c87a-4184-84b1-24132aabab66
that all map to the same concept in your domain model, and therefore return the same representations, or redirect to each other, or whatever.
It was argued that this restriction is better expressed in the GET /customers//projects/ route. (The permission is actually decided upon a user-id attribute which is a property of customer and project likewise.) Would this change your answer to the question?
No, because identification and security are orthogonal concerns.
Actually GET /projects is not used at the moment. So I also thought about adding it and using GET /projects?customerid= instead of GET /customers//projects. What do you think about that?
Same as before
/customers/<c-id>/projects
/projects?customerid=<c-id>
/a685ee45-f366-462b-a47a-dff61f98dd1e
... are all perfectly reasonable choices.
One thing which you may want to consider is RFC 3986, which specifies the rules for computing a new identifier given a base and a relative reference. Dot segments can be a convenient shorthand for directing the client to another reference without needing to worry about which base identifier is currently in scope.
We are discussing here two approaches.
To Divide url as custId + projId *
Yes. I will prefer this approach as well as it will be easy to handle authorization mechanism as compared to another approach.
If this is also case that 3 different customers have same project Id then also this type of structure will be helpful.
To access directly using project Id.
In this approach you will have to retrieve custId first and then check for authorization.
GET /customers/<c-id>/projects/<p-id> looks like a better option:
it clearly communicates that every project is assigned to one customer
it is clear that only when the user has access to /customers/<c-id> he can call /customers/<c-id>/projects/*
the fact that <p-id> are globally unique is an implementation detail and does not have to be communicated in the REST API
If your goal is to design a RESTful API which stands the test of time, your clients shouldn't really care what your URLs look like.
(i.e. embracing HATEOS)
In fact you should insist on your clients not trying to construct URLs based on some form of URL template.
If a client needs to get the list of projects for a customer, your hypertext (i.e. the resource representation returned to the client) should include an URL + instructions on how to do so.
That is how HTML handles it: You get a form URL and various HTML tags that describe how to add parameters to the URL to find a specific resource.
That's why you can have a generic client application (the browser) to - for example - a bank. The browser doesn't care what an account is, it just knows how to retrieve resources.
Going full REST is extra work that is worthwhile if you have no control over who your clients (the software making requests to your service) are and you are looking to evolve your API for many years to come without forcing unnecessary changes to your clients.
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
Based on the articles I read, GraphQL is more resource-efficient in terms of roundtrips and it can also do what REST can provide. What are the reasons why software architect & developers might decide to stay with REST over GraphQL given that the web application will just be started from scratch? Also given that this is a continuous project, will be consumed from web and mobile and openID connect is a requirement.
This is a rather broad question but I'll try answer speaking from my own experience.
REST provides access to a specific resource, e.g. a user or a product. The result from a request will likely be an assumption of what data you will want or use, i.e. it's probably everything about that resource regardless of whether you use all the data or not.
There is also the problem of N+1. As an example, take the user has and belongs to many relationships scenario; with a RESTful API you would make a request to the user, e.g. /users/:id then make a request to all their relationships, e.g. /users/:id/relationships, so that's two requests already. There could be an assumption of the relationships endpoint to include both the relationship (friend, family member, etc.) and the user in the resulting array, but if the API doesn't make that assumption, you're going to have to make a request to each user endpoint to get the data on each user in each relationship.
This example can go deeper too; what if you want all second tier relationships (friends of friends for instance)?
GraphQL solves this by allowing you to ask for specifically what you need. You can construct a query to return the data at depth:
query myQuery($userId: ID!) {
user(id: $userID) {
id
name
relationships {
id
type
user {
id
name
relationships {
id
type
user {
id
name
}
}
}
}
}
}
Fragments could clean this up a bit and there may be recursive issues, but you should get the idea; one request gets you all the nested data you need.
If you don't have much need for such nested or inter-connected result sets, GraphQL may not offer much in a trade between benefit and complexity.
However, one of the greatest benefits I have found with GraphQL is its extensibility and self-documentation.
In my opinion, it is – among other aspects – also a question of use cases:
If you have something like an app or other frontend with a connection that is slow and/or has high latency (typical example: a mobile app), GraphQL’s “roundtrip minimisation” can be a big plus. And it can be pretty handy to give the client-side control over the data structure, thus often reducing the number of required API endpoints.
If it’s rather data exchange between servers, the fact that RESTful APIs are strongly related to HTTP, has advantages such as the semantics of verbs (which GraphQL cannot offer, as you perform several operations with one GraphQL query) and status codes. Plus: you get all the HTTP caching functionality for free, which can be really important in heavily data-driven applications/services. In addition, REST is ubiquitous (although probably most APIs advertised as “RESTful” aren’t, often due to missing support for hypermedia).
There might be multiple reasons. This is very subjective I believe, but to me it's based on:
REST is the old and steady way. It is used by the most and provides an easy interface to API consumers. Because it's old (by no means a bad thing) most developers know of it and know how to consume it.
GraphQL is the new guy in town. It sure does save some performance (roundtrips and payload) for most systems, but does change the way we think of a backend. Instead of providing resource endpoints, it provides the graph of the data model and let the consumer decide what data to get.
As of the point of the "new guy", GraphQL is not as battle tested. It is new to most and there fore not adopted by others and the first-movers and startups, basically.
But again, this is a subjective question with a subjective answer. Currently I am using GraphQL for a startup to test it's durability and see if it can solve our needs. So far, it does by far. If you are to make a decision on wether to start a new project with REST or GraphQL you should be consider your needs and how much money/time you want to spend learning new vs. doing what you know and get to your goal faster.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
If an API only allows retrieval of data (through GET) and does not allow Create, Update or Delete is it still RESTful?
I question this because Wikipedia says "When a client holds a representation of a resource, including any metadata attached, it has enough information to modify or delete the resource." as a constraint of REST.
I'm sorry if this seems like a silly question but I'm trying to get to the point where I can say 'I understand REST' confidently.
Yes, a system can use REST even if it doesn't allow modification of the resources.
The most common implementation and use of REST is HTTP 1.1 used for the world wide web (even if the RESTfulness is implemented vith varying success). A vast majority of the resources are read-only.
I believe that the API is still RESTful if even if it does not implement all of the verbs. This simply will not make sense for all resources. Some verbs may not apply, or a client may not be authorized to perform them.
Take for example newspaper articles. I could see that GET is the only available verb as the news site may only publish the API for reading (i.e. getting) the articles.
As for the Wikipedia definition, I would change that slightly to say "it has enough information to attempt to modify or delete the resource."
And the API can communicate support/non-support of certain verbs by response codes. If DELETE is not supported, a client DELETE request would see a HTTP 405 (not supported) response.
REST is not coupled to any particular protocol, so what methods are being used does not affect the RESTfulness of an API, as long as the methods are used for their standardized behavior and any deviations are documented. For instance, there's nothing preventing you from having a similar "read-only" API implemented over FTP, using the RETR method.
What really matters is how clients obtain the URIs for the resources they are retrieving. If they are using out of band information, like URI patterns in documentation, it's not RESTFUL. Resources should have links referencing each other and clients should be able to find anything they want starting from an initial entry point URI. Do some googling for HATEOAS if you have doubts on that.
I'm completely new to REST. I helped to implement something that was called REST at work but it breaks so many of the rules that it's hard to qualify it as REST. I want to follow the HATEOAS guideline and the remaining question I have is regarding documentation of media types and their specification. Namely when one media type is really an extension of another.
For example, I've decided on 'application/hal+json' for the base media type. Everything that a user would receive is going to be a HAL blob with some added fields. I don't want to call my media types just 'application/hal+json', it seems to me more information should be available than that, but I want it to be clear that this is what they are in addition to the extra fields that are my data. Furthermore my system is going to end up having some of these fields inherited and such in both the request (which won't be HAL blobs) and response formats. A generic "User" type might have just a user id and name for example while an extension like "Student" or "Teacher" will have different additional fields.
Does it make sense to represent this extension somewhere in the media type itself? Do people generally document the relationship in their HATEOAS documentation links? If so, what's the general trend here? I want my API to be easy to use and thus figure it should follow norms that are available.
Couple of things i'd like to point out about your move to a true RESTful architecture.
First, RESTful APIs must perform content negotiation. To say your base type is hal+json is seems strange. It sounds like you want to have types like parent+hal+json or maybe hal+json;type=parent. This would mean your client would have to understand these types specifically...and this would be not very RESTful because it's just a local implementation. This is fine in the real world..you can do this...almost everyone does stuff like this.
To be true RESTful api you'd have to offer similar support for other content types...that could get messy.
Now specifically to HAL, there's two things available to you so that your client can "discover" what data types they are getting back. One is CURIEs and the other is Profiles https://datatracker.ietf.org/doc/html/draft-kelly-json-hal-06#section-5.6 I think Profiles is more what you're after here as it allows you to document conventions and constraints for the resource that will be retrieved.
But don't count out CURIE's either. There's lots of defined semantics out there already. Your model might fit one of http://schema.org sets and then you can just use their link relationships and the client should know what's going on.
If you really want a lot of control on the semantics of your resources...you may want to look at http://json-ld.org/ with it's #context concept would be a good reference.
In my opinion this is an area where the examples are very thin, especially for HAL. I've yet to seen a client smart enough to parse and care about semantics at run time. What i think is important is when someone is building the client that info is available they can figure out that a Student is a Person. One day the thing building the clients will be client generator code and it'll use that info to build a nice client side object model for you.
TL;DR if you stick with HAL use CURIEs and Profiles to get what you want.
This question is an extremely open ended discussion and it really depends on how different engineers interpret REST standards and best practices. Nonetheless, As a fellow software engineer with enough experience with REST services development (and faced the same questions professionally as you did), I would add my inputs here.
REST service development rules are heavily dependent on the url definitions. It's very important that you expose your apis in such a way that your clients can understand exactly what's happening per api just by looking at the url definition.
With that being said, different clients (and for that matter different engineers) view the best practices differently. For example, if you are trying to search a User by email, there are atleast two approaches
1) GET /users/emails/{email} // A client can interpret this as
"getting a user by email"
2) GET /users?email={email} // A client can interpret this as
"searching a user by email" because of query param
3) GET /users/email={email} // This can be interpreted just as # 1
It depends on the developer how they want to expose this api and how they document it for the clients. All the approaches are correct in different perspectives.
Now going specific to your questions. Here's what my approach would look like in terms of "User", "Student" and "Teacher".
I look at each of these 3 as separate resources? Why? because they are separate types even though 2 of them are extended from the 3rd one. Now how would my apis look like for these?
For Student:
1) Retrieving a list of students : GET /students
2) Retrieving a Student with id: GET /students/{id}
3) Creating a Student : POST /students
4) Updating a student : PUT /students/{id}
5) Delete a student: DELETE /students/{id}
6) Search a student: GET
/students?{whateverQueryParamsYouWantForSearch}
The same will be applied for Teacher as well.
Now here's for User.
1) GET /users : Retrieving list of all the users (Students and
Teachers)
2) GET /users?type={type} : Here's the kicker. You can specify the
type to be student OR teacher and you will return the data of specific
type (properly documented ofcourse)
3) POST /users?type={type} : Create a specific TYPE of user
(student or teacher)
.. And so on.
The main difference is .. the apis with root url /users can be used for BOTH types of users (Provided the type is always specified and documented to the clients). While the Student and Teacher apis are specific to those types.
My money has always been on specific types while generic types for searching (meaning for searching both types of users .. use /users?params). It's the most easy way for the clients to understand what's going on. Even documenting them is much easier.
Finally talking about HATEOAS. Yes, it's a part of the standards and the best practice is to ALWAYS provide a url/link to the resource you are returning or if your return object is complex and contains other resources which might contain resources who might themselves be exposed through apis. For example,
/users?type=student&email=abc#abc.com
will return all users with that email and it's better to follow HATEOAS here and provide a url to each returned user such that the url looks like : /students/{id}. This is how we have normally handled HATEOAS
That is all I have to add. As I said earlier, its a very open ended discussion. Each engineer interprets the standards differently and there is no ONE WAY to handle all usecases. There are some base rules and the clients and other developers will applaud you if you follow them :)
Most REST tutorials arranged resources as following:
GET /car/ -> list of cars
GET /car/<id>/ -> info about specific car
POST /car/ -> create a new car
but when building web applications for use in browsers, there is a missing link that are rarely discussed, before you can POST to /car/, you need to GET a form for creating a new resource (car). What should the URL for this form be?
I typically used:
GET /car/new/ -> form for creating a new car
POST /car/new/ -> redirect to /car/<id>/ if item is created else show form with invalid fields highlighted
but according to http://www.slideshare.net/Wombert/phpjp-urls-rest this is not a good REST URL. I can see why it's not a good REST, because "new" is really used as a verb and not a resource, but where should the form be then, because GET /car/ is already used for listing cars, so you can't use GET /car/ for the form for new cars.
In short, my question is: "What is the RESTful URL for 'create resource form'?"
On a slightly related note, even in a web service, it is sometimes not always wise to rely on the client knowing the schema in advance, therefore even in web services there could be a need to be a way for client to request the resource's current schema. AFAICS, this as a similar situation with the need to GET a create form (i.e. the form is sort of like a schema which describes how to construct POST query for creating the resource). Is my line of thought here correct?
REST does not care too much about what your URI looks like as long as it identifies one unique resource and is self-describing. Meet those criteria, and beyond that, it is personal preference. Nothing prohibits using a verb in a URI if it makes sense to use one.
In regards to your slightly related note, what you hint at with the form being a schema is media type. RESTful architecture concerns the client and the server both understanding the media types used to represent the application state.
A REST API should spend almost all of its descriptive effort in
defining the media type(s) used for representing resources and driving
application state, or in defining extended relation names and/or
hypertext-enabled mark-up for existing standard media types. Any
effort spent describing what methods to use on what URIs of interest
should be entirely defined within the scope of the processing rules
for a media type (and, in most cases, already defined by existing
media types).
Read more here: http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven
That is from Roy Fielding, the man who defined REST. In general, your media types should be extensible -- that is, any changes should add on and not break older clients unless necessary.
I always assumed that "form" as such is not a resource, so /<name>/new is okay - forms are not usual elements of APIs. Author of the slides put that on a "bad" list, but didn't provide a correct one - I assume he was so RESTful that he forgot to think about such cases.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
Along with half of the web developer community, I've been struggling to really and truly grok the REST style. More specifically, I've been trying to form some opinions on how practical a pure RESTful architecture really is between a web browser and an application server.
As part of my learning endeavor, I've been taking a look at some online examples of REST, specifically Twitter in this case. In their API documentation, they discuss their various "REST API Methods".
I'm struggling with rationalizing how exactly most of these are actually RESTful, beyond having a RESTful URL structure. Consider, for example, a simple GET request to http://twitter.com/favorites.
In a pure implementation of REST, I would expect identical requests to that URL, regardless of the initiating client, to return identical responses. In this particular case, though, we would obviously all see different responses depending on our currently authenticated users, which implies that our requests are being connected to some form of client state on the server before a response can be generated.
Hopefully that provides enough context for my question then - can that really be called "REST"? I get the impression that 90% of the so-called RESTful implementations between web browsers and application servers demonstrate this same inconsistency, where the restrictions on client state stored on the server are ignored.
Twitter breaks pretty much every REST constraint. Your example of http://twitter.com/favorites returning different results based on the authenticated user is an example of Twitter violating the "Resource Identification" constraint. Each interesting resource should have a unique identifier. My Twitter favorites and your Twitter favorites are two different resources and therefore should have two different URIs.
This actually is not related to idempotency at all. Idempotency is about being able to make the same request multiple times and it have the same effect. Even Twitter respects idempotency. If I GET my favorites multiple times, I still get my favorites back. How many times I do GET does not affect the result.
There are many other ways in which Twitter break the REST constraints. Many of these issues have been covered here on SO before.
Update
After perusing the Twitter api docs a bit more there is actually an alternative URI format that does properly identify the favourites resource. Here they show how to create an URL like:
http://api.twitter.com/1/favorites/bob.json
It still is a long way from being RESTful, but at least that's a step in the right direction.
In this context, idempotence is a tricky word. Even if you were retrieving an individual tweet, you would get a different result if that tweet were editable and someone edited it. When retrieving a list, I would certainly expect a tweet to retrieve the most current list.
It might be more helpful to think of idempotence as the ability to do something without causing side effects. So a GET is idempotent in this sense, but a POST is not.
From Wikipedia:
In computer science, the term
idempotent is used to describe methods
or subroutine calls that can safely be
called multiple times, as invoking the
procedure a single time or multiple
times has the same result; i.e., after
any number of method calls all
variables have the same value as they
did after the first call. Any method
or subroutine that has no side effects
is also idempotent.
Also from Wikipedia:
Methods PUT and DELETE are defined to
be idempotent, meaning that multiple
identical requests should have the
same effect as a single request.
In contrast, the POST method is not
necessarily idempotent, since
sending an identical POST request
multiple times may further affect
state or cause further side effects
(such as financial transactions [e.g. a customer getting mistakenly charged twice for the same product]).
See also:
How I Explained REST to My Wife
http://tomayko.com/writings/rest-to-my-wife
Looking at the documentation, the usage of the word "method" is probably a good indication whether that API is truly RESTful or not. There are a couple of resources that might actually qualify as such, like friends/<user-id> or favourites/<user-id>, but most of the resources are really just procedures, like account/update_profile_image for example.
The way I see it, in REST an URI should really just specifiy a thing, and not what you are going to do with it. If there is a verb in the URI (like update), you are most likely doing it wrong.
As the REST FAQ explains, the term "REST" is used to cover a wide array of things, including stateful applications that are structured in a RESTful style. Because the state is mostly being passed by the user in a cookie rather than stored on the server, it's considered RESTful. Roy Fielding (who invented REST) commented that as long as the entire state is being passed by the user, rather than a reference to state on the server, it's RESTful, since the same GET request will return the same result. Twitter's REST API is close to doing this, but not 100% there. It's not strictly the original meaning of "REST," but the interface and general philosophy are similar enough that it generally gets pulled under the same umbrella.
Technically, no, it's not RESTful. It's not stateless (a.k.a. idempotent as you mentioned) for one thing.
Reading the Twitter API i've come under the understanding that the RESTful API will be obsolete in a couple of weeks. Instead you should use the OAuth authentication method.