timeout

package module
v1.0.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 18, 2024 License: MIT Imports: 10 Imported by: 0

README

gin-timeout

golang-ci

Timeout Middleware for Gin framework

Thanks

Inspired by golang source code http.TimeoutHandler

Usage

Download and install using go module:

export GO111MODULE=on
go get github.com/vearne/gin-timeout
Notice:
  • If the handler supports to be canceled, you need to pass gin.Context.Request.Context() as parameter.

  • If you want to get the status code of the response in middleware, you should put the middleware before the timeout middleware.

package main

import (
	"net/http"
	"net/http/httptest"
	"time"

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

func main() {
	req, _ := http.NewRequest("GET", "/test", nil)

	engine := gin.New()
	engine.Use(func(c *gin.Context) {
		c.Next()
		println("middleware code: ", c.Writer.Status())
	})

	engine.Use(timeout.Timeout(timeout.WithTimeout(10 * time.Second)))
	
	engine.GET("/test", func(c *gin.Context) {
		c.Status(http.StatusBadRequest)
	})
	rr := httptest.NewRecorder()
	engine.ServeHTTP(rr, req)

	println("response code: ", rr.Code)
}
Example

more example

package main

import (
	"context"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/vearne/gin-timeout"
	"io/ioutil"
	"log"
	"net/http"
	"time"
)

func main() {
	// create new gin without any middleware
	engine := gin.Default()

	defaultMsg := `{"code": -1, "msg":"http: Handler timeout"}`
	// add timeout middleware with 2 second duration
	engine.Use(timeout.Timeout(
		timeout.WithTimeout(2*time.Second),
		timeout.WithErrorHttpCode(http.StatusRequestTimeout), // optional
		timeout.WithDefaultMsg(defaultMsg),                   // optional
		timeout.WithCallBack(func(r *http.Request) {
			fmt.Println("timeout happen, url:", r.URL.String())
		}))) // optional

	// create a handler that will last 1 seconds
	engine.GET("/short", short)

	// create a handler that will last 5 seconds
	engine.GET("/long", long)

	// create a handler that will last 5 seconds but can be canceled.
	engine.GET("/long2", long2)

	// create a handler that will last 20 seconds but can be canceled.
	engine.GET("/long3", long3)

	engine.GET("/boundary", boundary)

	// run the server
	log.Fatal(engine.Run(":8080"))
}

func short(c *gin.Context) {
	time.Sleep(1 * time.Second)
	c.JSON(http.StatusOK, gin.H{"hello": "short"})
}

func long(c *gin.Context) {
	time.Sleep(3 * time.Second)
	c.JSON(http.StatusOK, gin.H{"hello": "long"})
}

func boundary(c *gin.Context) {
	time.Sleep(2 * time.Second)
	c.JSON(http.StatusOK, gin.H{"hello": "boundary"})
}

func long2(c *gin.Context) {
	if doSomething(c.Request.Context()) {
		c.JSON(http.StatusOK, gin.H{"hello": "long2"})
	}
}

func long3(c *gin.Context) {
	// request a slow service
	// see  https://github.com/vearne/gin-timeout/blob/master/example/slow_service.go
	url := "http://localhost:8882/hello"
	// Notice:
	// Please use c.Request.Context(), the handler will be canceled where timeout event happen.
	req, _ := http.NewRequestWithContext(c.Request.Context(), http.MethodGet, url, nil)
	client := http.Client{Timeout: 100 * time.Second}
	resp, err := client.Do(req)
	if err != nil {
		// Where timeout event happen, a error will be received.
		fmt.Println("error1:", err)
		return
	}
	defer resp.Body.Close()
	s, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("error2:", err)
		return
	}
	fmt.Println(s)
}

// A cancelCtx can be canceled.
// When canceled, it also cancels any children that implement canceler.
func doSomething(ctx context.Context) bool {
	select {
	case <-ctx.Done():
		fmt.Println("doSomething is canceled.")
		return false
	case <-time.After(5 * time.Second):
		fmt.Println("doSomething is done.")
		return true
	}
}
Thanks

jetbrains

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Timeout

func Timeout(opts ...Option) gin.HandlerFunc

Types

type CallBackFunc

type CallBackFunc func(*http.Request)

type MsgCallBackFunc

type MsgCallBackFunc func(*http.Request) interface{}

type Option

type Option func(*TimeoutWriter)

func WithCallBack

func WithCallBack(f CallBackFunc) Option

Optional parameters

func WithDefaultMsg

func WithDefaultMsg(resp interface{}) Option

Optional parameters

func WithErrorHttpCode

func WithErrorHttpCode(code int) Option

Optional parameters

func WithMsgCallBack added in v1.0.1

func WithMsgCallBack(f MsgCallBackFunc) Option

WithMsgCallBack Optional parameters

func WithTimeout

func WithTimeout(d time.Duration) Option

type TimeoutOptions

type TimeoutOptions struct {
	CallBack      CallBackFunc
	DefaultMsg    interface{}
	MsgCallBack   MsgCallBackFunc
	Timeout       time.Duration
	ErrorHttpCode int
}

type TimeoutWriter

type TimeoutWriter struct {
	gin.ResponseWriter

	TimeoutOptions // TimeoutOptions in options.go
	// contains filtered or unexported fields
}

func (*TimeoutWriter) Header

func (tw *TimeoutWriter) Header() http.Header

func (*TimeoutWriter) Size

func (tw *TimeoutWriter) Size() int

func (*TimeoutWriter) Write

func (tw *TimeoutWriter) Write(b []byte) (int, error)

func (*TimeoutWriter) WriteHeader

func (tw *TimeoutWriter) WriteHeader(code int)

func (*TimeoutWriter) WriteHeaderNow

func (tw *TimeoutWriter) WriteHeaderNow()

Directories

Path Synopsis
example

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL