cotton

package module
v0.7.8 Latest Latest
Warning

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

Go to latest
Published: Feb 18, 2025 License: MIT Imports: 22 Imported by: 1

README

GoDoc Release Build Status Go Go Report Card

Cotton is a RESTful web framework written by Go (Golang). It's fast and scalable.

Contents

Installation

To install Cotton package, you need to install Go and set your Go workspace first.

  1. The first need Go installed (go 1.13 or later)
  2. install Cotton
go get -u github.com/tonny-zhang/cotton
  1. Import it in your code:
import "github.com/tonny-zhang/cotton

Quick start

You can find more in example/*

package main

import "github.com/tonny-zhang/cotton"

func main() {
	r := cotton.NewRouter()
	r.Get("/hello", func(ctx *cotton.Context) {
		ctx.String("hello world from cotton")
	})

	r.Run(":8080")
}

Feature

API Example

You can find a number of ready-to-run examples at examples project

Using GET, POST, PUT, OPTIONS, DELETE, PATCH, HEAD
func main() {
	r := cotton.NewRouter()
	r.Get("/hello", handler)
	r.Post("/hello", handler)

	r.Run(":8080")
}
Parameters in path
func main() {
	r := cotton.NewRouter()
	// /user/tonny		=> 	match
	// /user/123 		=> 	match
	// /user			=> 	no
	// /user/			=> 	no
	r.Get("/user/:name", func(c *cotton.Context) {
		c.String(200, "hello "+c.Param("name"))
	})

	// /file/test		=> 	match
	// /file/a/b/c		=> 	match
	// /room/			=> 	no
	r.Get("/file/*file", func(c *cotton.Context) {
		c.String(200, "file = "+c.Param("file"))
	})

	r.Run(":8080")
}
Querystring parameters
func main() {
	r := cotton.NewRouter()
	r.Get("/get", func(ctx *cotton.Context) {
		name := ctx.GetQuery("name")
		first := ctx.GetDefaultQuery("first", "first default value")

		ids := ctx.GetQueryArray("ids[]")
		m, _ := ctx.GetQueryMap("info")
		ctx.String(http.StatusOK, fmt.Sprintf("name = %s, first = %s, ids = %v, info = %v", name, first, ids, m))
	})

	r.Run("")
}
Using middleware
func main() {
	r := cotton.NewRouter()

	r.Use(cotton.Recover())
	r.Use(cotton.Logger())

	r.Get("/hello", func(c *cotton.Context) {
		c.String(200, "hello")
	})
	r.Run(":8080")
}
Using group
func main() {
	r := cotton.NewRouter()
	g1 := r.Group("/v1", func(ctx *cotton.Context) {
		// use as a middleware in group
	})
	g1.Use(func(ctx *cotton.Context) {
		fmt.Println("g1 middleware 2")
	})
	{
		g1.Get("/a", func(ctx *cotton.Context) {
			ctx.String(200, http.StatusOK, "g1 a")
		})
	}

	r.Get("/v2/a", func(ctx *cotton.Context) {
		ctx.String(200, http.StatusOK, "hello v2/a")
	})

	r.Run(":8080")
}
Custom NotFound
func main() {
	r := cotton.NewRouter()
	r.NotFound(func(ctx *cotton.Context) {
		ctx.String(http.StatusNotFound, "page ["+ctx.Request.RequestURI+"] not found")
	})

	r.Run(":8080")
}
Custom group NotFound
func main() {
	r := cotton.NewRouter()
	r.NotFound(func(ctx *cotton.Context) {
		ctx.String(http.StatusNotFound, "page ["+ctx.Request.RequestURI+"] not found")
	})
	g1 := r.Group("/v1/", func(ctx *cotton.Context) {
		fmt.Println("g1 middleware")
	})
	g1.NotFound(func(ctx *cotton.Context) {
		ctx.String(http.StatusNotFound, "group page ["+ctx.Request.RequestURI+"] not found")
	})
	r.Run(":8080")
}
Custom static file
func main() {
	dir, _ := os.Getwd()
	r := cotton.NewRouter()

	r.Use(cotton.Logger())
	// use custom static file
	r.Get("/v1/*file", func(ctx *cotton.Context) {
		file := filepath.Join(dir, ctx.Param("file"))

		http.ServeFile(ctx.Response, ctx.Request, file)
	})

	// use router.StaticFile
	r.StaticFile("/s/", dir, true)  // list dir
	r.StaticFile("/m/", dir, false) // 403 on list dir

	g := r.Group("/g/", func(ctx *cotton.Context) {
		fmt.Printf("status = %d param = %s, abspath = %s\n", ctx.Response.GetStatusCode(), ctx.Param("filepath"), filepath.Join(dir, ctx.Param("filepath")))
	})
	g.StaticFile("/", dir, true)

	r.Run("")
}
Use template

use router.LoadTemplates and ctx.Render; go to example/template for detail

PostForm

use method

  • ctx.GetPostForm
  • ctx.GetPostFormArray
  • ctx.GetPostFormMap
  • ctx.GetPostFormFile
  • ctx.GetPostFormArray
  • ctx.SavePostFormFile

go to example/post/ for detail

Benchmarks

the benchmarks code for cotton be found in the cotton-bench repository, so performance of cotton is good!

   cottonRouter:     90888 bytes
 BeegoMuxRouter:    107952 bytes
     BoneRouter:    100712 bytes
      ChiRouter:     75600 bytes
     HttpRouter:     36016 bytes
       trie-mux:    131568 bytes
      GoRouter1:     83112 bytes
goos: darwin
goarch: amd64
pkg: cottonbench
cpu: Intel(R) Core(TM) i5-8279U CPU @ 2.40GHz
BenchmarkHttpRouterWithGithubAPI-8                 38082             31611 ns/op    13856 B/op        169 allocs/op
BenchmarkCottonRouterWithGithubAPI-8               34648             35496 ns/op        0 B/op          0 allocs/op
BenchmarkBeegoMuxRouterWithGithubAPI-8              9888            120716 ns/op   139056 B/op       1050 allocs/op
BenchmarkBoneRouterWithGithubAPI-8                   640           1869374 ns/op   744018 B/op       8893 allocs/op
BenchmarkTrieMuxRouterWithGithubAPI-8              17448             68756 ns/op    66624 B/op        543 allocs/op
BenchmarkGoRouter1WithGithubAPI-8                     60          18084650 ns/op 14432841 B/op     132968 allocs/op

Author

Acknowledgements

This package is inspired by the following

Documentation

Index

Constants

View Source
const (
	// ModeDebug debug mode
	ModeDebug = iota
	// ModeTest test mode
	ModeTest
	// ModeProduct product mode
	ModeProduct
)
View Source
const BodyBytesKey = "cotton/bbk"

BodyBytesKey indicates a default body bytes key.

Variables

This section is empty.

Functions

func IsDebugging

func IsDebugging() bool

IsDebugging is in debug mode

func SetMode

func SetMode(mode int)

SetMode set mode

func SetWriter added in v0.6.1

func SetWriter(writer io.Writer)

SetWriter set default writer

Types

type Context

type Context struct {
	Request  *http.Request
	Response responseWriter
	// contains filtered or unexported fields
}

Context context for request

func (*Context) Abort

func (ctx *Context) Abort()

Abort fn

func (*Context) ClientIP

func (ctx *Context) ClientIP() string

ClientIP get client ip

func (*Context) Cookie added in v0.4.0

func (ctx *Context) Cookie(key string) (string, error)

Cookie get cookie

func (*Context) Get added in v0.4.0

func (ctx *Context) Get(key string) (interface{}, bool)

Get get value

func (Context) GetAllPostForm added in v0.4.1

func (ctx Context) GetAllPostForm() url.Values

GetAllPostForm get all post form value

func (Context) GetAllQuery added in v0.4.6

func (ctx Context) GetAllQuery() url.Values

GetAllQuery get all query value

func (*Context) GetDefaultQuery

func (ctx *Context) GetDefaultQuery(key, defaultVal string) string

GetDefaultQuery get default query

func (*Context) GetPostForm added in v0.3.0

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

GetPostForm get postform param

func (*Context) GetPostFormArray added in v0.3.0

func (ctx *Context) GetPostFormArray(key string) []string

GetPostFormArray get postform param array

func (*Context) GetPostFormFile added in v0.3.0

func (ctx *Context) GetPostFormFile(key string) *multipart.FileHeader

GetPostFormFile get postform file

func (*Context) GetPostFormFileArray added in v0.3.0

func (ctx *Context) GetPostFormFileArray(key string) (list []*multipart.FileHeader)

GetPostFormFileArray get postform files

func (*Context) GetPostFormMap added in v0.3.0

func (ctx *Context) GetPostFormMap(key string) (dicts map[string]string, exists bool)

GetPostFormMap get postform param map

func (*Context) GetQuery

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

GetQuery for Request.URL.Query().Get

func (*Context) GetQueryArray added in v0.3.0

func (ctx *Context) GetQueryArray(key string) (list []string)

GetQueryArray get query array url?list[]=1&list[]=2

GetQueryArray("list[]")	=> ["1", "2"]

func (*Context) GetQueryMap added in v0.3.0

func (ctx *Context) GetQueryMap(key string) (dicts map[string]string, exists bool)

GetQueryMap get query map

func (*Context) GetRequestHeader added in v0.3.0

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

GetRequestHeader get request header, short for ctx.Request.Header.Get

func (*Context) HTML added in v0.3.0

func (ctx *Context) HTML(code int, html string)

HTML response with html

func (*Context) JSON

func (ctx *Context) JSON(code int, val M)

JSON response with json

func (*Context) Next

func (ctx *Context) Next()

Next fn

func (*Context) NotFound

func (ctx *Context) NotFound()

NotFound for 404

func (*Context) Param

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

Param returns the value of the URL param.

router.GET("/user/:id", func(c *gin.Context) {
    // a GET request to /user/john
    id := c.Param("id") // id == "john"
})

func (*Context) Redirect added in v0.3.0

func (ctx *Context) Redirect(code int, location string)

Redirect short for http.Redirect

func (*Context) Render added in v0.3.0

func (ctx *Context) Render(tplName string, params map[string]interface{})

Render render html template

func (*Context) SavePostFormFile added in v0.3.0

func (ctx *Context) SavePostFormFile(file *multipart.FileHeader, dst string) error

SavePostFormFile save file

func (*Context) Set added in v0.4.0

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

Set set value

func (*Context) ShouldBindBodyWith added in v0.6.0

func (ctx *Context) ShouldBindBodyWith(obj interface{}, bb binding.IBindingBody) (err error)

ShouldBindBodyWith bind body

func (*Context) ShouldBindBodyWithJSON added in v0.6.0

func (ctx *Context) ShouldBindBodyWithJSON(obj interface{}) (err error)

ShouldBindBodyWithJSON bind body with json

func (*Context) ShouldBindWith added in v0.6.0

func (ctx *Context) ShouldBindWith(obj interface{}, b binding.IBinding) error

ShouldBindWith bind

func (*Context) ShouldBindWithJSON added in v0.6.0

func (ctx *Context) ShouldBindWithJSON(obj interface{}) error

ShouldBindWithJSON bind with json

func (*Context) String

func (ctx *Context) String(code int, content string)

response with string

type HandlerFunc

type HandlerFunc func(ctx *Context)

HandlerFunc handler func

func Logger

func Logger() HandlerFunc

Logger logger middleware

func LoggerWidthConf

func LoggerWidthConf(conf LoggerConf) HandlerFunc

LoggerWidthConf get logger with config

func Recover

func Recover() HandlerFunc

Recover recover middleware

func RecoverWithWriter

func RecoverWithWriter(writer io.Writer, handler ...HandlerFuncRecover) HandlerFunc

RecoverWithWriter recover with wirter

type HandlerFuncRecover

type HandlerFuncRecover func(ctx *Context, err interface{})

HandlerFuncRecover handler func for recover

type LoggerConf

type LoggerConf struct {
	Formatter func(param LoggerFormatterParam, ctx *Context) string
	Writer    io.Writer
}

LoggerConf config for logger

type LoggerFormatterParam

type LoggerFormatterParam struct {
	Host       string
	Method     string
	StatusCode int
	TimeStamp  time.Time
	Latency    time.Duration
	ClientIP   string
	Path       string
}

LoggerFormatterParam param to formatter

type M

type M map[string]interface{}

M short for map[string]interface{}

type Router

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

Router router struct

func Default added in v0.4.1

func Default() *Router

Default get default router

func NewRouter

func NewRouter() *Router

NewRouter new router

func (*Router) Delete

func (router *Router) Delete(path string, handler HandlerFunc)

Delete router delete method

func (*Router) Domain added in v0.4.3

func (router *Router) Domain(domain string, handler ...HandlerFunc) *Router

Domain support domain

func (*Router) Get

func (router *Router) Get(path string, handler HandlerFunc)

Get router get method

func (*Router) Group

func (router *Router) Group(path string, handler ...HandlerFunc) *Router

Group get group router

func (*Router) Head

func (router *Router) Head(path string, handler HandlerFunc)

Head router head method

func (*Router) LoadTemplates added in v0.3.0

func (router *Router) LoadTemplates(tplRoot string, funcs map[string]interface{})

LoadTemplates load template files

funcs is functions register to template example:

router.LoadTemplates(root, map[string]interface{}{
	"md5": func(str string) string {
		return str + "_md5"
	},
})

func (*Router) NotFound added in v0.3.0

func (router *Router) NotFound(handler ...HandlerFunc)

NotFound custom NotFoundHandler

func (*Router) Options

func (router *Router) Options(path string, handler HandlerFunc)

Options router options method

func (*Router) Patch

func (router *Router) Patch(path string, handler HandlerFunc)

Patch router patch method

func (*Router) Post

func (router *Router) Post(path string, handler HandlerFunc)

Post router post method

func (*Router) Put

func (router *Router) Put(path string, handler HandlerFunc)

Put router put method

func (*Router) Run

func (router *Router) Run(addr string) error

Run run for http

func (*Router) ServeHTTP

func (router *Router) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP serve http handler

func (*Router) StaticFile added in v0.3.0

func (router *Router) StaticFile(prefix, root string, listDir bool)

StaticFile static file handler

panic when prefix has ':' or '*'; and when open root error

you can use `ctx.Param("filepath")` to get relativepath

func (*Router) Stop added in v0.7.0

func (router *Router) Stop(ctx context.Context) (e error)

Stop stop http service

func (*Router) Use

func (router *Router) Use(handler ...HandlerFunc)

Use use for middleware

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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