Lesson 5
Handling PUT and DELETE Requests with Gin
Introduction to Handling PUT and DELETE Requests with Gin

Welcome to this lesson, where we will focus on handling PUT and DELETE requests to update and delete resources in a web application using the Gin framework. In previous lessons, you've become familiar with setting up a Gin application and handling GET and POST requests. As a quick reminder, Gin is a popular framework in the Go language used to build web applications and APIs efficiently.

Understanding PUT and DELETE HTTP Methods

Before we dive into the examples, let's briefly go over what PUT and DELETE HTTP methods entail. As part of the fundamentals of building RESTful APIs, these methods play a critical role:

  • PUT: This method is used to update existing resources. For instance, if your to-do app has a task with certain attributes, using a PUT request, you can change those attributes to different values.

  • DELETE: This method is used to remove resources. When a task is completed and no longer needed in your to-do list, a DELETE request will remove it.

Understanding these methods is crucial as they allow you to modify the state of resources within your web application.

Implementing PUT Request in Gin

To handle a PUT request that updates a todo item by its ID, you'll need to understand what kind of data is being sent. Here's an example JSON body that you might send with a PUT request to update a todo item:

JSON
1{ 2 "title": "Learn HTTP Methods", 3 "completed": false 4}

This JSON object represents a todo item with the title attribute and a completed status. These are the fields that can be updated.

Let’s look at the code to implement this:

router.go:

Go
1package router 2 3import ( 4 "github.com/gin-gonic/gin" 5 6 "codesignal.com/todoapp/internal/controllers" 7) 8 9func SetupRouter() *gin.Engine { 10 r := gin.Default() 11 r.PUT("/api/todos/:id", controllers.UpdateTodo) 12 return r 13}

controllers.go:

Go
1package controllers 2 3import ( 4 "net/http" 5 "strconv" 6 7 "github.com/gin-gonic/gin" 8 9 "codesignal.com/todoapp/internal/models" 10 "codesignal.com/todoapp/internal/services" 11) 12 13var todos []models.Todo 14 15func UpdateTodo(c *gin.Context) { 16 id, err := strconv.Atoi(c.Param("id")) 17 if err != nil { 18 c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID"}) 19 return 20 } 21 var updateData models.Todo 22 if err := c.ShouldBindJSON(&updateData); err != nil { 23 c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid JSON"}) 24 return 25 } 26 if updatedTodo, err := services.UpdateTodoService(id, updateData, todos); err != nil { 27 c.JSON(http.StatusNotFound, gin.H{"error": "Todo not found"}) 28 } else { 29 c.JSON(http.StatusOK, updatedTodo) 30 } 31}

services.go:

Go
1package services 2 3import ( 4 "errors" 5 6 "codesignal.com/todoapp/internal/models" 7) 8 9func UpdateTodoService(id int, updateData models.Todo, todos []models.Todo) (*models.Todo, error) { 10 for i, todo := range todos { 11 if todo.ID == id { 12 todos[i].Title = updateData.Title 13 todos[i].Completed = updateData.Completed 14 return &todos[i], nil 15 } 16 } 17 return nil, errors.New("Todo not found") 18}
  • Parsing the ID: The path parameter :id is extracted from the URL and converted to an integer. We handle any errors that might arise if the ID provided is invalid.
  • Binding JSON Data: The c.ShouldBindJSON method is used to bind the incoming JSON payload to the updateData variable, which is of type Todo. If this binding fails, due to invalid JSON format for instance, a BadRequest response is returned.
  • Router Setup and Handler Function: We define the PUT route in the router setup. The route is connected to the UpdateTodo handler function, which handles the logic of managing HTTP status codes and binding JSON data.
  • Business Logic and Updating the Resource: The UpdateTodoService function in the business logic package is responsible for the actual updating of the todo item. It loops through the todos list to find the matching Todo by ID and updates the Title and Completed fields.
  • Response Handling: If the todo is successfully updated, the new data is sent back with a StatusOK response. If no matching todo is found, a NotFound response is returned.
Implementing DELETE Request in Gin

Now, we'll look at implementing a DELETE request to remove a todo item using its ID:

router.go:

Go
1package router 2 3import ( 4 "github.com/gin-gonic/gin" 5 6 "codesignal.com/todoapp/internal/controllers" 7) 8 9func SetupRouter() *gin.Engine { 10 r := gin.Default() 11 r.DELETE("/api/todos/:id", controllers.DeleteTodo) 12 return r 13}

controllers.go:

Go
1package controllers 2 3import ( 4 "net/http" 5 "strconv" 6 7 "github.com/gin-gonic/gin" 8 9 "codesignal.com/todoapp/internal/models" 10 "codesignal.com/todoapp/internal/services" 11) 12 13var todos []models.Todo 14 15func DeleteTodo(c *gin.Context) { 16 id, err := strconv.Atoi(c.Param("id")) 17 if err != nil { 18 c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID"}) 19 return 20 } 21 if deletedTodo, err := services.DeleteTodoService(id, todos); err != nil { 22 c.JSON(http.StatusNotFound, gin.H{"error": "Todo not found"}) 23 } else { 24 c.JSON(http.StatusOK, deletedTodo) 25 } 26}

services.go:

Go
1package services 2 3import ( 4 "errors" 5 6 "codesignal.com/todoapp/internal/models" 7) 8 9func DeleteTodoService(id int, todos []models.Todo) (*models.Todo, error) { 10 for i, todo := range todos { 11 if todo.ID == id { 12 deletedTodo := todos[i] 13 todos = append(todos[:i], todos[i+1:]...) 14 return &deletedTodo, nil 15 } 16 } 17 return nil, errors.New("Todo not found") 18}
  • Extracting and Validating the ID: Similar to PUT, the ID is extracted from the path and validated. Any errors in conversion result in a BadRequest response.
  • Router Setup and Handler Function: The DELETE route is defined in the router setup and linked to the DeleteTodo handler function. This function manages the removal process and returns appropriate HTTP status codes.
  • Finding and Removing the Resource: The DeleteTodoService function in the business logic package iterates through the todos list to find the todo with the matching ID and removes it from the slice using optimized slice operations.
  • Response Management: A successful deletion results in a StatusOK response with the removed todo. If the todo is not found, a NotFound response is provided.
Summary and Practice Preparation

In this lesson, you learned how to handle PUT and DELETE requests with Gin. We explored how these HTTP methods work within RESTful APIs and walked through implementing them in code with practical examples. Understanding how to update and remove resources is fundamental as you continue to build dynamic web applications.

Get ready to apply what you've learned through upcoming practice exercises that will reinforce your understanding by implementing these techniques on your own. You are making excellent progress — keep experimenting and practicing to deepen your knowledge and skills further!

Enjoy this lesson? Now it's time to practice with Cosmo!
Practice is how you turn knowledge into actual skills.