Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
刘洪宝 committed Oct 22, 2018
1 parent efa00ee commit 0f55f1e
Show file tree
Hide file tree
Showing 11 changed files with 2,560 additions and 85 deletions.
1 change: 1 addition & 0 deletions .gitignore
@@ -1,2 +1,3 @@
size_coverage.out
vendor/
.idea/
11 changes: 11 additions & 0 deletions README.md
@@ -1,2 +1,13 @@
# bingo-router
基于httprouter的路由模块

// 重写httprouter种的router结构体,添加中间件支持

httprouter 原来是添加一个handle

改为添加一个 Route结构体

使用NewRoute创建

// 使用fasthttp

11 changes: 6 additions & 5 deletions examples/main.go
@@ -1,10 +1,9 @@
package main

import (
"github.com/julienschmidt/httprouter"
"github.com/silsuer/bingo-router"
"net/http"
"fmt"
"github.com/silsuer/bingo-router"
)

// 定义
Expand All @@ -14,14 +13,16 @@ func main() {
// 创建一个路由
// 给路由配置选项
// 配置连接池

//r := httprouter.New()
//r := bingo_router.New()
r := bingo_router.New()
r.GET("/", func(writer http.ResponseWriter, request *http.Request, params httprouter.Params) {

r.GET("/", func(writer http.ResponseWriter, request *http.Request, params bingo_router.Params) {
fmt.Fprint(writer, "hello111")
})

http.ListenAndServe(":8080", r)

//fasthttp.ListenAndServe(":8080",)
//fasthttp.ListenAndServe(":8080", r)
//fasthttp.Serve(":8080",)
}
38 changes: 38 additions & 0 deletions params_go17.go
@@ -0,0 +1,38 @@
// +build go1.7

package bingo_router

import (
"context"
"net/http"
)

type paramsKey struct{}

// ParamsKey is the request context key under which URL params are stored.
//
// This is only present from go 1.7.
var ParamsKey = paramsKey{}

// Handler is an adapter which allows the usage of an http.Handler as a
// request handle. With go 1.7+, the Params will be available in the
// request context under ParamsKey.
func (r *Router) Handler(method, path string, handler http.Handler) {
r.Handle(method, path,
func(w http.ResponseWriter, req *http.Request, p Params) {
ctx := req.Context()
ctx = context.WithValue(ctx, ParamsKey, p)
req = req.WithContext(ctx)
handler.ServeHTTP(w, req)
},
)
}

// ParamsFromContext pulls the URL parameters from a request context,
// or returns nil if none are present.
//
// This is only present from go 1.7.
func ParamsFromContext(ctx context.Context) Params {
p, _ := ctx.Value(ParamsKey).(Params)
return p
}
16 changes: 16 additions & 0 deletions params_legacy.go
@@ -0,0 +1,16 @@
// +build !go1.7

package bingo_router

import "net/http"

// Handler is an adapter which allows the usage of an http.Handler as a
// request handle. With go 1.7+, the Params will be available in the
// request context under ParamsKey.
func (r *Router) Handler(method, path string, handler http.Handler) {
r.Handle(method, path,
func(w http.ResponseWriter, req *http.Request, _ Params) {
handler.ServeHTTP(w, req)
},
)
}
123 changes: 123 additions & 0 deletions path.go
@@ -0,0 +1,123 @@
// Copyright 2013 Julien Schmidt. All rights reserved.
// Based on the path package, Copyright 2009 The Go Authors.
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file.

package bingo_router

// CleanPath is the URL version of path.Clean, it returns a canonical URL path
// for p, eliminating . and .. elements.
//
// The following rules are applied iteratively until no further processing can
// be done:
// 1. Replace multiple slashes with a single slash.
// 2. Eliminate each . path name element (the current directory).
// 3. Eliminate each inner .. path name element (the parent directory)
// along with the non-.. element that precedes it.
// 4. Eliminate .. elements that begin a rooted path:
// that is, replace "/.." by "/" at the beginning of a path.
//
// If the result of this process is an empty string, "/" is returned
func CleanPath(p string) string {
// Turn empty string into "/"
if p == "" {
return "/"
}

n := len(p)
var buf []byte

// Invariants:
// reading from path; r is index of next byte to process.
// writing to buf; w is index of next byte to write.

// path must start with '/'
r := 1
w := 1

if p[0] != '/' {
r = 0
buf = make([]byte, n+1)
buf[0] = '/'
}

trailing := n > 1 && p[n-1] == '/'

// A bit more clunky without a 'lazybuf' like the path package, but the loop
// gets completely inlined (bufApp). So in contrast to the path package this
// loop has no expensive function calls (except 1x make)

for r < n {
switch {
case p[r] == '/':
// empty path element, trailing slash is added after the end
r++

case p[r] == '.' && r+1 == n:
trailing = true
r++

case p[r] == '.' && p[r+1] == '/':
// . element
r += 2

case p[r] == '.' && p[r+1] == '.' && (r+2 == n || p[r+2] == '/'):
// .. element: remove to last /
r += 3

if w > 1 {
// can backtrack
w--

if buf == nil {
for w > 1 && p[w] != '/' {
w--
}
} else {
for w > 1 && buf[w] != '/' {
w--
}
}
}

default:
// real path element.
// add slash if needed
if w > 1 {
bufApp(&buf, p, w, '/')
w++
}

// copy element
for r < n && p[r] != '/' {
bufApp(&buf, p, w, p[r])
w++
r++
}
}
}

// re-append trailing slash
if trailing && w > 1 {
bufApp(&buf, p, w, '/')
w++
}

if buf == nil {
return p[:w]
}
return string(buf[:w])
}

// internal helper to lazily create a buffer if necessary
func bufApp(buf *[]byte, s string, w int, c byte) {
if *buf == nil {
if s[w] == c {
return
}

*buf = make([]byte, len(s))
copy(*buf, s[:w])
}
(*buf)[w] = c
}
93 changes: 93 additions & 0 deletions path_test.go
@@ -0,0 +1,93 @@
// Copyright 2013 Julien Schmidt. All rights reserved.
// Based on the path package, Copyright 2009 The Go Authors.
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file.

package bingo_router

import (
"runtime"
"testing"
)

var cleanTests = []struct {
path, result string
}{
// Already clean
{"/", "/"},
{"/abc", "/abc"},
{"/a/b/c", "/a/b/c"},
{"/abc/", "/abc/"},
{"/a/b/c/", "/a/b/c/"},

// missing root
{"", "/"},
{"a/", "/a/"},
{"abc", "/abc"},
{"abc/def", "/abc/def"},
{"a/b/c", "/a/b/c"},

// Remove doubled slash
{"//", "/"},
{"/abc//", "/abc/"},
{"/abc/def//", "/abc/def/"},
{"/a/b/c//", "/a/b/c/"},
{"/abc//def//ghi", "/abc/def/ghi"},
{"//abc", "/abc"},
{"///abc", "/abc"},
{"//abc//", "/abc/"},

// Remove . elements
{".", "/"},
{"./", "/"},
{"/abc/./def", "/abc/def"},
{"/./abc/def", "/abc/def"},
{"/abc/.", "/abc/"},

// Remove .. elements
{"..", "/"},
{"../", "/"},
{"../../", "/"},
{"../..", "/"},
{"../../abc", "/abc"},
{"/abc/def/ghi/../jkl", "/abc/def/jkl"},
{"/abc/def/../ghi/../jkl", "/abc/jkl"},
{"/abc/def/..", "/abc"},
{"/abc/def/../..", "/"},
{"/abc/def/../../..", "/"},
{"/abc/def/../../..", "/"},
{"/abc/def/../../../ghi/jkl/../../../mno", "/mno"},

// Combinations
{"abc/./../def", "/def"},
{"abc//./../def", "/def"},
{"abc/../../././../def", "/def"},
}

func TestPathClean(t *testing.T) {
for _, test := range cleanTests {
if s := CleanPath(test.path); s != test.result {
t.Errorf("CleanPath(%q) = %q, want %q", test.path, s, test.result)
}
if s := CleanPath(test.result); s != test.result {
t.Errorf("CleanPath(%q) = %q, want %q", test.result, s, test.result)
}
}
}

func TestPathCleanMallocs(t *testing.T) {
if testing.Short() {
t.Skip("skipping malloc count in short mode")
}
if runtime.GOMAXPROCS(0) > 1 {
t.Log("skipping AllocsPerRun checks; GOMAXPROCS>1")
return
}

for _, test := range cleanTests {
allocs := testing.AllocsPerRun(100, func() { CleanPath(test.result) })
if allocs > 0 {
t.Errorf("CleanPath(%q): %v allocs, want zero", test.result, allocs)
}
}
}

0 comments on commit 0f55f1e

Please sign in to comment.