timeout

package module
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: May 28, 2024 License: MIT Imports: 11 Imported by: 34

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())
		}),
		timeout.WithGinCtxCallBack(func(c *gin.Context) {
			fmt.Println("timeout happen, url:", c.Request.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 added in v0.0.6

type CallBackFunc func(*http.Request)

type GinCtxCallBackFunc added in v0.1.8

type GinCtxCallBackFunc func(*gin.Context)

type Option added in v0.0.6

type Option func(*TimeoutWriter)

func WithCallBack added in v0.0.6

func WithCallBack(f CallBackFunc) Option

Optional parameters

func WithDefaultMsg added in v0.0.6

func WithDefaultMsg(resp interface{}) Option

Optional parameters

func WithErrorHttpCode added in v0.0.6

func WithErrorHttpCode(code int) Option

Optional parameters

func WithGinCtxCallBack added in v0.1.8

func WithGinCtxCallBack(f GinCtxCallBackFunc) Option

Optional parameters

func WithTimeout added in v0.0.6

func WithTimeout(d time.Duration) Option

type TimeoutOptions added in v0.0.6

type TimeoutOptions struct {
	CallBack       CallBackFunc
	GinCtxCallBack GinCtxCallBackFunc
	DefaultMsg     interface{}
	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 added in v0.1.2

func (tw *TimeoutWriter) Size() int

func (*TimeoutWriter) Status added in v0.2.0

func (tw *TimeoutWriter) Status() 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