gear

package module
v1.9.2 Latest Latest
Warning

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

Go to latest
Published: Nov 24, 2017 License: MIT Imports: 29 Imported by: 0

README

Gear Build Status Coverage Status License GoDoc

A lightweight, composable and high performance web service framework for Go.

Features

  • Effective and flexible middlewares flow control, create anything by middleware
  • Powerful and smart HTTP error handling
  • Trie base gear.Router, as faster as HttpRouter, support regexp parameters and group routes
  • Integrated timeout context.Context
  • Integrated response content compress
  • Integrated structured logging middleware
  • Integrated request body parser
  • Integrated signed cookies
  • Integrated JSON, JSONP, XML and HTML renderer
  • Integrated CORS, Secure, Favicon and Static middlewares
  • More useful methods on gear.Context to manipulate HTTP Request/Response
  • Completely HTTP/2.0 supported

Documentation

Go-Documentation

Import

// package gear
import "github.com/teambition/gear"

Design

  1. Server 底层基于原生 net/http 而不是 fasthttp
  2. 通过 gear.Middleware 中间件模式扩展功能模块
  3. 中间件的单向顺序流程控制和级联流程控制
  4. 功能强大,完美集成 context.Context 的 gear.Context
  5. 集中、智能、可自定义的错误和异常处理
  6. After Hook 和 End Hook 的后置处理
  7. Any interface 无限的 gear.Context 状态扩展能力
  8. 请求数据的解析和验证

FAQ

  1. 如何从源码自动生成 Swagger v2 的文档?
  2. Go 语言完整的应用项目结构最佳实践是怎样的?

Demo

Hello

https://github.com/teambition/gear/tree/master/example/hello

  app := gear.New()

  // Add logging middleware
  app.UseHandler(logging.Default(true))

  // Add router middleware
  router := gear.NewRouter()

  // try: http://127.0.0.1:3000/hello
  router.Get("/hello", func(ctx *gear.Context) error {
    return ctx.HTML(200, "<h1>Hello, Gear!</h1>")
  })

  // try: http://127.0.0.1:3000/test?query=hello
  router.Otherwise(func(ctx *gear.Context) error {
    return ctx.JSON(200, map[string]interface{}{
      "Host":    ctx.Host,
      "Method":  ctx.Method,
      "Path":    ctx.Path,
      "URL":     ctx.Req.URL.String(),
      "Headers": ctx.Req.Header,
    })
  })
  app.UseHandler(router)
  app.Error(app.Listen(":3000"))

HTTP2 with Push

https://github.com/teambition/gear/tree/master/example/http2

package main

import (
  "net/http"

  "github.com/teambition/gear"
  "github.com/teambition/gear/logging"
  "github.com/teambition/gear/middleware/favicon"
)

// go run example/http2/app.go
// Visit: https://127.0.0.1:3000/
func main() {
  const htmlBody = `
<!DOCTYPE html>
<html>
  <head>
    <link href="/hello.css" rel="stylesheet" type="text/css">
  </head>
  <body>
    <h1>Hello, Gear!</h1>
  </body>
</html>`

  const pushBody = `
h1 {
  color: red;
}
`

  app := gear.New()

  app.UseHandler(logging.Default(true))
  app.Use(favicon.New("./testdata/favicon.ico"))

  router := gear.NewRouter()
  router.Get("/", func(ctx *gear.Context) error {
    ctx.Res.Push("/hello.css", &http.PushOptions{Method: "GET"})
    return ctx.HTML(200, htmlBody)
  })
  router.Get("/hello.css", func(ctx *gear.Context) error {
    ctx.Type("text/css")
    return ctx.End(200, []byte(pushBody))
  })
  app.UseHandler(router)
  app.Error(app.ListenTLS(":3000", "./testdata/out/test.crt", "./testdata/out/test.key"))
}

A CMD tool: static server

https://github.com/teambition/gear/tree/master/example/staticgo

Install it with go:

go install github.com/teambition/gear/example/staticgo

It is a useful CMD tool that serve your local files as web server (support TLS). You can build osx, linux, windows version with make build.

package main

import (
  "flag"

  "github.com/teambition/gear"
  "github.com/teambition/gear/logging"
  "github.com/teambition/gear/middleware/cors"
  "github.com/teambition/gear/middleware/static"
)

var (
  address  = flag.String("addr", "127.0.0.1:3000", `address to listen on.`)
  path     = flag.String("path", "./", `static files path to serve.`)
  certFile = flag.String("certFile", "", `certFile path, used to create TLS static server.`)
  keyFile  = flag.String("keyFile", "", `keyFile path, used to create TLS static server.`)
)

func main() {
  flag.Parse()
  app := gear.New()

  app.UseHandler(logging.Default(true))
  app.Use(cors.New())
  app.Use(static.New(static.Options{Root: *path}))

  logging.Println("staticgo v1.1.0, created by https://github.com/teambition/gear")
  logging.Printf("listen: %s, serve: %s\n", *address, *path)

  if *certFile != "" && *keyFile != "" {
    app.Error(app.ListenTLS(*address, *certFile, *keyFile))
  } else {
    app.Error(app.Listen(*address))
  }
}

HTTP2 & gRPC

https://github.com/teambition/gear/tree/master/example/grpc_server

https://github.com/teambition/gear/tree/master/example/grpc_client

About Router

gear.Router is a tire base HTTP request handler. Features:

  1. Support named parameter
  2. Support regexp
  3. Support suffix matching
  4. Support multi-router
  5. Support router layer middlewares
  6. Support fixed path automatic redirection
  7. Support trailing slash automatic redirection
  8. Automatic handle 405 Method Not Allowed
  9. Automatic handle 501 Not Implemented
  10. Automatic handle OPTIONS method
  11. Best Performance

The registered path, against which the router matches incoming requests, can contain six types of parameters:

Syntax Description
:name named parameter
:name(regexp) named with regexp parameter
:name+suffix named parameter with suffix matching
:name(regexp)+suffix named with regexp parameter and suffix matching
:name* named with catch-all parameter
::name not named parameter, it is literal :name

Named parameters are dynamic path segments. They match anything until the next '/' or the path end:

Defined: /api/:type/:ID

/api/user/123             matched: type="user", ID="123"
/api/user                 no match
/api/user/123/comments    no match

Named with regexp parameters match anything using regexp until the next '/' or the path end:

Defined: /api/:type/:ID(^\d+$)

/api/user/123             matched: type="user", ID="123"
/api/user                 no match
/api/user/abc             no match
/api/user/123/comments    no match

Named parameters with suffix, such as Google API Design:

Defined: /api/:resource/:ID+:undelete

/api/file/123                     no match
/api/file/123:undelete            matched: resource="file", ID="123"
/api/file/123:undelete/comments   no match

Named with regexp parameters and suffix:

Defined: /api/:resource/:ID(^\d+$)+:cancel

/api/task/123                   no match
/api/task/123:cancel            matched: resource="task", ID="123"
/api/task/abc:cancel            no match

Named with catch-all parameters match anything until the path end, including the directory index (the '/' before the catch-all). Since they match anything until the end, catch-all parameters must always be the final path element.

Defined: /files/:filepath*

/files                           no match
/files/LICENSE                   matched: filepath="LICENSE"
/files/templates/article.html    matched: filepath="templates/article.html"

The value of parameters is saved on the Matched.Params. Retrieve the value of a parameter by name:

type := matched.Params("type")
id   := matched.Params("ID")

More Middlewares

Applications with Gear

  • KPass - a web application to manage password safe.
  • IP Service - a simple IP service.

License

Gear is licensed under the MIT license. Copyright © 2016-2017 Teambition.

Documentation

Overview

Example
package main

import (
	"fmt"

	"github.com/teambition/gear"
	"github.com/teambition/gear/logging"
	"github.com/teambition/gear/middleware/static"
)

func main() {
	// Create app
	app := gear.New()

	// Use a default logger middleware
	app.UseHandler(logging.Default())

	// Add a static middleware
	// http://localhost:3000/middleware/static.go
	app.Use(static.New(static.Options{
		Root:        "./middleware",
		Prefix:      "/middleware",
		StripPrefix: true,
	}))

	// Add some middleware to app
	app.Use(func(ctx *gear.Context) (err error) {
		// fmt.Println(ctx.IP(), ctx.Method, ctx.Path
		// Do something...

		// Add after hook to the ctx
		ctx.After(func() {
			// Do something in after hook
			fmt.Println("After hook")
		})
		return
	})

	// Create views router
	ViewRouter := gear.NewRouter()
	// "http://localhost:3000"
	ViewRouter.Get("/", func(ctx *gear.Context) error {
		return ctx.HTML(200, "<h1>Hello, Gear!</h1>")
	})
	// "http://localhost:3000/view/abc"
	// "http://localhost:3000/view/123"
	ViewRouter.Get("/view/:view", func(ctx *gear.Context) error {
		view := ctx.Param("view")
		if view == "" {
			return gear.ErrBadRequest.WithMsg("Invalid view")
		}
		return ctx.HTML(200, "View: "+view)
	})
	// "http://localhost:3000/abc"
	// "http://localhost:3000/abc/efg"
	ViewRouter.Get("/:others*", func(ctx *gear.Context) error {
		others := ctx.Param("others")
		if others == "" {
			return gear.ErrBadRequest.WithMsg("Invalid path")
		}
		return ctx.HTML(200, "Request path: /"+others)
	})

	// Create API router
	APIRouter := gear.NewRouter(gear.RouterOptions{Root: "/api", IgnoreCase: true})
	// "http://localhost:3000/api/user/abc"
	// "http://localhost:3000/abc/user/123"
	APIRouter.Get("/user/:id", func(ctx *gear.Context) error {
		id := ctx.Param("id")
		if id == "" {
			return gear.ErrBadRequest.WithMsg("Invalid user id")
		}
		return ctx.JSON(200, map[string]string{
			"Method": ctx.Method,
			"Path":   ctx.Path,
			"UserID": id,
		})
	})

	// Must add APIRouter first.
	app.UseHandler(APIRouter)
	app.UseHandler(ViewRouter)
	// Start app at 3000
	app.Error(app.Listen(":3000"))
}
Output:

Index

Examples

Constants

View Source
const (
	// It will be used by `ctx.ParseBody`, value should implements `gear.BodyParser` interface, default to:
	//  app.Set(gear.SetBodyParser, gear.DefaultBodyParser(1<<20))
	SetBodyParser appSetting = iota

	// It will be used by `ctx.ParseURL`, value should implements `gear.URLParser` interface, default to:
	//  app.Set(gear.SetURLParser, gear.DefaultURLParser)
	SetURLParser

	// Enable compress for response, value should implements `gear.Compressible` interface, no default value.
	// Example:
	//  import "github.com/teambition/compressible-go"
	//
	//  app := gear.New()
	//  app.Set(gear.SetCompress, compressible.WithThreshold(1024))
	SetCompress

	// Set secret keys for signed cookies, it will be used by `ctx.Cookies`, value should be `[]string` type,
	// no default value. More document https://github.com/go-http-utils/cookie, Example:
	//  app.Set(gear.SetKeys, []string{"some key2", "some key1"})
	SetKeys

	// Set a logger to app, value should be `*log.Logger` instance, default to:
	//  app.Set(gear.SetLogger, log.New(os.Stderr, "", 0))
	// Maybe you need LoggerFilterWriter to filter some server errors in production:
	//  app.Set(gear.SetLogger, log.New(gear.DefaultFilterWriter(), "", 0))
	// We recommand set logger flags to 0.
	SetLogger

	// Set a on-error hook to app, value should be `func(ctx *Context, err *Error)`, no default value.
	SetOnError

	// Set a renderer to app, it will be used by `ctx.Render`, value should implements `gear.Renderer` interface,
	// no default value.
	SetRenderer

	// Set a timeout to for the middleware process, value should be `time.Duration`. No default.
	// Example:
	//  app.Set(gear.SetTimeout, 3*time.Second)
	SetTimeout

	// Set a function that Wrap the gear.Context' underlayer context.Context. No default.
	SetWithContext

	// Set a app env string to app, it can be retrieved by `ctx.Setting(gear.SetEnv)`.
	// Default to os process "APP_ENV" or "development".
	SetEnv

	// Set a server name that respond to client as "Server" header.
	// Default to "Gear/{version}".
	SetServerName
)

Build-in app settings

View Source
const (
	// Got from https://github.com/labstack/echo
	MIMEApplicationJSON                  = "application/json"
	MIMEApplicationJSONCharsetUTF8       = "application/json; charset=utf-8"
	MIMEApplicationJavaScript            = "application/javascript"
	MIMEApplicationJavaScriptCharsetUTF8 = "application/javascript; charset=utf-8"
	MIMEApplicationXML                   = "application/xml"
	MIMEApplicationXMLCharsetUTF8        = "application/xml; charset=utf-8"
	MIMEApplicationForm                  = "application/x-www-form-urlencoded"
	MIMEApplicationProtobuf              = "application/protobuf"
	MIMEApplicationMsgpack               = "application/msgpack"
	MIMETextHTML                         = "text/html"
	MIMETextHTMLCharsetUTF8              = "text/html; charset=utf-8"
	MIMETextPlain                        = "text/plain"
	MIMETextPlainCharsetUTF8             = "text/plain; charset=utf-8"
	MIMEMultipartForm                    = "multipart/form-data"
	MIMEOctetStream                      = "application/octet-stream"
)

MIME types

View Source
const (
	HeaderAccept             = "Accept"              // Requests, Responses
	HeaderAcceptCharset      = "Accept-Charset"      // Requests
	HeaderAcceptEncoding     = "Accept-Encoding"     // Requests
	HeaderAcceptLanguage     = "Accept-Language"     // Requests
	HeaderAuthorization      = "Authorization"       // Requests
	HeaderCacheControl       = "Cache-Control"       // Requests, Responses
	HeaderContentLength      = "Content-Length"      // Requests, Responses
	HeaderContentMD5         = "Content-MD5"         // Requests, Responses
	HeaderContentType        = "Content-Type"        // Requests, Responses
	HeaderIfMatch            = "If-Match"            // Requests
	HeaderIfModifiedSince    = "If-Modified-Since"   // Requests
	HeaderIfNoneMatch        = "If-None-Match"       // Requests
	HeaderIfRange            = "If-Range"            // Requests
	HeaderIfUnmodifiedSince  = "If-Unmodified-Since" // Requests
	HeaderMaxForwards        = "Max-Forwards"        // Requests
	HeaderProxyAuthorization = "Proxy-Authorization" // Requests
	HeaderPragma             = "Pragma"              // Requests, Responses
	HeaderRange              = "Range"               // Requests
	HeaderReferer            = "Referer"             // Requests
	HeaderUserAgent          = "User-Agent"          // Requests
	HeaderTE                 = "TE"                  // Requests
	HeaderVia                = "Via"                 // Requests
	HeaderWarning            = "Warning"             // Requests, Responses
	HeaderCookie             = "Cookie"              // Requests
	HeaderOrigin             = "Origin"              // Requests
	HeaderAcceptDatetime     = "Accept-Datetime"     // Requests
	HeaderXRequestedWith     = "X-Requested-With"    // Requests

	HeaderAccessControlAllowOrigin      = "Access-Control-Allow-Origin"      // Responses
	HeaderAccessControlAllowMethods     = "Access-Control-Allow-Methods"     // Responses
	HeaderAccessControlAllowHeaders     = "Access-Control-Allow-Headers"     // Responses
	HeaderAccessControlAllowCredentials = "Access-Control-Allow-Credentials" // Responses
	HeaderAccessControlExposeHeaders    = "Access-Control-Expose-Headers"    // Responses
	HeaderAccessControlMaxAge           = "Access-Control-Max-Age"           // Responses
	HeaderAccessControlRequestMethod    = "Access-Control-Request-Method"    // Responses
	HeaderAccessControlRequestHeaders   = "Access-Control-Request-Headers"   // Responses
	HeaderAcceptPatch                   = "Accept-Patch"                     // Responses
	HeaderAcceptRanges                  = "Accept-Ranges"                    // Responses
	HeaderAllow                         = "Allow"                            // Responses
	HeaderContentEncoding               = "Content-Encoding"                 // Responses
	HeaderContentLanguage               = "Content-Language"                 // Responses
	HeaderContentLocation               = "Content-Location"                 // Responses
	HeaderContentDisposition            = "Content-Disposition"              // Responses
	HeaderContentRange                  = "Content-Range"                    // Responses
	HeaderETag                          = "ETag"                             // Responses
	HeaderExpires                       = "Expires"                          // Responses
	HeaderLastModified                  = "Last-Modified"                    // Responses
	HeaderLink                          = "Link"                             // Responses
	HeaderLocation                      = "Location"                         // Responses
	HeaderP3P                           = "P3P"                              // Responses
	HeaderProxyAuthenticate             = "Proxy-Authenticate"               // Responses
	HeaderRefresh                       = "Refresh"                          // Responses
	HeaderRetryAfter                    = "Retry-After"                      // Responses
	HeaderServer                        = "Server"                           // Responses
	HeaderSetCookie                     = "Set-Cookie"                       // Responses
	HeaderStrictTransportSecurity       = "Strict-Transport-Security"        // Responses
	HeaderTransferEncoding              = "Transfer-Encoding"                // Responses
	HeaderUpgrade                       = "Upgrade"                          // Responses
	HeaderVary                          = "Vary"                             // Responses
	HeaderWWWAuthenticate               = "WWW-Authenticate"                 // Responses
	HeaderPublicKeyPins                 = "Public-Key-Pins"                  // Responses
	HeaderPublicKeyPinsReportOnly       = "Public-Key-Pins-Report-Only"      // Responses
	HeaderRefererPolicy                 = "Referrer-Policy"                  // Responses

	// Common Non-Standard Response Headers
	HeaderXFrameOptions                   = "X-Frame-Options"                     // Responses
	HeaderXXSSProtection                  = "X-XSS-Protection"                    // Responses
	HeaderContentSecurityPolicy           = "Content-Security-Policy"             // Responses
	HeaderContentSecurityPolicyReportOnly = "Content-Security-Policy-Report-Only" // Responses
	HeaderXContentSecurityPolicy          = "X-Content-Security-Policy"           // Responses
	HeaderXWebKitCSP                      = "X-WebKit-CSP"                        // Responses
	HeaderXContentTypeOptions             = "X-Content-Type-Options"              // Responses
	HeaderXPoweredBy                      = "X-Powered-By"                        // Responses
	HeaderXUACompatible                   = "X-UA-Compatible"                     // Responses
	HeaderXForwardedProto                 = "X-Forwarded-Proto"                   // Responses
	HeaderXHTTPMethodOverride             = "X-HTTP-Method-Override"              // Responses
	HeaderXForwardedFor                   = "X-Forwarded-For"                     // Responses
	HeaderXRealIP                         = "X-Real-IP"                           // Responses
	HeaderXCSRFToken                      = "X-CSRF-Token"                        // Responses
	HeaderXDNSPrefetchControl             = "X-DNS-Prefetch-Control"              // Responses
	HeaderXDownloadOptions                = "X-Download-Options"                  // Responses
)

HTTP Header Fields

View Source
const Version = "1.9.2"

Version is Gear's version

Variables

View Source
var (
	Err = &Error{Code: http.StatusInternalServerError, Err: "Error"}

	// https://golang.org/pkg/net/http/#pkg-constants
	ErrBadRequest                    = Err.WithCode(http.StatusBadRequest).WithErr("BadRequest")
	ErrUnauthorized                  = Err.WithCode(http.StatusUnauthorized).WithErr("Unauthorized")
	ErrPaymentRequired               = Err.WithCode(http.StatusPaymentRequired).WithErr("PaymentRequired")
	ErrForbidden                     = Err.WithCode(http.StatusForbidden).WithErr("Forbidden")
	ErrNotFound                      = Err.WithCode(http.StatusNotFound).WithErr("NotFound")
	ErrMethodNotAllowed              = Err.WithCode(http.StatusMethodNotAllowed).WithErr("MethodNotAllowed")
	ErrNotAcceptable                 = Err.WithCode(http.StatusNotAcceptable).WithErr("NotAcceptable")
	ErrProxyAuthRequired             = Err.WithCode(http.StatusProxyAuthRequired).WithErr("ProxyAuthenticationRequired")
	ErrRequestTimeout                = Err.WithCode(http.StatusRequestTimeout).WithErr("RequestTimeout")
	ErrConflict                      = Err.WithCode(http.StatusConflict).WithErr("Conflict")
	ErrGone                          = Err.WithCode(http.StatusGone).WithErr("Gone")
	ErrLengthRequired                = Err.WithCode(http.StatusLengthRequired).WithErr("LengthRequired")
	ErrPreconditionFailed            = Err.WithCode(http.StatusPreconditionFailed).WithErr("PreconditionFailed")
	ErrRequestEntityTooLarge         = Err.WithCode(http.StatusRequestEntityTooLarge).WithErr("RequestEntityTooLarge")
	ErrRequestURITooLong             = Err.WithCode(http.StatusRequestURITooLong).WithErr("RequestURITooLong")
	ErrUnsupportedMediaType          = Err.WithCode(http.StatusUnsupportedMediaType).WithErr("UnsupportedMediaType")
	ErrRequestedRangeNotSatisfiable  = Err.WithCode(http.StatusRequestedRangeNotSatisfiable).WithErr("RequestedRangeNotSatisfiable")
	ErrExpectationFailed             = Err.WithCode(http.StatusExpectationFailed).WithErr("ExpectationFailed")
	ErrTeapot                        = Err.WithCode(http.StatusTeapot).WithErr("Teapot")
	ErrMisdirectedRequest            = Err.WithCode(421).WithErr("MisdirectedRequest")
	ErrUnprocessableEntity           = Err.WithCode(http.StatusUnprocessableEntity).WithErr("UnprocessableEntity")
	ErrLocked                        = Err.WithCode(http.StatusLocked).WithErr("Locked")
	ErrFailedDependency              = Err.WithCode(http.StatusFailedDependency).WithErr("FailedDependency")
	ErrUpgradeRequired               = Err.WithCode(http.StatusUpgradeRequired).WithErr("UpgradeRequired")
	ErrPreconditionRequired          = Err.WithCode(http.StatusPreconditionRequired).WithErr("PreconditionRequired")
	ErrTooManyRequests               = Err.WithCode(http.StatusTooManyRequests).WithErr("TooManyRequests")
	ErrRequestHeaderFieldsTooLarge   = Err.WithCode(http.StatusRequestHeaderFieldsTooLarge).WithErr("RequestHeaderFieldsTooLarge")
	ErrUnavailableForLegalReasons    = Err.WithCode(http.StatusUnavailableForLegalReasons).WithErr("UnavailableForLegalReasons")
	ErrInternalServerError           = Err.WithCode(http.StatusInternalServerError).WithErr("InternalServerError")
	ErrNotImplemented                = Err.WithCode(http.StatusNotImplemented).WithErr("NotImplemented")
	ErrBadGateway                    = Err.WithCode(http.StatusBadGateway).WithErr("BadGateway")
	ErrServiceUnavailable            = Err.WithCode(http.StatusServiceUnavailable).WithErr("ServiceUnavailable")
	ErrGatewayTimeout                = Err.WithCode(http.StatusGatewayTimeout).WithErr("GatewayTimeout")
	ErrHTTPVersionNotSupported       = Err.WithCode(http.StatusHTTPVersionNotSupported).WithErr("HTTPVersionNotSupported")
	ErrVariantAlsoNegotiates         = Err.WithCode(http.StatusVariantAlsoNegotiates).WithErr("VariantAlsoNegotiates")
	ErrInsufficientStorage           = Err.WithCode(http.StatusInsufficientStorage).WithErr("InsufficientStorage")
	ErrLoopDetected                  = Err.WithCode(http.StatusLoopDetected).WithErr("LoopDetected")
	ErrNotExtended                   = Err.WithCode(http.StatusNotExtended).WithErr("NotExtended")
	ErrNetworkAuthenticationRequired = Err.WithCode(http.StatusNetworkAuthenticationRequired).WithErr("NetworkAuthenticationRequired")
)

Predefined errors

Functions

func ContentDisposition added in v1.0.1

func ContentDisposition(fileName, dispositionType string) (header string)

ContentDisposition implements a simple version of https://tools.ietf.org/html/rfc2183 Use mime.ParseMediaType to parse Content-Disposition header.

func Decompress added in v1.8.10

func Decompress(encoding string, r io.Reader) (io.ReadCloser, error)

Decompress wrap the reader for decompressing, It support gzip and zlib, and compatible for deflate.

func GetRouterNodeFromCtx added in v1.9.0

func GetRouterNodeFromCtx(ctx *Context) *trie.Node

GetRouterNodeFromCtx returns matched Node from router

router.Get("/api/:type/:ID", func(ctx *Context) error {
	assert.Equal("/api/:type/:ID", GetRouterNodeFromCtx(ctx).GetPattern())
	return ctx.HTML(200, ctx.Param("type")+ctx.Param("ID"))
})

func IsNil added in v0.26.4

func IsNil(val interface{}) bool

IsNil checks if a specified object is nil or not, without failing.

func IsStatusCode added in v0.18.0

func IsStatusCode(status int) bool

IsStatusCode returns true if status is HTTP status code. https://en.wikipedia.org/wiki/List_of_HTTP_status_codes

func ValuesToStruct added in v1.5.0

func ValuesToStruct(values map[string][]string, target interface{}, tag string) (err error)

ValuesToStruct converts url.Values into struct object. It supports specific types that implementing encoding.TextUnmarshaler interface.

type jsonQueryTemplate struct {
	ID   string `json:"id" form:"id"`
	Pass string `json:"pass" form:"pass"`
}

target := jsonQueryTemplate{}

gear.ValuesToStruct(map[string][]string{
	"id": []string{"some id"},
	"pass": []string{"some pass"},
}, &target, "form")

Types

type Any added in v0.10.0

type Any interface {
	New(ctx *Context) (interface{}, error)
}

Any interface is used by ctx.Any.

type App added in v0.11.0

type App struct {
	Server *http.Server
	// contains filtered or unexported fields
}

App is the top-level framework app instance.

Hello Gear!

package main

import "github.com/teambition/gear"

func main() {
	app := gear.New() // Create app
	app.Use(func(ctx *gear.Context) error {
		return ctx.HTML(200, "<h1>Hello, Gear!</h1>")
	})
	app.Error(app.Listen(":3000"))
}

func New

func New() *App

New creates an instance of App.

func (*App) Close added in v1.0.0

func (app *App) Close(ctx ...context.Context) error

Close closes the underlying server. If context omit, Server.Close will be used to close immediately. Otherwise Server.Shutdown will be used to close gracefully.

func (*App) Env added in v0.26.4

func (app *App) Env() string

Env returns app' env. You can set app env with `app.Set(gear.SetEnv, "some env")` Default to os process "APP_ENV" or "development".

func (*App) Error added in v0.11.0

func (app *App) Error(err error)

Error writes error to underlayer logging system.

func (*App) Listen added in v0.11.0

func (app *App) Listen(addr string) error

Listen starts the HTTP server.

func (*App) ListenTLS added in v0.11.0

func (app *App) ListenTLS(addr, certFile, keyFile string) error

ListenTLS starts the HTTPS server.

func (*App) ServeHTTP added in v0.25.0

func (app *App) ServeHTTP(w http.ResponseWriter, r *http.Request)

func (*App) Set added in v0.12.0

func (app *App) Set(key, val interface{}) *App

Set add key/value settings to app. The settings can be retrieved by `ctx.Setting(key)`.

func (*App) Start added in v0.11.0

func (app *App) Start(addr ...string) *ServerListener

Start starts a non-blocking app instance. It is useful for testing. If addr omit, the app will listen on a random addr, use ServerListener.Addr() to get it. The non-blocking app instance must close by ServerListener.Close().

func (*App) Use added in v0.11.0

func (app *App) Use(handle Middleware) *App

Use uses the given middleware `handle`.

func (*App) UseHandler added in v0.11.0

func (app *App) UseHandler(h Handler) *App

UseHandler uses a instance that implemented Handler interface.

type BodyParser added in v0.23.0

type BodyParser interface {
	// Maximum allowed size for a request body
	MaxBytes() int64
	Parse(buf []byte, body interface{}, mediaType, charset string) error
}

BodyParser interface is used by ctx.ParseBody. Default to:

app.Set(gear.SetBodyParser, gear.DefaultBodyParser(1<<20))

type BodyTemplate added in v0.23.0

type BodyTemplate interface {
	Validate() error
}

BodyTemplate interface is used by ctx.ParseBody.

type Compressible added in v0.16.5

type Compressible interface {
	// Compressible checks the response Content-Type and Content-Length to
	// determine whether to compress.
	// `length == 0` means response body maybe stream, or will be writed later.
	Compressible(contentType string, contentLength int) bool
}

Compressible interface is use to enable compress response content.

type Context

type Context struct {
	Req     *http.Request
	Res     *Response
	Cookies *cookie.Cookies // https://github.com/go-http-utils/cookie

	Host   string
	Method string
	Path   string
	// contains filtered or unexported fields
}

Context represents the context of the current HTTP request. It holds request and response objects, path, path parameters, data, registered handler and content.Context.

func NewContext added in v0.5.0

func NewContext(app *App, w http.ResponseWriter, r *http.Request) *Context

NewContext creates an instance of Context. Export for testing middleware.

func (*Context) AcceptCharset added in v0.21.0

func (ctx *Context) AcceptCharset(preferred ...string) string

AcceptCharset returns the most preferred charset from the HTTP Accept-Charset header. If nothing accepted, then empty string is returned.

func (*Context) AcceptEncoding added in v0.21.0

func (ctx *Context) AcceptEncoding(preferred ...string) string

AcceptEncoding returns the most preferred encoding from the HTTP Accept-Encoding header. If nothing accepted, then empty string is returned.

func (*Context) AcceptLanguage added in v0.21.0

func (ctx *Context) AcceptLanguage(preferred ...string) string

AcceptLanguage returns the most preferred language from the HTTP Accept-Language header. If nothing accepted, then empty string is returned.

func (*Context) AcceptType added in v0.21.0

func (ctx *Context) AcceptType(preferred ...string) string

AcceptType returns the most preferred content type from the HTTP Accept header. If nothing accepted, then empty string is returned.

func (*Context) After

func (ctx *Context) After(hook func())

After add a "after hook" to the ctx that will run after middleware process, but before Response.WriteHeader. So it will block response writing.

func (*Context) Any added in v0.10.0

func (ctx *Context) Any(any interface{}) (val interface{}, err error)

Any returns the value on this ctx by key. If key is instance of Any and value not set, any.New will be called to eval the value, and then set to the ctx. if any.New returns error, the value will not be set.

// create some Any type for your project.
type someAnyType struct{}
type someAnyResult struct {
	r *http.Request
}

var someAnyKey = &someAnyType{}

func (t *someAnyType) New(ctx *gear.Context) (interface{}, error) {
	return &someAnyResult{r: ctx.Req}, nil
}

// use it in app
if val, err := ctx.Any(someAnyKey); err == nil {
	res := val.(*someAnyResult)
}

func (*Context) Attachment

func (ctx *Context) Attachment(name string, modtime time.Time, content io.ReadSeeker, inline ...bool) (err error)

Attachment sends a response from `io.ReaderSeeker` as attachment, prompting client to save the file. If inline is true, the attachment will sends as inline, opening the file in the browser. It will end the ctx. The middlewares after current middleware will not run. "after hooks" and "end hooks" will run normally.

func (*Context) Cancel

func (ctx *Context) Cancel()

Cancel cancel the ctx and all it' children context. The ctx' process will ended too.

func (*Context) Context added in v1.0.3

func (ctx *Context) Context() context.Context

Context returns the underlying context of gear.Context

func (*Context) Deadline added in v0.5.0

func (ctx *Context) Deadline() (time.Time, bool)

Deadline returns the time when work done on behalf of this context should be canceled.

func (*Context) Done added in v0.5.0

func (ctx *Context) Done() <-chan struct{}

Done returns a channel that's closed when work done on behalf of this context should be canceled.

func (*Context) End

func (ctx *Context) End(code int, buf ...[]byte) (err error)

End end the ctx with bytes and status code optionally. After it's called, the rest of middleware handles will not run. But "after hooks" and "end hooks" will run normally.

func (*Context) Err added in v0.5.0

func (ctx *Context) Err() error

Err returns a non-nil error value after Done is closed.

func (*Context) Error

func (ctx *Context) Error(e error) error

Error send a error with application/json type to response. It will not reset response headers and not use app.OnError hook It will end the ctx. The middlewares after current middleware and "after hooks" will not run. "end hooks" will run normally.

func (*Context) ErrorStatus added in v0.23.0

func (ctx *Context) ErrorStatus(status int) error

ErrorStatus send a error by status code with application/json type to response. The status should be 4xx or 5xx code. It will not reset response headers and not use app.OnError hook It will end the ctx. The middlewares after current middleware and "after hooks" will not run. "end hooks" will run normally.

func (*Context) Get

func (ctx *Context) Get(key string) string

Get - Please use ctx.GetHeader instead. This method will be changed in v2.

func (*Context) GetHeader added in v1.8.0

func (ctx *Context) GetHeader(key string) string

GetHeader retrieves data from the request Header.

func (*Context) HTML

func (ctx *Context) HTML(code int, str string) error

HTML set an Html body with status code to response. It will end the ctx. The middlewares after current middleware will not run. "after hooks" and "end hooks" will run normally.

func (*Context) IP

func (ctx *Context) IP() net.IP

IP returns the client's network address based on `X-Forwarded-For` or `X-Real-IP` request header.

func (*Context) JSON

func (ctx *Context) JSON(code int, val interface{}) error

JSON set a JSON body with status code to response. It will end the ctx. The middlewares after current middleware will not run. "after hooks" (if no error) and "end hooks" will run normally.

func (*Context) JSONBlob

func (ctx *Context) JSONBlob(code int, buf []byte) error

JSONBlob set a JSON blob body with status code to response. It will end the ctx. The middlewares after current middleware will not run. "after hooks" and "end hooks" will run normally.

func (*Context) JSONP

func (ctx *Context) JSONP(code int, callback string, val interface{}) error

JSONP sends a JSONP response with status code. It uses `callback` to construct the JSONP payload. It will end the ctx. The middlewares after current middleware will not run. "after hooks" (if no error) and "end hooks" will run normally.

func (*Context) JSONPBlob

func (ctx *Context) JSONPBlob(code int, callback string, buf []byte) error

JSONPBlob sends a JSONP blob response with status code. It uses `callback` to construct the JSONP payload. It will end the ctx. The middlewares after current middleware will not run. "after hooks" and "end hooks" will run normally.

func (*Context) LogErr added in v1.8.7

func (ctx *Context) LogErr(err error)

LogErr writes error to underlayer logging system through app.Error.

func (*Context) MustAny added in v1.8.8

func (ctx *Context) MustAny(any interface{}) interface{}

MustAny returns the value on this ctx by key. It is a sugar for ctx.Any, If some error occurred, it will panic.

func (*Context) OnEnd

func (ctx *Context) OnEnd(hook func())

OnEnd add a "end hook" to the ctx that will run after Response.WriteHeader. They run in a goroutine and will not block response. Take care that http.ResponseWriter and http.Request maybe reset for reusing. Issue https://github.com/teambition/gear/issues/24

func (*Context) Param

func (ctx *Context) Param(key string) (val string)

Param returns path parameter by name.

func (*Context) ParseBody added in v0.23.0

func (ctx *Context) ParseBody(body BodyTemplate) error

ParseBody parses request content with BodyParser, stores the result in the value pointed to by BodyTemplate body, and validate it. DefaultBodyParser support JSON, Form and XML.

Define a BodyTemplate type in some API:

type jsonBodyTemplate struct {
	ID   string `json:"id" form:"id"`
	Pass string `json:"pass" form:"pass"`
}

func (b *jsonBodyTemplate) Validate() error {
	if len(b.ID) < 3 || len(b.Pass) < 6 {
		return ErrBadRequest.WithMsg("invalid id or pass")
	}
	return nil
}

Use it in middleware:

body := jsonBodyTemplate{}
if err := ctx.ParseBody(&body) {
	return err
}

func (*Context) ParseURL added in v1.5.0

func (ctx *Context) ParseURL(body BodyTemplate) error

ParseURL parses router params (like ctx.Param) and queries (like ctx.Query) in request URL, stores the result in the struct object pointed to by BodyTemplate body, and validate it.

Define a BodyTemplate type in some API:

type taskTemplate struct {
	ID      bson.ObjectId `json:"_taskID" param:"_taskID"` // router.Get("/tasks/:_taskID", APIhandler)
	StartAt time.Time     `json:"startAt" query:"startAt"` // GET /tasks/50c32afae8cf1439d35a87e6?startAt=2017-05-03T10:06:45.319Z
}

func (b *taskTemplate) Validate() error {
	if !b.ID.Valid() {
		return gear.ErrBadRequest.WithMsg("invalid task id")
	}
	if b.StartAt.IsZero() {
		return gear.ErrBadRequest.WithMsg("invalid task start time")
	}
	return nil
}

Use it in APIhandler:

body := taskTemplate{}
if err := ctx.ParseURL(&body) {
	return err
}

func (*Context) Protocol added in v1.4.2

func (ctx *Context) Protocol() string

Protocol returns the protocol ("http" or "https") that a client used to connect to your proxy or load balancer. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Proto

func (*Context) Query

func (ctx *Context) Query(name string) string

Query returns the query param for the provided name.

func (*Context) QueryAll added in v0.23.2

func (ctx *Context) QueryAll(name string) []string

QueryAll returns all query params for the provided name.

func (*Context) Redirect

func (ctx *Context) Redirect(url string) (err error)

Redirect redirects the request with status code 302. You can use other status code with ctx.Status method, It is a wrap of http.Redirect. It will end the ctx. The middlewares after current middleware will not run. "after hooks" and "end hooks" will run normally.

func (*Context) Render

func (ctx *Context) Render(code int, name string, data interface{}) (err error)

Render renders a template with data and sends a text/html response with status code. Templates can be registered using `app.Renderer = Renderer`. It will end the ctx. The middlewares after current middleware will not run. "after hooks" (if no error) and "end hooks" will run normally.

func (*Context) Set

func (ctx *Context) Set(key, value string)

Set - Please use ctx.SetHeader instead. This method will be changed in v2.

func (*Context) SetAny added in v0.10.0

func (ctx *Context) SetAny(key, val interface{})

SetAny save a key, value pair on the ctx. Then we can use ctx.Any(key) to retrieve the value from ctx.

func (*Context) SetHeader added in v1.8.0

func (ctx *Context) SetHeader(key, value string)

SetHeader saves data to the response Header.

func (*Context) Setting added in v0.12.0

func (ctx *Context) Setting(key interface{}) interface{}

Setting returns App's settings by key

fmt.Println(ctx.Setting(gear.SetEnv).(string) == "development")
app.Set(gear.SetEnv, "production")
fmt.Println(ctx.Setting(gear.SetEnv).(string) == "production")

func (*Context) Status

func (ctx *Context) Status(code int)

Status set a status code to the response, ctx.Res.Status() returns the status code.

func (*Context) Stream

func (ctx *Context) Stream(code int, contentType string, r io.Reader) (err error)

Stream sends a streaming response with status code and content type. It will end the ctx. The middlewares after current middleware will not run. "after hooks" and "end hooks" will run normally.

func (*Context) Timing added in v0.16.1

func (ctx *Context) Timing(dt time.Duration, fn func(context.Context)) (err error)

Timing runs fn with the given time limit. If a call runs for longer than its time limit or panic, it will return context.DeadlineExceeded error or panic error.

func (*Context) Type

func (ctx *Context) Type(str string)

Type set a content type to the response, ctx.Res.Type() returns the content type.

func (*Context) Value added in v0.5.0

func (ctx *Context) Value(key interface{}) (val interface{})

Value returns the value associated with this context for key, or nil if no value is associated with key. Successive calls to Value with the same key returns the same result.

func (*Context) WithCancel

func (ctx *Context) WithCancel() (context.Context, context.CancelFunc)

WithCancel returns a copy of the ctx with a new Done channel. The returned context's Done channel is closed when the returned cancel function is called or when the parent context's Done channel is closed, whichever happens first.

func (*Context) WithContext added in v0.26.6

func (ctx *Context) WithContext(c context.Context)

WithContext sets the context to underlying gear.Context. The context must be a children or a grandchild of gear.Context.

ctx.WithContext(ctx.WithValue("key", "value"))
// ctx.Value("key") == "value"

a opentracing middleware:

func New(opts ...opentracing.StartSpanOption) gear.Middleware {
	return func(ctx *gear.Context) error {
		span := opentracing.StartSpan(fmt.Sprintf(`%s %s`, ctx.Method, ctx.Path), opts...)
		ctx.WithContext(opentracing.ContextWithSpan(ctx.Context(), span))
		ctx.OnEnd(span.Finish)
		return nil
	}
}

func (*Context) WithDeadline

func (ctx *Context) WithDeadline(deadline time.Time) (context.Context, context.CancelFunc)

WithDeadline returns a copy of the ctx with the deadline adjusted to be no later than d.

func (*Context) WithTimeout

func (ctx *Context) WithTimeout(timeout time.Duration) (context.Context, context.CancelFunc)

WithTimeout returns WithDeadline(time.Now().Add(timeout)).

func (*Context) WithValue

func (ctx *Context) WithValue(key, val interface{}) context.Context

WithValue returns a copy of the ctx in which the value associated with key is val.

func (*Context) XML

func (ctx *Context) XML(code int, val interface{}) error

XML set an XML body with status code to response. It will end the ctx. The middlewares after current middleware will not run. "after hooks" (if no error) and "end hooks" will run normally.

func (*Context) XMLBlob

func (ctx *Context) XMLBlob(code int, buf []byte) error

XMLBlob set a XML blob body with status code to response. It will end the ctx. The middlewares after current middleware will not run. "after hooks" and "end hooks" will run normally.

type DefaultBodyParser added in v0.23.0

type DefaultBodyParser int64

DefaultBodyParser is default BodyParser type. SetBodyParser used 1MB as default:

app.Set(gear.SetBodyParser, gear.DefaultBodyParser(1<<20))

func (DefaultBodyParser) MaxBytes added in v0.23.0

func (d DefaultBodyParser) MaxBytes() int64

MaxBytes implemented BodyParser interface.

func (DefaultBodyParser) Parse added in v0.23.0

func (d DefaultBodyParser) Parse(buf []byte, body interface{}, mediaType, charset string) error

Parse implemented BodyParser interface.

type DefaultCompress added in v0.14.0

type DefaultCompress struct{}

DefaultCompress is defalut Compress implemented. Use it to enable compress:

app.Set(gear.SetCompress, &gear.DefaultCompress{})

func (*DefaultCompress) Compressible added in v0.14.0

func (d *DefaultCompress) Compressible(contentType string, contentLength int) bool

Compressible implemented Compress interface. Recommend https://github.com/teambition/compressible-go.

import "github.com/teambition/compressible-go"

app := gear.New()
app.Set(gear.SetCompress, compressible.WithThreshold(1024))

// Add a static middleware
app.Use(static.New(static.Options{
	Root:   "./",
	Prefix: "/",
}))
app.Error(app.Listen(":3000")) // http://127.0.0.1:3000/

type DefaultURLParser added in v1.5.0

type DefaultURLParser struct{}

DefaultURLParser is default URLParser type.

func (DefaultURLParser) Parse added in v1.5.0

func (d DefaultURLParser) Parse(val map[string][]string, body interface{}, tag string) error

Parse implemented URLParser interface.

type Error added in v0.3.0

type Error struct {
	Code  int         `json:"-"`
	Err   string      `json:"error"`
	Msg   string      `json:"message"`
	Data  interface{} `json:"data,omitempty"`
	Stack string      `json:"-"`
}

Error represents a numeric error with optional meta. It can be used in middleware as a return result.

func ErrorWithStack added in v0.24.0

func ErrorWithStack(val interface{}, skip ...int) *Error

ErrorWithStack create a error with stacktrace

func (*Error) Error added in v0.10.0

func (err *Error) Error() string

Error implemented HTTPError interface.

func (Error) Format added in v1.8.2

func (err Error) Format() (string, error)

Format implemented logging.Messager interface.

func (Error) From added in v1.4.0

func (err Error) From(e error) *Error

From returns a copy of err with given error. It will try to merge the given error. If the given error is a *Error instance, it will be returned without copy.

err := gear.ErrBadRequest.From(errors.New("invalid email"))
err := gear.Err.From(someErr)

func (Error) GoString added in v1.7.0

func (err Error) GoString() string

GoString implemented fmt.GoStringer interface, returns a Go-syntax string.

func (*Error) Status added in v0.3.0

func (err *Error) Status() int

Status implemented HTTPError interface.

func (Error) String added in v0.15.1

func (err Error) String() string

String implemented fmt.Stringer interface.

func (Error) WithCode added in v1.4.0

func (err Error) WithCode(code int) *Error

WithCode returns a copy of err with given code.

BadRequestErr := gear.Err.WithCode(400)

func (Error) WithErr added in v1.7.9

func (err Error) WithErr(name string) *Error

WithErr returns a copy of err with given new error name.

err := gear.ErrBadRequest.WithErr("InvalidEmail") // 400 Bad Request error with error name InvalidEmail"

func (Error) WithMsg added in v1.4.0

func (err Error) WithMsg(msgs ...string) *Error

WithMsg returns a copy of err with given new messages.

err := gear.Err.WithMsg() // just clone
err := gear.ErrBadRequest.WithMsg("invalid email") // 400 Bad Request error with message invalid email"

func (Error) WithMsgf added in v1.5.3

func (err Error) WithMsgf(format string, args ...interface{}) *Error

WithMsgf returns a copy of err with given message in the manner of fmt.Printf.

err := gear.ErrBadRequest.WithMsgf(`invalid email: "%s"`, email)

func (Error) WithStack added in v1.5.3

func (err Error) WithStack(skip ...int) *Error

WithStack returns a copy of err with error stack.

err := gear.Err.WithMsg("some error").WithStack()

type HTTPError

type HTTPError interface {
	// Error returns error's message.
	Error() string
	// Status returns error's http status code.
	Status() int
}

HTTPError interface is used to create a server error that include status code and error message.

func ParseError added in v0.10.0

func ParseError(e error, code ...int) HTTPError

ParseError parse a error, textproto.Error or HTTPError to HTTPError

type Handler

type Handler interface {
	Serve(ctx *Context) error
}

Handler interface is used by app.UseHandler as a middleware.

type LoggerFilterWriter added in v1.7.5

type LoggerFilterWriter struct {
	// contains filtered or unexported fields
}

LoggerFilterWriter is a writer for Logger to filter bytes. In a https server, avoid some handshake mismatch condition such as loadbalance healthcheck:

2017/06/09 07:18:04 http: TLS handshake error from 10.10.5.1:45001: tls: first record does not look like a TLS handshake
2017/06/14 02:39:29 http: TLS handshake error from 10.0.1.2:54975: read tcp 10.10.5.22:8081->10.0.1.2:54975: read: connection reset by peer

Usage:

func main() {
	app := gear.New() // Create app
	app.Use(func(ctx *gear.Context) error {
		return ctx.HTML(200, "<h1>Hello, Gear!</h1>")
	})

	app.Set(gear.SetLogger, log.New(gear.DefaultFilterWriter(), "", 0))
	app.Listen(":3000")
}

func DefaultFilterWriter added in v1.7.5

func DefaultFilterWriter() *LoggerFilterWriter

DefaultFilterWriter returns the default LoggerFilterWriter instance.

func (*LoggerFilterWriter) Add added in v1.7.5

func (s *LoggerFilterWriter) Add(err string)

Add add a phrase string to filter

func (*LoggerFilterWriter) SetOutput added in v1.7.5

func (s *LoggerFilterWriter) SetOutput(out io.Writer)

SetOutput sets the output destination for the loggerFilterWriter.

func (*LoggerFilterWriter) Write added in v1.7.5

func (s *LoggerFilterWriter) Write(p []byte) (n int, err error)

type Middleware

type Middleware func(ctx *Context) error

Middleware defines a function to process as middleware.

func Compose added in v0.26.4

func Compose(mds ...Middleware) Middleware

Compose composes a slice of middlewares to one middleware

func WrapHandler added in v0.3.0

func WrapHandler(handler http.Handler) Middleware

WrapHandler wrap a http.Handler to Gear Middleware

func WrapHandlerFunc added in v0.3.0

func WrapHandlerFunc(fn http.HandlerFunc) Middleware

WrapHandlerFunc wrap a http.HandlerFunc to Gear Middleware

type Renderer

type Renderer interface {
	Render(ctx *Context, w io.Writer, name string, data interface{}) error
}

Renderer interface is used by ctx.Render.

type Response

type Response struct {
	// contains filtered or unexported fields
}

Response wraps an http.ResponseWriter and implements its interface to be used by an HTTP handler to construct an HTTP response.

func (*Response) Body

func (r *Response) Body() []byte

Body returns the response content. If you use Response.Write directly, the content will not be captured.

func (*Response) CloseNotify added in v0.20.0

func (r *Response) CloseNotify() <-chan bool

CloseNotify implements the http.CloseNotifier interface to allow detecting when the underlying connection has gone away. This mechanism can be used to cancel long operations on the server if the client has disconnected before the response is ready. See http.CloseNotifier(https://golang.org/pkg/net/http/#CloseNotifier)

func (*Response) Del

func (r *Response) Del(key string)

Del deletes the header entries associated with key.

func (*Response) Flush added in v0.20.0

func (r *Response) Flush()

Flush implements the http.Flusher interface to allow an HTTP handler to flush buffered data to the client. See http.Flusher(https://golang.org/pkg/net/http/#Flusher)

func (*Response) Get

func (r *Response) Get(key string) string

Get gets the first value associated with the given key. If there are no values associated with the key, Get returns "". To access multiple values of a key, access the map directly with CanonicalHeaderKey.

func (*Response) Header

func (r *Response) Header() http.Header

Header returns the header map that will be sent by WriteHeader.

func (*Response) HeaderWrote added in v0.14.0

func (r *Response) HeaderWrote() bool

HeaderWrote indecates that whether the reply header has been (logically) written.

func (*Response) Hijack added in v0.20.0

func (r *Response) Hijack() (net.Conn, *bufio.ReadWriter, error)

Hijack implements the http.Hijacker interface to allow an HTTP handler to take over the connection. See http.Hijacker(https://golang.org/pkg/net/http/#Hijacker)

func (*Response) Push added in v1.0.0

func (r *Response) Push(target string, opts *http.PushOptions) error

Push implements http.Pusher. Example: https://github.com/teambition/gear/blob/master/example/http2/app.go

func (*Response) ResetHeader added in v0.16.4

func (r *Response) ResetHeader(filterReg ...*regexp.Regexp)

ResetHeader reset headers. The default filterReg is `(?i)^(accept|allow|retry-after|warning|vary|server|x-powered-by|access-control-allow-|x-ratelimit-)`.

func (*Response) Set

func (r *Response) Set(key, value string)

Set sets the header entries associated with key to the single element value. It replaces any existing values associated with key.

func (*Response) Status

func (r *Response) Status() int

Status returns the current status code.

func (*Response) Type

func (r *Response) Type() string

Type returns the current content type.

func (*Response) Vary added in v0.21.0

func (r *Response) Vary(field string)

Vary manipulate the HTTP Vary header. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Vary

func (*Response) Write

func (r *Response) Write(buf []byte) (int, error)

Write writes the data to the connection as part of an HTTP reply.

func (*Response) WriteHeader

func (r *Response) WriteHeader(code int)

WriteHeader sends an HTTP response header with status code. If WriteHeader is not called explicitly, the first call to Write will trigger an implicit WriteHeader(http.StatusOK). Thus explicit calls to WriteHeader are mainly used to send error codes.

type Router

type Router struct {
	// contains filtered or unexported fields
}

Router is a tire base HTTP request handler for Gear which can be used to dispatch requests to different handler functions. A trivial example is:

package main

import (
	"fmt"

	"github.com/teambition/gear"
)

func SomeRouterMiddleware(ctx *gear.Context) error {
	// do some thing.
	fmt.Println("Router middleware...")
	return nil
}

func ViewHello(ctx *gear.Context) error {
	return ctx.HTML(200, "<h1>Hello, Gear!</h1>")
}

func main() {
	app := gear.New()
	// Add app middleware

	router := gear.NewRouter()
	router.Use(SomeRouterMiddleware) // Add router middleware, optionally
	router.Get("/", ViewHello)

	app.UseHandler(router)
	app.Error(app.Listen(":3000"))
}

The router matches incoming requests by the request method and the path. If a handle is registered for this path and method, the router delegates the request to that function.

The registered path, against which the router matches incoming requests, can contain six types of parameters:

| Syntax | Description |
|--------|------|
| `:name` | named parameter |
| `:name(regexp)` | named with regexp parameter |
| `:name+suffix` | named parameter with suffix matching |
| `:name(regexp)+suffix` | named with regexp parameter and suffix matching |
| `:name*` | named with catch-all parameter |
| `::name` | not named parameter, it is literal `:name` |

Named parameters are dynamic path segments. They match anything until the next '/' or the path end:

Defined: `/api/:type/:ID`

/api/user/123             matched: type="user", ID="123"
/api/user                 no match
/api/user/123/comments    no match

Named with regexp parameters match anything using regexp until the next '/' or the path end:

Defined: `/api/:type/:ID(^\d+$)`

/api/user/123             matched: type="user", ID="123"
/api/user                 no match
/api/user/abc             no match
/api/user/123/comments    no match

Named parameters with suffix, such as [Google API Design](https://cloud.google.com/apis/design/custom_methods):

Defined: `/api/:resource/:ID+:undelete`

/api/file/123                     no match
/api/file/123:undelete            matched: resource="file", ID="123"
/api/file/123:undelete/comments   no match

Named with regexp parameters and suffix:

Defined: `/api/:resource/:ID(^\d+$)+:cancel`

/api/task/123                   no match
/api/task/123:cancel            matched: resource="task", ID="123"
/api/task/abc:cancel            no match

Named with catch-all parameters match anything until the path end, including the directory index (the '/' before the catch-all). Since they match anything until the end, catch-all parameters must always be the final path element.

Defined: `/files/:filepath*`

/files                           no match
/files/LICENSE                   matched: filepath="LICENSE"
/files/templates/article.html    matched: filepath="templates/article.html"

The value of parameters is saved on the `Matched.Params`. Retrieve the value of a parameter by name:

type := matched.Params("type")
id   := matched.Params("ID")

More info: https://github.com/teambition/trie-mux

func NewRouter

func NewRouter(routerOptions ...RouterOptions) *Router

NewRouter returns a new Router instance with root path and ignoreCase option. Gear support multi-routers. For example:

// Create app
app := gear.New()

// Create views router
viewRouter := gear.NewRouter()
viewRouter.Get("/", Ctl.IndexView)
// add more ...

apiRouter := gear.NewRouter(RouterOptions{
	Root: "/api",
	IgnoreCase: true,
	FixedPathRedirect: true,
	TrailingSlashRedirect: true,
})
// support one more middleware
apiRouter.Get("/user/:id", API.Auth, API.User)
// add more ..

app.UseHandler(apiRouter) // Must add apiRouter first.
app.UseHandler(viewRouter)
// Start app at 3000
app.Listen(":3000")

func (*Router) Delete

func (r *Router) Delete(pattern string, handlers ...Middleware) *Router

Delete registers a new DELETE route for a path with matching handler in the router.

func (*Router) Get

func (r *Router) Get(pattern string, handlers ...Middleware) *Router

Get registers a new GET route for a path with matching handler in the router.

func (*Router) Handle

func (r *Router) Handle(method, pattern string, handlers ...Middleware) *Router

Handle registers a new Middleware handler with method and path in the router. For GET, POST, PUT, PATCH and DELETE requests the respective shortcut functions can be used.

This function is intended for bulk loading and to allow the usage of less frequently used, non-standardized or custom methods (e.g. for internal communication with a proxy).

func (*Router) Head

func (r *Router) Head(pattern string, handlers ...Middleware) *Router

Head registers a new HEAD route for a path with matching handler in the router.

func (*Router) Options

func (r *Router) Options(pattern string, handlers ...Middleware) *Router

Options registers a new OPTIONS route for a path with matching handler in the router.

func (*Router) Otherwise

func (r *Router) Otherwise(handlers ...Middleware) *Router

Otherwise registers a new Middleware handler in the router that will run if there is no other handler matching.

func (*Router) Patch

func (r *Router) Patch(pattern string, handlers ...Middleware) *Router

Patch registers a new PATCH route for a path with matching handler in the router.

func (*Router) Post

func (r *Router) Post(pattern string, handlers ...Middleware) *Router

Post registers a new POST route for a path with matching handler in the router.

func (*Router) Put

func (r *Router) Put(pattern string, handlers ...Middleware) *Router

Put registers a new PUT route for a path with matching handler in the router.

func (*Router) Serve added in v0.5.0

func (r *Router) Serve(ctx *Context) error

Serve implemented gear.Handler interface

func (*Router) Use

func (r *Router) Use(handle Middleware) *Router

Use registers a new Middleware in the router, that will be called when router mathed.

type RouterOptions added in v0.15.0

type RouterOptions struct {
	// Router's namespace. Gear supports multiple routers with different namespace.
	// Root string should start with "/", default to "/"
	Root string

	// Ignore case when matching URL path.
	IgnoreCase bool

	// Enables automatic redirection if the current path can't be matched but
	// a handler for the fixed path exists.
	// For example if "/api//foo" is requested but a route only exists for "/api/foo", the
	// client is redirected to "/api/foo"" with http status code 301 for GET requests
	// and 307 for all other request methods.
	FixedPathRedirect bool

	// Enables automatic redirection if the current route can't be matched but a
	// handler for the path with (without) the trailing slash exists.
	// For example if "/foo/" is requested but a route only exists for "/foo", the
	// client is redirected to "/foo"" with http status code 301 for GET requests
	// and 307 for all other request methods.
	TrailingSlashRedirect bool
}

RouterOptions is options for Router

type ServerListener added in v0.6.0

type ServerListener struct {
	// contains filtered or unexported fields
}

ServerListener is returned by a non-blocking app instance.

func (*ServerListener) Addr added in v0.6.0

func (s *ServerListener) Addr() net.Addr

Addr returns the non-blocking app instance addr.

func (*ServerListener) Close added in v0.6.0

func (s *ServerListener) Close() error

Close closes the non-blocking app instance.

func (*ServerListener) Wait added in v0.6.0

func (s *ServerListener) Wait() error

Wait make the non-blocking app instance blocking.

type URLParser added in v1.5.0

type URLParser interface {
	Parse(val map[string][]string, body interface{}, tag string) error
}

URLParser interface is used by ctx.ParseUrl. Default to:

app.Set(gear.SetURLParser, gear.DefaultURLParser)

Directories

Path Synopsis
example
sse
middleware

Jump to

Keyboard shortcuts

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