Handling HTTP request in Go Echo framework (2)
Tags: go, echo
Published: 2019-04-18 09:24:54

---
title: "Handling HTTP request in Go Echo framework (2)"
published: true
description: "An example demonstrating HTTP POST request in Go Echo framework."
tags: [Golang, Echo]
cover_image: https://thepracticaldev.s3.amazonaws.com/i/wwp648j5u5rqp7majdrc.png
---

_Originally posted on [Boatswain Blog](https://blog.boatswain.io/post/handling-http-request-in-go-echo-framework-2/)._

---

This is the second post about handling HTTP request in [Echo][echo] framework and we will continue to work on the example we made previously.

- [Handling HTTP request in Go Echo framework (1)](https://blog.boatswain.io/post/handling-http-request-in-go-echo-framework-1/)

This time we will create a simple HTML form and submit it as a POST request.

## Create a POST request endpoint

Checkout this [repo](https://gitlab.com/ykyuen/handling-http-request-in-go-echo-example-1) and create the *api/post_full_name.go* to handle the POST request. This new file is almost the same as *api/get_full_name.go* except the JSON is prettified before returning to the client.

`api/post_full_name.go`

```go
package api

import (
  "bytes"
  "encoding/json"
  "fmt"
  "net/http"

  "github.com/labstack/echo"

  "gitlab.com/ykyuen/handling-http-request-in-go-echo-example-1/model"
)

func PostFullName(c echo.Context) error {
  // Bind the input data to ExampleRequest
  exampleRequest := new(model.ExampleRequest)
  if err := c.Bind(exampleRequest); err != nil {
    return err
  }

  // Manipulate the input data
  greeting := exampleRequest.FirstName + " " + exampleRequest.LastName

  // Pretty print the json []byte
  var resp bytes.Buffer
  var b = []byte(
    fmt.Sprintf(`{
      "first_name": %q,
      "last_name": %q,
      "msg": "Hello %s"
    }`, exampleRequest.FirstName, exampleRequest.LastName, greeting),
  )
  err := json.Indent(&resp, b, "", "  ")
  if err != nil {
    return err
  }

  // Return the json to the client
  return c.JSONBlob(
    http.StatusOK,
    []byte(
      fmt.Sprintf("%s", resp.Bytes()),
    ),
  )
}
```

Add the new route in *main.go*.

```go
...
func main() {
  // Echo instance
  e := echo.New()

  // Instantiate a template registry with an array of template set
  // Ref: https://gist.github.com/rand99/808e6e9702c00ce64803d94abff65678
  templates := make(map[string]*template.Template)
  templates["home.html"] = template.Must(template.ParseFiles("view/home.html", "view/base.html"))
  templates["about.html"] = template.Must(template.ParseFiles("view/about.html", "view/base.html"))
  e.Renderer = &TemplateRegistry{
    templates: templates,
  }

  // Route => handler
  e.GET("/", handler.HomeHandler)
  e.GET("/about", handler.AboutHandler)

  // Route => api
  e.GET("/api/get-full-name", api.GetFullName)
  e.POST("/api/post-full-name", api.PostFullName)

  // Start the Echo server
  e.Logger.Fatal(e.Start(":1323"))
}
```

### Test the new endpoint using curl

Run the [Echo][echo] server as send a POST request using **curl**.

```bash
curl http://localhost:1323/api/post-full-name -H "Content-Type: application/json" -d '{ "first_name": "Kit", "last_name": "Yuen"  }'
```

Here is the example result.

![A JSON is return based on our POST request payload.](https://thepracticaldev.s3.amazonaws.com/i/j1xx9is5w6hmlswwxo66.jpg)

## Add an HTML form

The POST request endpoint is ready and now we could add an HTML form and complete the whole setup. Let's add the form in the about page.

`view/about.html`

```html
{{define "title"}}
  Boatswain Blog | {{index . "name"}}
{{end}}

{{define "body"}}
  <h1>{{index . "msg"}}</h1>
  <h2>This is the about page.</h2>

  <!-- HTML form -->
  <form id="post-full-name-form">
    <input type="text" id="first-name" placeholder="First Name">
    <input type="text" id="last-name" placeholder="Last Name">
    <button type="button" id="submit-btn">Submit</button>
  </form>

  <!-- Print the response after the jQuery ajax request -->
  <pre id="form-result"></pre>

  <script type="text/javascript">
    // Send a ajax request when the submit button is clicked
    $("#submit-btn").on("click", function(){
      var firstName = $("#first-name").val();
      var lastName = $("#last-name").val();

      $.ajax({
        type: "POST",
        url: "/api/post-full-name",
        data: JSON.stringify({
          first_name: firstName,
          last_name: lastName
        }),
        processData: false,
        contentType: "application/json",
        dataType: "json"
      }).done(
        function(data){
          $("#form-result").text(JSON.stringify(data, null, 2));
        }
      ).fail(
        function(data){
          $("#form-result").text("POST request failed!");
        }
      )
    });
  </script>
{{end}}
```

As the form submission required **jQuery**, let's include it in the *view/base.html*.

`view/base.html`

```html
{{define "base.html"}}
  <!DOCTYPE html>
  <html>
    <head>
      <title>{{template "title" .}}</title>
      <!-- jQuery -->
      <script
        src="https://code.jquery.com/jquery-3.3.1.min.js"
        integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
        crossorigin="anonymous"></script>
    </head>
    <body>
      {{template "body" .}}
    </body>
  </html>
{{end}}
```

### Test the HTML form in the about page

Start the [Echo][echo] server and browse the about page. Fill in the first and last name and then click the submit button. It should show the response JSON as follow.

![Click the submit button and get the response.](https://thepracticaldev.s3.amazonaws.com/i/8xxkjzs37c6t6hak7ijp.jpg)

### The project structure

Here is our new project structure. _(The project is renamed to **handling-http-request-in-go-echo-example-2**, make sure you set the **import** statement in the [Golang][golang] source files correctly if you want to change the project name.)_

```bash
handling-http-request-in-go-echo-example-2/
  ├── api/                     # folder of api endpoints
  │   ├── get_full_name.go     # api for get full name
  │   ├── post_full_name.go    # api for post full name
  ├── handler/                 # folder of request handlers
  │   ├── home_handler.go      # handler for home page
  │   └── about_handler.go     # handler for about page
  ├── model/                   # folder of custom struct types
  │   ├── example_request.go   # struct type of get_full_name request
  │   └── example_response.go  # hstruct type of get_full_name response
  ├── vendor/                  # dependencies managed by dep
  │   ├── github.com/*
  │   └── golang.org/*
  ├── view/                    # folder of html templates
  │   ├── base.html            # base layout template
  │   ├── home.html            # home page template
  │   └── about.html           # about page template
  ├── Gopkg.lock               # dep config file
  ├── Gopkg.toml               # dep config file
  └── main.go                  # programme entrypoint
```

## Summary

This is the second episode of [Handling HTTP request in Go Echo framework (1)](https://blog.boatswain.io/post/handling-http-request-in-go-echo-framework-1/) and we have added the following:

- Setup a POST request endpoint in the [Echo][echo] framework.
- Prettify the JSON byte array
- Add an HTML form and bind it to the new POST request using AJAX in jQuery/javascript.

The complete example could be found on [gitlab.com](https://gitlab.com/ykyuen/handling-http-request-in-go-echo-example-2).





[golang]: https://golang.org/
[echo]: https://echo.labstack.com/