Gin Framework – Part 12

Serving Static Files

Code

package main

import "github.com/gin-gonic/gin"

func main() {
	engine := gin.Default()
	// static image
	engine.Static("/img", "./public/img")
	// Static file
	engine.StaticFile("/favicon.ico", "./public/favicon.ico")
	// start the service
	_ = engine.Run(":9090")
}

Directory Structure

Hori Systems – Go Gin Framework – Part 12 – Directory Structure

Request example

# Request images
http://127.0.0.1:9090/img/testing_a.jpg
http://127.0.0.1:9090/img/testing_b.jpg

# Request favicon 
http://127.0.0.1:9090/favicon.ico

Redirect

package main

import (
	"net/http"

	"github.com/gin-gonic/gin"
)

func main() {
	engine := gin.Default()
	// Redirect to external (Google)
	engine.GET("/google", func(context *gin.Context) {
		context.Redirect(http.StatusMovedPermanently, "http://www.google.com")
	})
	// route redirection (first type)
	engine.GET("/route", func(context *gin.Context) {
		context.Request.URL.Path = "/google"
		engine.HandleContext(context)
	})

	// Route redirection (second type)
	engine.GET("/pos", func(context *gin.Context) {
		context.Redirect(http.StatusTemporaryRedirect, "/get")
	})
	engine.GET("/get", func(context *gin.Context) {
		context.JSON(http.StatusOK, gin.H{"msg": "success"})
	})
	// start the service
	_ = engine.Run(":9090")
}

Modify the HTTP configuration

Start HTTP service by default

func main() {
	engine := gin.Default()
	// register route
	engine.GET("/", func(context *gin.Context) {
		// todo
	})
	// start the service
	_ = engine.Run(":9090")
}

Start custom HTTP service

You can use it directly to http.ListenAndServe() start the service, the specific configuration is as follows:

package main

import (
	"net/http"
	"time"

	"github.com/gin-gonic/gin"
)

func main() {
	engine := gin.Default()
	// custom configuration HTTP service
	serverConfig := &http.Server{
		Addr:           ":9090",     // ip and port number
		Handler:        engine,      // The handler to be called, if it is nil, it will call http.DefaultServeMux
		ReadTimeout:    time.Second, // Calculate the time from successfully establishing a connection until the request body (or header) is completely read
		WriteTimeout:   time.Second, // Calculate the time from the end of the request body (or header) read to the end of the response write
		MaxHeaderBytes: 1 << 20,     // The maximum length of the request header, if it is 0, use DefaultMaxHeaderBytes
	}
	// register route
	engine.GET("/test", func(context *gin.Context) {
		context.JSON(200, gin.H{"msg": "success"})
	})
	// Start the service with http.ListenAndServe
	_ = serverConfig.ListenAndServe()
}

Run Multiple Services

package main

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

	"github.com/gin-gonic/gin"
	"golang.org/x/sync/errgroup"
)

// Manage multiple services via sync/errgroup
var (
	g errgroup.Group
)

// Service 1
func serverOne() http.Handler {
	engine := gin.Default()
	engine.GET("/server1", func(context *gin.Context) {
		context.JSON(200, gin.H{"msg": "server1"})
	})
	return engine
}

// Service 2
func serverTwo() http.Handler {
	engine := gin.Default()
	engine.GET("/server2", func(context *gin.Context) {
		context.JSON(200, gin.H{"msg": "server2"})
	})
	return engine
}

func main() {
	// Configuration information of service 1
	s1 := &http.Server{
		Addr:         ":9090",
		Handler:      serverOne(),
		ReadTimeout:  5 * time.Second,
		WriteTimeout: 10 * time.Second,
	}
	// Configuration information of service 2
	s2 := &http.Server{
		Addr:         ":9091",
		Handler:      serverTwo(),
		ReadTimeout:  5 * time.Second,
		WriteTimeout: 10 * time.Second,
	}
	//start service
	g.Go(func() error {
		return s1.ListenAndServe()
	})
	g.Go(func() error {
		return s2.ListenAndServe()
	})
	if err := g.Wait(); err != nil {
		log.Fatal(err)
	}
}
  • Returns
$ go run main.go
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.

[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:	export GIN_MODE=release
 - using code:	gin.SetMode(gin.ReleaseMode)

[GIN-debug] GET    /server1                  --> main.serverOne.func1 (3 handlers)
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.

[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:	export GIN_MODE=release
 - using code:	gin.SetMode(gin.ReleaseMode)

[GIN-debug] GET    /server2                  --> main.serverTwo.func1 (3 handlers)
[GIN] 2021/11/11 - 17:58:17 | 404 |    1.184µs |    127.0.0.1 | GET      "/"
[GIN] 2021/11/11 - 17:58:26 | 200 |   116.28µs |    127.0.0.1 | GET      "/server1"
[GIN] 2021/11/11 - 17:58:33 | 200 |   63.547µs |    127.0.0.1 | GET      "/server2"