I'm designing a REST-API and currently I'm stuck with the following question. For example I got the following structure:
/foods/fruits/{fruit}
/foods/meat/{meat}
for example:
/foods/fruits/apple
/foods/fruits/pineapple
/foods/meat/chicken
Each of the endpoints is unique (only one apple, one chicken), but different sorts of fruits can exist (e.g. pineapple).
However my service needs to return either
one specific fruit (apple),
all fruits (collection-resource filled with all accessible fruits --> apple, pineapple)
or the whole food (composition of the collection-resources of fruits and meat)
With this design my resource is addressable about 3 URIs (composition, collection, endpoint), but it should be a maxima of 2.
It this a restful design?
Looking at the Richardson Maturity Model, you could have a generic Food resource and endpoint, with properties like type and name, and then your requirements would be accessible like so:
GET /api/food?name=apple
GET /api/food?type=fruit
GET /api/food
With this design my ressource is addressable about 3 URIs (composition, collection, endpoint), but it should be a maxima of 2. It this a restful design?
Could you provide a reference for the guideline that it should be a maxima of 2?
But either way - those three URIs are not 3 different URIs for the same resource, they are three different resources:
the food resource
a collection of foods of a particular type
a particular type of food
While the earlier resources can be considered to be composed of the others, it does not mean that the finest grain (the particular type, e.g. apple) is addressable via 3 URIs.
If you are using a hypermedia format such as HAL your composition representation could utilised embedded resources, which clearly illustrates that the contained resources are also available directly via their own endpoint.
Related
Using HTTP POST method/AnyMethod If a client is sending some information like name, number etc in a representation to server and server is storing it to DB then here name and number is called a resource?
or we are creating a resource in server with the information what client gave?
then client will not have a resource at any time?
Let's take a theoretical look at this:
resource = the intended conceptual target of a hypertext reference
[...]
The key abstraction of information in REST is a resource. Any
information that can be named can be a resource: a document or image,
a temporal service (e.g. "today's weather in Los Angeles"), a
collection of other resources, a non-virtual object (e.g. a person),
and so on. In other words, any concept that might be the target of an
author's hypertext reference must fit within the definition of a
resource. A resource is a conceptual mapping to a set of entities, not
the entity that corresponds to the mapping at any particular point in
time.
Source: Fielding, Roy Thomas. Architectural Styles and the Design of Network-based Software Architectures. Doctoral dissertation, University of California, Irvine, 2000 as referenced in RFC 7231.
In a brief interpretation that means that the resource is never any particular data but rather a mapping. Let's put it into something tangible:
GET /members
-> A resource called members (= set of entities) consisting out of username, e-mail address.
Members is considered a resource because it describes what the set of entities represent and because I've decided so.
To answer your questions:
> name and number is called a resource?
Depends on the context. Are you storing the name and number alone and independent from each other? Then they are resources, if they are part of something else, the resource would be the thing the two values describe (e.g. contact information).
Since the concept is abstract, you may even define three resources here: names, contact information and numbers. As it said, any information can be a resource, but that's not a must. So you are free to decide what you call a resource and what not.
> or we are creating a resource in server with the information what
> client gave?
No. We are creating an entity within a resource. The resource was defined by you earlier.
> then client will not have a resource at any time?
To be frank, I am sitting over this question for quite some time now - the dissertation doesn't state something specific but from interpreting and understanding the abstract concept, I'd say no. The server always holds the state of a resource, the client just gets or modifies it, but never provides any resource itself.
Related Questions:
What are REST resources?
What is the difference between resource and resource representation in REST?
If entity (e.g person) has data that has to be presented in different representations:
I have a big profile that has different representations but for a small example:
representations1:
GET /profiles/{id}/activity/projection1
returns:
{"actions":["add", "delete", "add"], "dates":[1499865456, 1499861544, 1499863655]}
representations2:
GET /profiles/{id}/activity/projection2
returns:
{add_at:[1499865456, 1499863655], delete_at:[1499861544]}
So the question: how to design such cases?
I have some ideas but don't know which one is better
GET /profiles/{id}/activity/projection1
GET /profiles/{id}/activity/projections/1
GET /profiles/{id}/activities/projection1
GET /profiles/{id}/activities/projections/1
GET /profiles/{id}/activity-actions and GET /profiles/{id}/activity-timestamps
I found only one same question Different RESTful representations of the same resource but it is about filtering data in response not about change model
A couple things to keep in mind
As far as REST is concerned, two things with different identifiers (URI) are different resources. The fact that they have the same source of truth is an implementation detail.
In designing a REST api, your resources are integration points. The representations of your resources will depend on the state of your model at any given time.
For instance, if I look up Clayton Kershaw at Baseball Reference, I am probably directed to this resource
http://www.baseball-reference.com/players/k/kershcl01.shtml
But if I ask to see his "2014 splits", then I'll be directed to this resource instead.
http://www.baseball-reference.com/players/split.fcgi?id=kershcl01&year=2014&t=p
There's no particular reason that every resource identifier related to kershcl01 has to be under the same root in the hierarchy.
You may want to review Cool URIs don't change; stable URI over time is a good goal for a design, in which case you'll want to make sure that temporary implementation details don't leak into the URI space.
Jim Webber's observation was that REST resources are part of your integration domain; "Resources adapt your domain model for the web."
So your design guidance should probably come from asking what properties are important to your consumers, and what constraints will ensure that those properties are present (outside in), rather than starting from your (current) implementation.
This question is about optimal REST API design and a problem I'm facing to choose between nested resources and root level collections.
To demonstrate the concept, suppose I have collections City, Business, and Employees. A typical API may be constructed as follows. Imagine that ABC, X7N and WWW are keys, e.g. guids:
GET Api/City/ABC/Businesses (returns all Businesses in City ABC)
GET Api/City/ABC/Businesses/X7N (returns business X7N)
GET Api/City/ABC/Businesses/X7N/Employees (returns all employees at business X7N)
PUT Api/City/ABC/Businesses/X7N/Employees/WWW (updates employee WWW)
This appears clean because it follows the original domain structure - business are in a city, and employees are at a business. Individual items are accessible via key under the collection (e.g. ../Businesses returns all businesses, while ../Businesses/X7N returns the individual business).
Here is what the API consumer needs to be able to do:
Get businesses in a city (GET Api/City/ABC/Businesses)
Get all employees at a business (GET Api/City/ABC/Businesses/X7N/Employees)
Update individual employee information (PUT Api/City/ABC/Businesses/X7N/Employees/WWW)
That second and third call, while appearing to be in the right place, use a lot of parameters that are actually unnecessary.
To get employees at a business, the only parameter needed is the key of the business (X7N).
To update an individual employee, the only parameter needed it the key of the employee (WWW)
Nothing in the backend code requires non-key information to look up the business or update the employee. So, instead, the following endpoints appear better:
GET Api/City/ABC/Businesses (returns all Businesses in City ABC)
GET Api/Businesses/X7N (returns business X7N)
GET Api/Businesses/X7N/Employees (returns all employees at business X7N)
PUT Api/Employees/WWW (updates employee WWW)
As you can see, I've created a new root for businesses and employees, even though from a domain perspective they are a sub/sub-sub-collection.
Neither solution appears very clean to me.
The first example asks for unnecessary information, but is structured in a way that appears "natural" to the consumer (individual items from a collection are retrieved via lower leafs)
The second example only asks for necessary information, but isn't structured in a "natural" way - subcollections are accessible via roots
The individual employee root would not work when adding a new employee, as we need to know which business to add the employee to, which means that call would at least have to reside under the Business root, such as POST Api/Businesses/X7N7/Employees, which makes everything even more confusing.
Is there a cleaner, third way that I'm not thinking of?
I don't see how REST adds a constraint that two resources could not have the same value. The resourceType/ID is just an example of the easiest use case rather than the best way to go from a RESTful point of view.
If you read paragraph 5.2.1.1 of Roy Fielding's dissertation carefully, you will notice that Fielding makes the disctinction between a value and a resource. Now a resource should have a unique URI, that's true. But nothing prevents two resources from having the same value:
For example, the "authors' preferred version" of an academic paper is a mapping whose value changes over time, whereas a mapping to "the paper published in the proceedings of conference X" is static. These are two distinct resources, even if they both map to the same value at some point in time. The distinction is necessary so that both resources can be identified and referenced independently. A similar example from software engineering is the separate identification of a version-controlled source code file when referring to the "latest revision", "revision number 1.2.7", or "revision included with the Orange release."
So nothing prevents you from, as you say, changing the root. In your example, a Business is a value not a resource. It is perfectly RESTful to create a resource which is a list of "every business located in a city" (just like Roy's example, "revisions included with the Orange release"), while having a "business which ID is x" resource as well (like "revision number x").
For Employees, I would keep API/Businesses/X7N/Employees as the relation between a business and its employees is a composition relationship, and thus as you say, Employees can and should only be accessed through the Businesses class root. But this is not a REST requirement, and the other alternative is perfectly RESTful as well.
Note that this goes in pair with the application of the HATEAOS principle. In your API, the list of Businesses located in a city could (and perhaps should from a theoretical point of view) be just a list of links to the API/Businesses. But this would mean that the clients would have to do one round-trip to the server for each of the items in the list. This is not efficient and, to stay pragmatic, what I do is embed the representation of the business in the list along with the self link to the URI that would be in this example API/Businesses.
You should not confuse REST with the application of a specific URI naming convention.
HOW the resources are named is entirely secondary. You are trying to use HTTP resource naming conventions - this has nothing to do with REST. Roy Fielding himself states so repeatedly in the documents quoted above by others. REST is not a protocol, it is an architectural style.
In fact, Roy Fielding states in his 2008 blog comment (http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven 6/20/2012):
"A REST API must not define fixed resource names or hierarchies (an obvious coupling of
client and server). Servers must have the freedom to control their own namespace. Instead,
allow servers to instruct clients on how to construct appropriate URIs, such as is done in
HTML forms and URI templates, by defining those instructions within media types and link relations."
So in essence:
The problem you describe is not actually a problem of REST - conceptually, it is a problem of HIERARCHY STRUCTURES versus RELATIONAL STRUCTURES.
While a business is "in" a city and so can be considered to be part of the city "hierarchy" - what about international companies which have offices in 75 cities. Then the city suddenly becomes the junior element in a hierarchy with the business name at the senior level of the structure.
The point is, you can view data from various angles, and depending on the viewpoint you take, it may be simplest to see it as a hierarchy. But the same data can be seen as a hierarchy with different levels. When you are using HTTP type resource names, then you have entered a hierarchy structure defined by HTTP. This is a constraint, yes, but it's not a REST constraint, it's a HTTP constraint.
From that angle, you can chose the solution which fits better to your scenario. If your customer cannot supply the city name when he supplies the company name (he may not know), then it would be better to have the key with only city name. As I said, it's up to you, and REST won't stand in your way ...
More to the point:
The only real REST constraints you have, if you have already decided to use HTTP with GET
PUT and so on, are:
Thou shalt not presumeth any prior ("out of band") knowledge between client and servers. *
Look at your proposal #1 above in that light. You assume that customers know the keys for the cities which are contained in your system? Wrong - that's not restful. So the server has to give the list of cities as a list of choices in some way. So are you going to list every city in the world here?
I guess not, but then you'll have to do some work on how you are planning to do this, which brings us to:
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 ...
I think, reading the mentioned Roy Fielding blog will help you out considerably.
In a RESTful-API URL design should be quite unimportant - or at least a side issue since the discoverability is encoded in the hypertext and not in the URL path. Have a look at the resources linked in the REST tag wiki here on StackOverflow.
But if you want to design human readable URLs for your UC, I would suggest the following:
Use the resource type you are creating/updating/querying as the first part of the URL (after your API prefix). So when somebody sees the URL he immediately knows to which resources this URL points. GET /Api/Employees... is the only only way to receive Employee resources from the API.
Use Unique IDs for each resource independent of the relations they are in. So GET /Api/<CollectionType>/UniqueKey should return a valid resource representation. Nobody should have to worry where the Employee is located. (But the returned Employee should have the links to the Business (and for convenience sake City) he belongs to.) GET /Api/Employees/Z6W returns the Employee with this ID no matter where is is located.
If you want to get a specific resource: Put your query parameter at the end (instead in the hierarchical order described in the question). You can use the URL query string (GET /Api/Employees?City=X7N) or a matrix parameter expression (GET /Api/Employees;City=X7N;Business=A4X,A5Y). This will allow you to easily express a collection of all Employees in a specific City - independent of the Business they are in.
Side node:
In my experience an initial hierarchical domain data model seldom survives additional requirements that come up during a project. In your case: Consider a business located in two Cities. You could create a workaround by modelling it as two separate businesses but what about the employee who works half his time in one place and the other half at the other location? Or even worse: It's only clear for which business he works but it's undefined, in which city?
The third way that I see is to make Businesses and Employees root resources and use query parameters to filter collections:
GET Api/Businesses?city=ABC (returns all Businesses in City ABC)
GET Api/Businesses/X7N (returns business X7N)
GET Api/Employees?businesses=X7N (returns all employees at business X7N)
PUT Api/Employees/WWW (updates employee WWW)
Your both solutions use concept of REST sub-resources which requires that subresource is included in parent resource so:
GET Api/City/ABC/Businesses
in response should also return data provided by:
GET Api/City/ABC/Businesses/X7N
GET Api/City/ABC/Businesses/X7N/Employees
similar for:
GET Api/Businesses/X7N
which should return data provided by:
GET Api/Businesses/X7N/Employees
It will make size of the response huge and time required to generate will increase.
To make REST API clean each resource should have only one bounded URI which fallow below patterns:
GET /resources
GET /resources/{id}
POST /resources
PUT /resources/{id}
If you need to make links between resources use HATEOAS
Go with example 1. I wouldn't worry about unnecessary information from the point of view of the server. A URL should clearly identify a resource in a unique fashion from the point of view of the client. If the client would not know what /Employee/12 means without first knowing that it is actually /Businesses/X7N/Employees/12 then the first URL seems redundant.
The client should be dealing with URLs rather than the individual parameters that make up the URLs, so there is nothing wrong with long URLs. To the client they are just strings. The server should be telling the client the URL to do what it needs to do, not the individual parameters that then require the client to construct the URL.
Having trouble coming up with a good URL path for the case in which the same RESTful resource (model) is associated in two or more different ways with another RESTful resource, e.g.:
Specify a URL path that intuitively represents a request to look up all instances of training sessions associated with a certain trainer, where the TrainingSession model has a trainer_id that is an association to the Employee model.
Specify a URL path that intuitively represents a request to look up all instances of training sessions associated with a certain trainee, where the TrainingSession model has a trainee_id that is also an association to the Employee model.
Including "trainees" or "trainers" in the path of the URL doesn't seem to be right, since they aren't real resources (only TrainingSession and Employee are):
/trainees/1/training_sessions
/trainers/1/training_sessions
But, using "employees" is too ambiguous and could mean either:
/employees/1/training_sessions
What would you suggest for these routes/paths and why?
Actually using trainees and trainers is not wrong at all.
Your trainees and trainers both urls can map to the employee controller function which then find the trainee / trainer data using the id provided. I don't see why you could not do that. It is simply smart url directing.
If you had to store information about trainees and trainers seperately then they need their own model. But if TrainingSession has trainee id and trainer id which maps directly to employee ids and you don't have to store anything else about the trainee and trainer I don't see why the mentioned approach is not usable.
EDIT: The following is a matter of philosophy and therefore largely debatable.
I feel the REST principles is for the API user. So as long as user sees that there is a trainee resource and trainer resource and can manipulate it it is REST. How you implement inside, say using MVC is your choice. A good way would be to use MVC principles but principles are guidelines and no golden rules can be applied to all situations. I think creating virtual resources is just fine and they don't have to map to models / controllers of their own.
I would see training sessions as another resource and you are searching training sessions based on search parameters searchType and employeeId. So a #GET on /trainingsessions?searchby=trainer&employeeId=xyz should give sessions for the trainer/trainingsessions?searchby=trainee&employeeId=xyz should give sessions for the trainee.
Your triplestore contains a lot of nodes, and you have to make accessible this database via a REST interface.
Now, my solution would be that every named (not-anonymous) node is exported as a resource, whose representation is:
all the triples having the node as a subject
all the triples having the node as an object
all the connected anonymous nodes.
I am a little reluctant on point number 2: this would basically give both incoming and outgoing triples.
What is your take on a REST sytle representation of a purely RDF-oriented data store ?
Do you share my point of view or not, and if not, what is your take on it ?
Depends on what the the data is and what the interface users want to do with it. This question is similar to what the SPARQL DESCRIBE query form should return. (It's determined by the implementation.)
For the use cases I've had with RDF data, I'd go with 1 and 3, producing a blank node closure of the resource. Additionally, you could have a separate interface for case 2, returning the incoming arcs of the resource.
One easy way to make an RDF dataset REST traversible is to use URLs for all traversible elements.
When the URL is accessed, for example via HTTP GET, then result shows the connected nodes (connected as properties and/or inverse properties).
More formally the returned representation could be a Concise Bounded Description of the resource.
(disclaimer: this may not correspond exactly to the content of your question, but it corresponds to the title)
I think that about the topic of Rest representation of RDF data is a general problem of inverting the order of concepts. For me the normal would be to have a collection of Rest documents with RDF data and use a RDF database for indexing and making global querys.
In this situation you can organize your resources in the way you prefer.
Also (if you pretend to use the URI of the node as the exported resource) your approach will have subtle problems about what is the meaning of your resources: the Rest resources you propose here are "information resources" and then they cannot be abstract resources. There will be a conflict between information and meta-information.
I published an article here explaining this view in more detail.