袁英傑
袁英傑

軟件工程師,Boatswain 的創辦人 https://boatswain.io/。

Manipulating HTTP requests in the Go Echo framework(1)


Update @ 2019-12-13: As of Go 1.13, use the built-in Go Module to manage suites.


In the previous article, we discussed how to set up nested boilerplates in the Echo framework.

In the next sections, we'll move on to how to make an HTTP request in the Echo server and render the result on the client. Let's start with the example from the previous article.

Set up API endpoints

First, create a new API endpoint to return a simple JSON that will later be called by the Echo server itself.

Create a new endpoint in the api folder

Unlike hard-coded JSON requests, the request structure of this new API endpoint will be defined in the file model/example_request.go , and its content can be provided as a JSON object, HTML table, or URL parameters when implemented, and then return it to the client.

model/example_request.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

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),
    ),
  )
}

Set up routes for the above API endpoints

Add our new API endpoint route in main.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 server to test it out.

This new endpoint can serve browsers or other clients directly, or it can be called by the Echo server itself.

Call API from Echo server

Create Response Structure Types

Similar to model/example_request.go , we need to define an HTTP response structure type.

model/example_response.go

 package model

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

Display response information on the about page

Modify the code in about handler to display information about the HTTP response.

handler/about_handler.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

Starting the Echo server and browsing the about page, we can see the new greeting.

The greeting now consists of the response you get after calling the API.

Project structure

After making the above changes, the project structure should look like the image below. (The project is renamed to handling-http-request-in-go-echo-example-1 . If you want to change the project name, make sure to set the import statement in the Golang code correctly.)

 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

Summarize

This article describes how to set up a simple API endpoint in the Echo framework. Since Go is a strongly typed language, we must type the structure of the JSON request and response before we can manipulate its content. E.g:

  • Bind a GET request to exampleRequest at api/ get_full_name.go.
  • Unmarshal the GET response into exampleResponse at handler/ about_handler.go .

To call the API, we can directly use the built-in net/http standard library of Go .

The full example can be found on this gitlab.com repository .

Original URL

CC BY-NC-ND 2.0

Like my work?
Don't forget to support or like, so I know you are with me..

Loading...

Comment