Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly structure REST-API endpoints

im quite new with REST-API.

i want to have something like this

POST http://localhost/posts/ <--- PostsController.java
GET http://localhost/posts/{id} <--- PostsController.java
POST http://localhost/posts/{id}/comments <--- CommentsController.java
GET http://localhost/posts/{id}/comments <--- CommentsController.java
GET http://localhost/posts/{id}/comments/{id} <--- CommentsController.java

Where the following controllers handle /posts and another controller handler /comments

PostsController.java

@RestController
@RequestMapping("/posts")
public class PostsController {
   // something
}

CommentsController.java

@RestController
@RequestMapping("/comments")
public class CommentsController {
 //do something
}

How do i maintain the above url whilst having different controllers to handle it?

like image 987
lemoncodes Avatar asked Jul 28 '19 03:07

lemoncodes


People also ask

What is the format of REST API endpoint URL?

An Endpoint URL. An application implementing a RESTful API will define one or more URL endpoints with a domain, port, path, and/or querystring — for example, https://mydomain/user/123?format=json .

How should rest endpoints be named?

In general, URIs should be named with nouns that specify the contents of the resource, rather than adding a verb for the function that is being performed. For example, you should use https://api.example.com/users instead of https://api.example.com/getUsers.

What is the standard format for a REST API?

The usual format used while sending resources is JSON REST API or XML.


2 Answers

Here is the skeleton for both the controllers with endpoints, But still you can also have all these endpoints in one controller or different, some people differentiate them based on methods, some based on paths, so i believe this is completely developer experience how to design this

PostsController.java

@RestController
@RequestMapping("/posts")
public class PostsController {

@PostMapping("/")
public String createPosts() {

    return "createPosts";

}

@GetMapping("/{id}")
public String getPosts(@PathVariable(name = "id") String id) {
    return "getPosts......" + id;
   }

}

CommentsController.java

@RestController
@RequestMapping("/posts/{id}/comments")
public class CommentsController {

@PostMapping
public String createComment(@PathVariable(name = "id") String id) {
    return "createComment..." + id;
}

@GetMapping
public String getComment(@PathVariable(name = "id") String id) {
    return "getComment..." + id;
}

@GetMapping("/{id1@Path}")
public String getCommentById(@PathVariable(name = "id") String id, @PathVariable(name = "id1") String id1) {
    return "getComment..." + id + "...." + id1;
     }

 }
like image 57
Deadpool Avatar answered Sep 21 '22 14:09

Deadpool


I'll share my expreience here. When I work with Rest controllers, I always try to understand what is the "core" entity - a notion we deal with and what are just criterias for queries. Usually the "core" entity appears right after the context path.

Note that this doesn't really depend on an actual implementation at the level of database.

So it looks like all the cases are actually about the "post" entity that's why you've put it in the first place (in the case of comments by post, you didn't opt for something like this http://localhost/comments?post=123 and that's ok, it just means that post is your "main" entity to serve.

In this case I think all the operations can be done in PostsController.

Now an important side-note about controllers in Spring / SpringBoot. People tend to put business logic in these controllers and I believe its a mistake. Controllers should not contain any real logic, maybe some light input transformations / validations but that's it. Leave a real work to "Services" not to controllers, keep controllers to be an entry point for your backend. Now why I'm stating this? Because controllers, if written in this way are really small classes, so you won't get a one "giant" class that handles all, which, I believe, might be an argument for separation to different controllers.

Ok, so what is comments in this case? It depends on how you think about it, but as you wrote in end-points list, is a property of post (something that belongs to the post/ always associated with the post), so its a "Criteria of search": give me a post with comments, give me only a post without comments, give me a post that has comments only from today and yesterday, the point is that you always query for "post", not for comments.

From the purely technical standpoint, the @RequestMapping in spring boot when put on controller class says that only /post can be queried by this controller. You can also set different values on @GetMapping/@PostMapping annotations but that's it. If should be flexible enough to design the level of rest controllers.

like image 41
Mark Bramnik Avatar answered Sep 18 '22 14:09

Mark Bramnik