Good Practices for URI in Restful API

Asked

Viewed 2,295 times

10

I’m having doubts about the Uris of some of the api features I’m developing. I have the features projects and activities in connection with 1-N, that is, a project has several activities and an activity belongs to a project.

What is the correct form or best form in relation to REST conventions? I would like some examples for requests GET, POST, PUT and DELETE for these resources.

EDIT: I rephrased the question.

2 answers

7


If the project has activities, here is the correct way to represent, differentiating the PUT of PATCH. As I understand there will be the appeal /projetos/ and only the /atividades/ for GET, I will organize possible endpoints by HTTP methods.

GET

  • Search all the projects: GET /projetos/
  • Fetch project number 1: GET /projetos/1
  • Browse all project activities 1: GET /projetos/1/atividades
  • Find Project 1 Activity 1: GET /projetos/1/atividades/1, but an option is also just to create a /atividades/1.
  • Search for activity 1: GET /atividades/1
  • Search all activities: GET /atividades/

POST

  • Create project number 1: POST /projetos/, passing on the request body the project information
  • Create an activity in project number 1: POST /projetos/1/atividades, passing on the request body the activity information

You might as well have one POST /atividades/1, passing the project number on the body. This decision will depend on how you want to represent the available resources. This "break" can be done when your endpoint starts to get too long or believes it will get better organized. If you are going to break, the ideal is to maintain consistency and also break the other HTTP methods of the resource.

PUT

Used to replace a resource whole existing on the other.

  • Replace whole the contents of draft number 1: PUT /projetos/1, passing on the request body all new project information
  • Replace all a number 1 activity in project number 1: PUT /projetos/1/atividades/1, passing on the request body the new activity information

PATCH

Used to change only one or some resource-specific information.

  • Update any project information from number 1: PATCH /projetos/1, passing on the request body only the project information you would like to update
  • Update any information from a number 1 activity in the number 1 project: PATCH /projetos/1/atividades/1, passing on the request body only the activity information

DELETE

  • Remove project number 1: DELETE /projetos/1
  • Remove a number 1 activity in project number 1: DELETE /projetos/1/atividades/1.

The DELETE can also be used when the sense is a logical exclusion of the resource, because sometimes the staff only associates this method to the DELETE database, which makes no sense.

Also remember to return HTTP codes that are consistent. Example: 201 for creating a via resource POST, 200 or 204 in PUT and DELETE, 404 for when not finding resource, etc.

  • 1

    "Search activity 1 of project 1: GET /projects/1/activities" - Missing activity number: "GET /projects/1/activities/1"

  • So you really have to use this hierarchy. And if I wanted to pursue all the activities independently of the project I could use GET /atividades or GET /projetos/atividades? And when I want to display a single activity attribute, for example on a project screen I need to display only the activity name, I should use another method, right? Since GET /atividades or GET /projetos/atividades I would get back all of them. Thank you.

  • 1

    @Fernandozabin For your first question, it would be GET /atividades/. For the second question, if you have an activity 1 and want to get information from it, I recommend using /atividades/1 or, if you have the project already and want to take from it, it may also be /projetos/1/atividades/1, but I recommend the /atividades/1 even.

  • @Fernandozabin, I edited my answer to be clearer

  • 1

    @Dherik, it’s very clear. Another question, I have a table where I display all the activities and in a column of this table I display the code of the project to which it belongs. Then I would use GET /atividades, but if project had 20 attributes (keys) and I only need the code, I would create another http or user method GET /atividades even and would bring all the information? I ask this thinking about performance or to avoid bringing too much information. Abusing a little more, how would a method to bring activity by name and date? Thank you very much for the answer, It was excellent.

  • 1

    @Fernandozabin, I wouldn’t worry about performance right at the beginning, the REST is very light. If this really if necessary, I don’t know anything in REST that tells you how to do it. A solution you could implement is to do something like /atividades?fields=id,nome. Thus the GET /atividades/ return the default (all) information and when pass the fields it would return only the listed fields. To bring by name and date, you would use GET /atividades?nome=Joao&data=2016-10-26T13:43:10Z , date in ISO 8601 format preferably (and UTC, preferably also).

Show 1 more comment

4

I could use the following approach:

get /projetos # Lista de projetos    
post /projetos # Criar um projeto

get /projetos/1 # Buscar o projeto com id 1
put /projetos/1 # Atualizar o projeto com id 1
delete /projetos/1 # Deletar o projeto com id 1

get /atividades # Todas as atividades
post /atividades # Criar nova atividade

get /atividades/1 # Atividade com id 1
put /atividades/1 # Atualizar atividade com id 1
delete /atividades/1 # Deletar atividade com id 1

get /projetos/1/atividades # Lista de atividades do projeto com id 1

Remembering RFC 5789, the put method would be to replace a resource. Use the patch to modify it. https://stackoverflow.com/questions/24241893/rest-api-patch-or-put

You can check these questions about URI design

https://stackoverflow.com/questions/13038943/restful-api-uri-design

https://stackoverflow.com/questions/7833548/hierarchical-restful-url-design

  • 1

    I got it, I was doing it that way, but I saw some examples that got me confused, I saw something like GET /projetos/1/atividades // Criar nova atividade. So it gets easier to understand. Thanks, Matheus. Ps: had forgotten about the patch, thanks!

  • Correcting my comment: POST in place of GET.

  • 1

    @Fernandozabin, you almost got it right the first time. If you want to create a new activity for a project, you should use POST (and not GET) to /projetos/1/atividades, because the activity is of the project, right? Having this concept in mind is very important in REST. See my answer.

  • 1

    If the POST was done in /projects/1/activities, then it would have to follow as @Fernandozabin’s response, representing the hierarchy in the URI, in this case the URI can end very long. Imagine that now each activity has an item attribute with its properties, to follow the default would be /projects/1/activities/1/items. And if a new item attribute appears?

  • @Matheussilva, I’d stay that way anyway. If you don’t, you’ll need to pass, in your example, the activity id inside the POST body in /items/, which can get a little confusing later. But if there is a case of having too many long Urls, it is a good alternative to your.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.