Skip to content

Commit

Permalink
Showing 79 changed files with 750 additions and 5,650 deletions.
701 changes: 699 additions & 2 deletions README.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions bench_test.go
Original file line number Diff line number Diff line change
@@ -51,15 +51,15 @@ func BenchmarkContextNewMap(b *testing.B) {

func BenchmarkConvertServerTiming(b *testing.B) {
b.ReportAllocs()
traceInfos := make([]*TraceInfo, 0)
traceInfos := make(TraceInfos, 0)
for _, name := range strings.Split("0123456789", "") {
traceInfos = append(traceInfos, &TraceInfo{
Name: name,
Duration: time.Microsecond * 100,
})
}
for i := 0; i < b.N; i++ {
ConvertToServerTiming(traceInfos, "cod-")
traceInfos.ServerTiming("cod-")
}
}

106 changes: 34 additions & 72 deletions cod.go
Original file line number Diff line number Diff line change
@@ -16,16 +16,12 @@ package cod

import (
"bytes"
"crypto/sha1"
"encoding/base64"
"fmt"
"net"
"net/http"
"reflect"
"regexp"
"runtime"
"strconv"
"strings"
"sync"
"sync/atomic"
"time"
@@ -43,13 +39,9 @@ const (
StatusClosed
)

var (
camelCaseReg = regexp.MustCompile(`[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+`)
)

type (
// M alias
M map[string]interface{}
// Skipper check for skip middleware
Skipper func(c *Context) bool
// RouterInfo router's info
RouterInfo struct {
Method string `json:"method,omitempty"`
@@ -58,19 +50,22 @@ type (
// Cod web framework instance
Cod struct {
// status of cod
status int32
Server *http.Server
Router *httprouter.Router
status int32
// Server http server
Server *http.Server
// Router http router
Router *httprouter.Router
// Routers all router infos
Routers []*RouterInfo
// Middlewares middleware function
Middlewares []Handler
errorListeners []ErrorListener
traceListeners []TraceListener
// ErrorHandler error handler
// ErrorHandler set the function for error handler
ErrorHandler ErrorHandler
// NotFoundHandler not found handler
// NotFoundHandler set the function for not found handler
NotFoundHandler http.HandlerFunc
// GenerateID generate id function
// GenerateID generate id function, will use it for create id for context
GenerateID GenerateID
// EnableTrace enable trace
EnableTrace bool
@@ -85,6 +80,8 @@ type (
Name string `json:"name,omitempty"`
Duration time.Duration `json:"duration,omitempty"`
}
// TraceInfos trace infos
TraceInfos []*TraceInfo
// Router router
Router struct {
Method string `json:"method,omitempty"`
@@ -96,7 +93,6 @@ type (
Path string
HandlerList []Handler
routers []*Router
Cod *Cod
}
// ErrorHandler error handle function
ErrorHandler func(*Context, error)
@@ -107,7 +103,7 @@ type (
// ErrorListener error listener function
ErrorListener func(*Context, error)
// TraceListener trace listener
TraceListener func(*Context, []*TraceInfo)
TraceListener func(*Context, TraceInfos)
)

// New create a cod instance
@@ -184,7 +180,7 @@ func (d *Cod) GracefulClose(delay time.Duration) error {
atomic.StoreInt32(&d.status, StatusClosing)
time.Sleep(delay)
atomic.StoreInt32(&d.status, StatusClosed)
return d.Server.Close()
return d.Close()
}

// GetStatus get status of cod
@@ -253,9 +249,9 @@ func (d *Cod) Handle(method, path string, handlerList ...Handler) {
maxMid := len(mids)
maxNext := maxMid + len(handlerList)
index := -1
var traceInfos []*TraceInfo
var traceInfos TraceInfos
if d.EnableTrace {
traceInfos = make([]*TraceInfo, 0, maxNext)
traceInfos = make(TraceInfos, 0, maxNext)
}
c.Next = func() error {
index++
@@ -285,17 +281,20 @@ func (d *Cod) Handle(method, path string, handlerList ...Handler) {
if traceInfos != nil {
d.EmitTrace(c, traceInfos)
}
if err != nil {
d.EmitError(c, err)
d.Error(c, err)
} else if !c.Committed {
if c.StatusCode != 0 {
resp.WriteHeader(c.StatusCode)
}
if c.BodyBuffer != nil {
_, responseErr := resp.Write(c.BodyBuffer.Bytes())
if responseErr != nil {
d.EmitError(c, responseErr)
// 如果已commit 表示返回数据已设置,无需处理
if !c.Committed {
if err != nil {
d.EmitError(c, err)
d.Error(c, err)
} else {
if c.StatusCode != 0 {
resp.WriteHeader(c.StatusCode)
}
if c.BodyBuffer != nil {
_, responseErr := resp.Write(c.BodyBuffer.Bytes())
if responseErr != nil {
d.EmitError(c, responseErr)
}
}
}
}
@@ -403,7 +402,7 @@ func (d *Cod) OnError(ln ErrorListener) {
}

// EmitTrace emit trace
func (d *Cod) EmitTrace(c *Context, infos []*TraceInfo) {
func (d *Cod) EmitTrace(c *Context, infos TraceInfos) {
lns := d.traceListeners
for _, ln := range lns {
ln(c, infos)
@@ -509,18 +508,6 @@ func (g *Group) ALL(path string, handlerList ...Handler) {
}
}

// GenerateETag generate eTag
func GenerateETag(buf []byte) string {
size := len(buf)
if size == 0 {
return "\"0-2jmj7l5rSw0yVb_vlWAYkK_YBwk=\""
}
h := sha1.New()
h.Write(buf)
hash := base64.URLEncoding.EncodeToString(h.Sum(nil))
return fmt.Sprintf("\"%x-%s\"", size, hash)
}

func getMs(ns int) string {
microSecond := int(time.Microsecond)
milliSecond := int(time.Millisecond)
@@ -546,8 +533,8 @@ func getMs(ns int) string {
return prefix + "." + strconv.Itoa(offset/unit)
}

// ConvertToServerTiming convert trace infos to server timing
func ConvertToServerTiming(traceInfos []*TraceInfo, prefix string) []byte {
// ServerTiming trace infos to server timing
func (traceInfos TraceInfos) ServerTiming(prefix string) []byte {
size := len(traceInfos)
if size == 0 {
return nil
@@ -573,28 +560,3 @@ func ConvertToServerTiming(traceInfos []*TraceInfo, prefix string) []byte {
}
return bytes.Join(timings, []byte(","))
}

// GenerateRewrites generate rewrites
func GenerateRewrites(rewrites []string) (m map[*regexp.Regexp]string, err error) {
if len(rewrites) == 0 {
return
}
m = make(map[*regexp.Regexp]string)

for _, value := range rewrites {
arr := strings.Split(value, ":")
if len(arr) != 2 {
continue
}
k := arr[0]
v := arr[1]
k = strings.Replace(k, "*", "(\\S*)", -1)
reg, e := regexp.Compile(k)
if e != nil {
err = e
break
}
m[reg] = v
}
return
}
33 changes: 4 additions & 29 deletions cod_test.go
Original file line number Diff line number Diff line change
@@ -378,7 +378,7 @@ func TestOnTrace(t *testing.T) {
d := New()
d.EnableTrace = true
done := false
d.OnTrace(func(c *Context, infos []*TraceInfo) {
d.OnTrace(func(c *Context, infos TraceInfos) {
if len(infos) != 2 {
t.Fatalf("trace count should be 2")
}
@@ -416,17 +416,6 @@ func TestGenerateID(t *testing.T) {
d.ServeHTTP(resp, req)
}

func TestGenerateETag(t *testing.T) {
eTag := GenerateETag([]byte(""))
if eTag != `"0-2jmj7l5rSw0yVb_vlWAYkK_YBwk="` {
t.Fatalf("gen nil byte eTag fail")
}
eTag = GenerateETag([]byte("abc"))
if eTag != `"3-qZk-NkcGgWq6PiVxeFDCbJzQ2J0="` {
t.Fatalf("gen abc eTag fail")
}
}

func TestGetSetFunctionName(t *testing.T) {
fn := func() {}
d := New()
@@ -438,7 +427,7 @@ func TestGetSetFunctionName(t *testing.T) {
}

func TestConvertToServerTiming(t *testing.T) {
traceInfos := make([]*TraceInfo, 0)
traceInfos := make(TraceInfos, 0)

t.Run("get ms", func(t *testing.T) {
if getMs(10) != "0" ||
@@ -448,7 +437,7 @@ func TestConvertToServerTiming(t *testing.T) {
})

t.Run("empty trace infos", func(t *testing.T) {
if ConvertToServerTiming(traceInfos, "") != nil {
if traceInfos.ServerTiming("") != nil {
t.Fatalf("it should be nil")
}
})
@@ -461,26 +450,12 @@ func TestConvertToServerTiming(t *testing.T) {
Name: "b",
Duration: time.Millisecond + time.Microsecond,
})
if string(ConvertToServerTiming(traceInfos, "cod-")) != `cod-0;dur=0.01;desc="a",cod-1;dur=1;desc="b"` {
if string(traceInfos.ServerTiming("cod-")) != `cod-0;dur=0.01;desc="a",cod-1;dur=1;desc="b"` {
t.Fatalf("convert server timing fail")
}
})
}

func TestGenerateRewrites(t *testing.T) {
arr := []string{
"/api/*:/$1",
"/images/*:/static/$1",
}
regs, err := GenerateRewrites(arr)
if err != nil {
t.Fatalf("generate rewrites fail, %v", err)
}
if len(regs) != 2 {
t.Fatalf("generate rewriters fail")
}
}

func TestGracefulClose(t *testing.T) {
d := New()
t.Run("running 404", func(t *testing.T) {
18 changes: 10 additions & 8 deletions context.go
Original file line number Diff line number Diff line change
@@ -95,13 +95,12 @@ func (c *Context) RealIP() string {
if c.realIP != "" {
return c.realIP
}
h := c.Request.Header
ip := h.Get(HeaderXForwardedFor)
ip := c.GetRequestHeader(HeaderXForwardedFor)
if ip != "" {
c.realIP = strings.TrimSpace(strings.Split(ip, ",")[0])
return c.realIP
}
c.realIP = h.Get(HeaderXRealIp)
c.realIP = c.GetRequestHeader(HeaderXRealIp)
if c.realIP != "" {
return c.realIP
}
@@ -234,18 +233,21 @@ func (c *Context) SignedCookie(name string) (cookie *http.Cookie, err error) {
if err != nil {
return
}
sc, err := c.Cookie(name + sig)
if err != nil {
return
}
keys := c.getKeys()
// 如果没有配置keys,则认为cookie符合
if len(keys) == 0 {
return
}

sc, err := c.Cookie(name + sig)
if err != nil {
return
}
kg := keygrip.New(keys)
// 如果校验不符合,则返回空
// 如果校验不符合,则与查找不到cookie 一样
if !kg.Verify([]byte(cookie.Value), []byte(sc.Value)) {
cookie = nil
err = http.ErrNoCookie
}
return
}
2 changes: 1 addition & 1 deletion context_test.go
Original file line number Diff line number Diff line change
@@ -281,7 +281,7 @@ func TestSignedCookie(t *testing.T) {
c := NewContext(resp, req)
c.cod = cod
cookie, err := c.SignedCookie("a")
if err != nil {
if err != http.ErrNoCookie {
t.Fatalf("get signed cookie fail, %v", err)
}
if cookie != nil {
20 changes: 0 additions & 20 deletions docs/basic_auth.md

This file was deleted.

31 changes: 0 additions & 31 deletions docs/body_parser.md

This file was deleted.

350 changes: 0 additions & 350 deletions docs/cod.md

This file was deleted.

45 changes: 0 additions & 45 deletions docs/compress.md

This file was deleted.

48 changes: 0 additions & 48 deletions docs/concurrent_limiter.md

This file was deleted.

356 changes: 0 additions & 356 deletions docs/context.md

This file was deleted.

15 changes: 0 additions & 15 deletions docs/error_handler.md

This file was deleted.

16 changes: 0 additions & 16 deletions docs/etag.md

This file was deleted.

17 changes: 0 additions & 17 deletions docs/fresh.md

This file was deleted.

39 changes: 0 additions & 39 deletions docs/json_picker.md

This file was deleted.

33 changes: 0 additions & 33 deletions docs/middleware.md

This file was deleted.

33 changes: 0 additions & 33 deletions docs/proxy.md

This file was deleted.

16 changes: 0 additions & 16 deletions docs/recover.md

This file was deleted.

24 changes: 0 additions & 24 deletions docs/responder.md

This file was deleted.

29 changes: 0 additions & 29 deletions docs/static_file.md

This file was deleted.

33 changes: 0 additions & 33 deletions docs/stats.md

This file was deleted.

22 changes: 0 additions & 22 deletions docs/tracker.md

This file was deleted.

1 change: 0 additions & 1 deletion examples/basic/go.mod

This file was deleted.

59 changes: 0 additions & 59 deletions examples/basic/main.go

This file was deleted.

1 change: 0 additions & 1 deletion examples/basic_auth/go.mod

This file was deleted.

53 changes: 0 additions & 53 deletions examples/basic_auth/main.go

This file was deleted.

1 change: 0 additions & 1 deletion examples/body_parser/go.mod

This file was deleted.

40 changes: 0 additions & 40 deletions examples/body_parser/main.go

This file was deleted.

1 change: 0 additions & 1 deletion examples/compress/go.mod

This file was deleted.

46 changes: 0 additions & 46 deletions examples/compress/main.go

This file was deleted.

1 change: 0 additions & 1 deletion examples/concurrent_limiter/go.mod

This file was deleted.

72 changes: 0 additions & 72 deletions examples/concurrent_limiter/main.go

This file was deleted.

1 change: 0 additions & 1 deletion examples/execution_order/go.mod

This file was deleted.

43 changes: 0 additions & 43 deletions examples/execution_order/main.go

This file was deleted.

1 change: 0 additions & 1 deletion examples/json_picker/go.mod

This file was deleted.

49 changes: 0 additions & 49 deletions examples/json_picker/main.go

This file was deleted.

1 change: 0 additions & 1 deletion examples/proxy/go.mod

This file was deleted.

46 changes: 0 additions & 46 deletions examples/proxy/main.go

This file was deleted.

2 changes: 0 additions & 2 deletions examples/static_serve/go.mod

This file was deleted.

53 changes: 0 additions & 53 deletions examples/static_serve/main.go

This file was deleted.

1 change: 0 additions & 1 deletion examples/stats/go.mod

This file was deleted.

41 changes: 0 additions & 41 deletions examples/stats/main.go

This file was deleted.

1 change: 0 additions & 1 deletion examples/tracker/go.mod

This file was deleted.

53 changes: 0 additions & 53 deletions examples/tracker/main.go

This file was deleted.

5 changes: 0 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
module github.com/vicanso/cod

require (
github.com/json-iterator/go v1.1.5
github.com/julienschmidt/httprouter v1.2.0
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.1 // indirect
github.com/vicanso/fresh v0.1.1
github.com/vicanso/hes v0.1.3
github.com/vicanso/keygrip v0.1.0
github.com/vicanso/superjson v0.0.4
)
14 changes: 0 additions & 14 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,20 +1,6 @@
github.com/json-iterator/go v1.1.5 h1:gL2yXlmiIo4+t+y32d4WGwOjKGYcGOuyrg46vadswDE=
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/julienschmidt/httprouter v1.2.0 h1:TDTW5Yz1mjftljbcKqRcrYhd4XeOoI98t+9HbQbYf7g=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/tidwall/gjson v1.1.5 h1:QysILxBeUEY3GTLA0fQVgkQG1zme8NxGvhh2SSqWNwI=
github.com/tidwall/gjson v1.1.5/go.mod h1:c/nTNbUr0E0OrXEhq1pwa8iEgc2DOt4ZZqAt1HtCkPA=
github.com/tidwall/match v1.0.1 h1:PnKP62LPNxHKTwvHHZZzdOAOCtsJTjo6dZLCwpKm5xc=
github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E=
github.com/vicanso/fresh v0.1.1 h1:L3UX/g2uZ4pNFzjc7+PyeYOlIAs2/yUfhcFnK7E+JQU=
github.com/vicanso/fresh v0.1.1/go.mod h1:gr1RKSFxQ1OnQHzUMBHCigifni7KrXveJjWCTlPjICA=
github.com/vicanso/hes v0.1.3 h1:3txPJL+J+xBRhIotkK3XKNbmBz+JXJ1knmGM0L+Qe4k=
github.com/vicanso/hes v0.1.3/go.mod h1:bG0UJ3EihDKObFcLLwJYjxHHr9saFllsFcepyDIvFlo=
github.com/vicanso/keygrip v0.1.0 h1:/zYzoVIbREAvaxSM7bo3/oSXuuYztaP71dPBfhRoNkM=
github.com/vicanso/keygrip v0.1.0/go.mod h1:cI05iOjY00NJ7oH2Z9Zdm9eJPUkpoex3XnEubK78nho=
github.com/vicanso/superjson v0.0.4 h1:k6PswKdSdEsuZ37g8UynYur+MMkkibBQVEYTOHNIuzA=
github.com/vicanso/superjson v0.0.4/go.mod h1:JWCSeF6/wImFZx+8lPyfeHj1EkbeuLtAZg6fR9sRBpM=
113 changes: 0 additions & 113 deletions middleware/basic_auth.go

This file was deleted.

137 changes: 0 additions & 137 deletions middleware/basic_auth_test.go

This file was deleted.

146 changes: 0 additions & 146 deletions middleware/body_parser.go

This file was deleted.

240 changes: 0 additions & 240 deletions middleware/body_parser_test.go

This file was deleted.

147 changes: 0 additions & 147 deletions middleware/compress.go

This file was deleted.

236 changes: 0 additions & 236 deletions middleware/compress_test.go

This file was deleted.

147 changes: 0 additions & 147 deletions middleware/concurrent_limiter.go

This file was deleted.

Loading

0 comments on commit c0fc4fe

Please sign in to comment.