How to do it...

The following steps cover the writing and running of your application:

  1. From your Terminal or console application, create a new directory called ~/projects/go-programming-cookbook/chapter8/middlewareand navigate to this directory.
  2. Run the following command:
$ go mod init github.com/PacktPublishing/Go-Programming-Cookbook-Second-Edition/chapter8/middleware

You should see a file called go.mod that contains the following:

module github.com/PacktPublishing/Go-Programming-Cookbook-Second-Edition/chapter8/middleware    
  1. Copy the tests from ~/projects/go-programming-cookbook-original/chapter8/middleware, or use this as an exercise to write some of your own code!
  2. Create a file called middleware.go with the following contents:
        package middleware

import (
"log"
"net/http"
"time"
)

// Middleware is what all middleware functions will return
type Middleware func(http.HandlerFunc) http.HandlerFunc

// ApplyMiddleware will apply all middleware, the last
// arguments will be the
// outer wrap for context passing purposes
func ApplyMiddleware(h http.HandlerFunc, middleware
...Middleware) http.HandlerFunc {
applied := h
for _, m := range middleware {
applied = m(applied)
}
return applied
}

// Logger logs requests, this will use an id passed in via
// SetID()
func Logger(l *log.Logger) Middleware {
return func(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
l.Printf("started request to %s with id %s", r.URL,
GetID(r.Context()))
next(w, r)
l.Printf("completed request to %s with id %s in
%s", r.URL, GetID(r.Context()), time.Since(start))
}
}
}
  1. Create a file called context.go with the following contents:
        package middleware

import (
"context"
"net/http"
"strconv"
)

// ContextID is our type to retrieve our context
// objects
type ContextID int

// ID is the only ID we've defined
const ID ContextID = 0

// SetID updates context with the id then
// increments it
func SetID(start int64) Middleware {
return func(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ctx := context.WithValue(r.Context(), ID,
strconv.FormatInt(start, 10))
start++
r = r.WithContext(ctx)
next(w, r)
}
}
}

// GetID grabs an ID from a context if set
// otherwise it returns an empty string
func GetID(ctx context.Context) string {
if val, ok := ctx.Value(ID).(string); ok {
return val
}
return ""
}
  1. Create a file called handler.go with the following contents:
        package middleware

import (
"net/http"
)

// Handler is very basic
func Handler(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("success"))
}
  1. Create a new directory named example and navigate to it.
  2. Create a file called main.go with the following contents:
        package main

import (
"fmt"
"log"
"net/http"
"os"

"github.com/PacktPublishing/
Go-Programming-Cookbook-Second-Edition/
chapter8/middleware"
)

func main() {
// We apply from bottom up
h := middleware.ApplyMiddleware(
middleware.Handler,
middleware.Logger(log.New(os.Stdout, "", 0)),
middleware.SetID(100),
)
http.HandleFunc("/", h)
fmt.Println("Listening on port :3333")
err := http.ListenAndServe(":3333", nil)
panic(err)
}
  1. Run go run main.go.
  2. You could also run the following commands:
$ go build
$ ./example

You should see the following output:

$ go run main.go
Listening on port :3333
  1. In a separate Terminal, run the following curl command several times:
$ curl http://localhost:3333

You should see the following output:

$ curl http://localhost:3333
success

$ curl http://localhost:3333
success

$ curl http://localhost:3333
success
  1. In the original main.go, you should see the following:
Listening on port :3333
started request to / with id 100
completed request to / with id 100 in 52.284µs
started request to / with id 101
completed request to / with id 101 in 40.273µs
started request to / with id 102
  1. The go.mod file may be updated and the go.sum file should now be present in the top-level recipe directory.
  2. If you copied or wrote your own tests, go up one directory and run go test. Ensure that all tests pass.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.227.114.125