Handling HTTP request in Go Echo framework (1)
Tags: go, echo
Published: 2019-04-08 17:31:20

---
title: Handling HTTP request in Go Echo framework (1)
published: true
description: "Retrieve data thru HTTP GET request in Go Echo framework."
tags: [Golang, Echo]
cover_image: https://thepracticaldev.s3.amazonaws.com/i/sudbu1ud34fjfbeiw1ht.png
---

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

---

In the last post, we have discussed about how we could setup nested templates in [Echo][echo] framework.

- [Setup nested HTML template in Go Echo web framework](https://blog.boatswain.io/post/setup-nested-html-template-in-go-echo-web-framework/)

In the following sections, we will move on and see how we could make HTTP request in [Echo][echo] server and render the result back to the client. Let's start with the [example](https://gitlab.com/ykyuen/golang-echo-template-example) we did in the last article.

## Setup an API endpoint

Firstly, create a new API endpoint and return a simple JSON which is later called by the [Echo][echo] server itself.

### Create new endpoint in the api folder

Unlike a hardcoded JSON request, our new API endpoint takes the request input from JSON data, form data or query parameters as defined in the *model/example_request.go* and then return it the the client.

*model/example_request.go*

```go
package model

type ExampleRequest struct {
  FirstName string `json:"first_name" form:"first_name" query:"first_name"`
  LastName  string `json:"last_name" form:"last_name" query:"last_name"`
}
```

*api/get_full_name.go*

```go
package api

import (
  "fmt"
  "net/http"

  "github.com/labstack/echo"

  "gitlab.com/ykyuen/golang-echo-template-example/model"
)

func GetFullName(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

  return c.JSONBlob(
    http.StatusOK,
    []byte(
      fmt.Sprintf(`{
        "first_name": %q,
        "last_name": %q,
        "msg": "Hello %s"
      }`, exampleRequest.FirstName, exampleRequest.LastName, greeting),
    ),
  )
}
```

### Setup the route for the above API endpoint

Add our new API endpoint 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)

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

### Test the new API endpoint

Run the [Echo][echo] server as see if it works.

![It works!](https://thepracticaldev.s3.amazonaws.com/i/ol8hlhtvhniowb38uuee.jpg)

This new endpoint could serve the browser client directly or it could be called by the [Echo][echo] server itself.

## Call the API from Echo server

### Create the response struct type

Similar to the *model/example_request.go*, we need to define another struct type for the HTTP response.

*model/example_response.go*

```go
package model

type ExampleResponse struct {
  FirstName string `json:"first_name"`
  LastName  string `json:"last_name"`
  Msg       string `json:"msg"`
}
```

### Show the new greeting message in the about page

Let's modify the about page handler such that it will show the greeting message.

*handler/about_handler.go*

```go
package handler

import (
  "encoding/json"
  "io/ioutil"
  "net/http"

  "github.com/labstack/echo"

  "gitlab.com/ykyuen/golang-echo-template-example/model"
)

func AboutHandler(c echo.Context) error {

  tr := &http.Transport{}
  client := &http.Client{Transport: tr}

  // Call the api
  resp, err := client.Get(
    "http://localhost:1323/api/get-full-name?first_name=Kit&last_name=Yuen",
  )

  if err != nil {
    return err
  }

  defer resp.Body.Close()
  body, err := ioutil.ReadAll(resp.Body)

  // Unmarshal the response into a ExampleResponse struct
  var exampleResponse model.ExampleResponse
  if err = json.Unmarshal(body, &exampleResponse); err != nil {
    return err
  }

  // Please note the the second parameter "about.html" is the template name and should
  // be equal to one of the keys in the TemplateRegistry array defined in main.go
  return c.Render(http.StatusOK, "about.html", map[string]interface{}{
    "name": "About",
    "msg": exampleResponse.Msg,
  })
}
```

### Test the about page

Start the [Echo][echo] server and browse the about page. We could see the new greeting message.

![The greeting msg is now composed of the result of the API call.](https://thepracticaldev.s3.amazonaws.com/i/dnhkmwc8q949at6dfsom.jpg)

### The project structure

After making the above changes, the project structure should look like this. _(The project is renamed to **handling-http-request-in-go-echo-example-1**, 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-1/
  ├── api/                     # folder of api endpoints
  │   ├── get_full_name.go     # api for get 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 article shows you how to setup a simple API endpoint in [Echo][echo] framework. Since [Go][golang] is a **strongly typed** language, we have to convert the JSON into well defined struct type before for we could manipulate its content. For example:

- Binding the GET request input to **exampleRequest** in *api/get_full_name.go*.
- Unmarshal the GET response into **exampleResponse** in *handler/about_handler.go*.

To invoke the API call, we could simply make use of the [Go][golang] standard [net/http][net/http] library.

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





[golang]: https://golang.org/
[echo]: https://echo.labstack.com/
[net/http]: https://golang.org/pkg/net/http/