mirror of
https://github.com/labstack/echo.git
synced 2025-01-10 00:28:23 +02:00
Fixes from rebase, Bump Github actions, Fix staticcheck problems
This commit is contained in:
parent
3d2da856e3
commit
7efeffb06b
12
.github/workflows/echo.yml
vendored
12
.github/workflows/echo.yml
vendored
@ -19,7 +19,7 @@ on:
|
|||||||
- '_fixture/**'
|
- '_fixture/**'
|
||||||
- '.github/**'
|
- '.github/**'
|
||||||
- 'codecov.yml'
|
- 'codecov.yml'
|
||||||
workflow_dispatch: # to be able to run workflow manually
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
@ -44,16 +44,18 @@ jobs:
|
|||||||
go-version: ${{ matrix.go }}
|
go-version: ${{ matrix.go }}
|
||||||
|
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: go install golang.org/x/lint/golint@latest
|
run: |
|
||||||
|
go install golang.org/x/lint/golint@latest
|
||||||
|
go install honnef.co/go/tools/cmd/staticcheck@latest
|
||||||
|
|
||||||
- name: Run Tests
|
- name: Run Tests
|
||||||
run: |
|
run: |
|
||||||
golint -set_exit_status ./...
|
golint -set_exit_status ./...
|
||||||
|
staticcheck ./...
|
||||||
go test -race --coverprofile=coverage.coverprofile --covermode=atomic ./...
|
go test -race --coverprofile=coverage.coverprofile --covermode=atomic ./...
|
||||||
|
|
||||||
- name: Upload coverage to Codecov
|
- name: Upload coverage to Codecov
|
||||||
if: success() && matrix.go == 1.18 && matrix.os == 'ubuntu-latest'
|
if: success() && matrix.go == 1.18 && matrix.os == 'ubuntu-latest'
|
||||||
uses: codecov/codecov-action@v2
|
uses: codecov/codecov-action@v1
|
||||||
with:
|
with:
|
||||||
token:
|
token:
|
||||||
fail_ci_if_error: false
|
fail_ci_if_error: false
|
||||||
@ -89,12 +91,10 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
cd previous
|
cd previous
|
||||||
go test -run="-" -bench=".*" -count=8 ./... > benchmark.txt
|
go test -run="-" -bench=".*" -count=8 ./... > benchmark.txt
|
||||||
|
|
||||||
- name: Run Benchmark (New)
|
- name: Run Benchmark (New)
|
||||||
run: |
|
run: |
|
||||||
cd new
|
cd new
|
||||||
go test -run="-" -bench=".*" -count=8 ./... > benchmark.txt
|
go test -run="-" -bench=".*" -count=8 ./... > benchmark.txt
|
||||||
|
|
||||||
- name: Run Benchstat
|
- name: Run Benchstat
|
||||||
run: |
|
run: |
|
||||||
benchstat previous/benchmark.txt new/benchmark.txt
|
benchstat previous/benchmark.txt new/benchmark.txt
|
||||||
|
1
Makefile
1
Makefile
@ -10,6 +10,7 @@ check: lint vet race ## Check project
|
|||||||
|
|
||||||
init:
|
init:
|
||||||
@go install golang.org/x/lint/golint@latest
|
@go install golang.org/x/lint/golint@latest
|
||||||
|
@go install honnef.co/go/tools/cmd/staticcheck@latest
|
||||||
|
|
||||||
lint: ## Lint the files
|
lint: ## Lint the files
|
||||||
@golint -set_exit_status ${PKG_LIST}
|
@golint -set_exit_status ${PKG_LIST}
|
||||||
|
28
echo.go
28
echo.go
@ -49,6 +49,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
@ -709,20 +710,26 @@ func newDefaultFS() *defaultFS {
|
|||||||
dir, _ := os.Getwd()
|
dir, _ := os.Getwd()
|
||||||
return &defaultFS{
|
return &defaultFS{
|
||||||
prefix: dir,
|
prefix: dir,
|
||||||
fs: os.DirFS(dir),
|
fs: nil,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fs defaultFS) Open(name string) (fs.File, error) {
|
func (fs defaultFS) Open(name string) (fs.File, error) {
|
||||||
|
if fs.fs == nil {
|
||||||
|
return os.Open(name)
|
||||||
|
}
|
||||||
return fs.fs.Open(name)
|
return fs.fs.Open(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func subFS(currentFs fs.FS, root string) (fs.FS, error) {
|
func subFS(currentFs fs.FS, root string) (fs.FS, error) {
|
||||||
root = filepath.ToSlash(filepath.Clean(root)) // note: fs.FS operates only with slashes. `ToSlash` is necessary for Windows
|
root = filepath.ToSlash(filepath.Clean(root)) // note: fs.FS operates only with slashes. `ToSlash` is necessary for Windows
|
||||||
if dFS, ok := currentFs.(*defaultFS); ok {
|
if dFS, ok := currentFs.(*defaultFS); ok {
|
||||||
// we need to make exception for `defaultFS` instances as it interprets root prefix differently from fs.FS to
|
// we need to make exception for `defaultFS` instances as it interprets root prefix differently from fs.FS.
|
||||||
// allow cases when root is given as `../somepath` which is not valid for fs.FS
|
// fs.Fs.Open does not like relative paths ("./", "../") and absolute paths at all but prior echo.Filesystem we
|
||||||
|
// were able to use paths like `./myfile.log`, `/etc/hosts` and these would work fine with `os.Open` but not with fs.Fs
|
||||||
|
if isRelativePath(root) {
|
||||||
root = filepath.Join(dFS.prefix, root)
|
root = filepath.Join(dFS.prefix, root)
|
||||||
|
}
|
||||||
return &defaultFS{
|
return &defaultFS{
|
||||||
prefix: root,
|
prefix: root,
|
||||||
fs: os.DirFS(root),
|
fs: os.DirFS(root),
|
||||||
@ -731,6 +738,21 @@ func subFS(currentFs fs.FS, root string) (fs.FS, error) {
|
|||||||
return fs.Sub(currentFs, root)
|
return fs.Sub(currentFs, root)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isRelativePath(path string) bool {
|
||||||
|
if path == "" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if path[0] == '/' {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if runtime.GOOS == "windows" && strings.IndexByte(path, ':') != -1 {
|
||||||
|
// https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file?redirectedfrom=MSDN#file_and_directory_names
|
||||||
|
// https://docs.microsoft.com/en-us/dotnet/standard/io/file-path-formats
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// MustSubFS creates sub FS from current filesystem or panic on failure.
|
// MustSubFS creates sub FS from current filesystem or panic on failure.
|
||||||
// Panic happens when `fsRoot` contains invalid path according to `fs.ValidPath` rules.
|
// Panic happens when `fsRoot` contains invalid path according to `fs.ValidPath` rules.
|
||||||
//
|
//
|
||||||
|
@ -79,9 +79,6 @@ func TestDecompressWithConfig_DefaultConfig_noDecode(t *testing.T) {
|
|||||||
|
|
||||||
func TestDecompressWithConfig_DefaultConfig(t *testing.T) {
|
func TestDecompressWithConfig_DefaultConfig(t *testing.T) {
|
||||||
e := echo.New()
|
e := echo.New()
|
||||||
req := httptest.NewRequest(http.MethodPost, "/", strings.NewReader("test"))
|
|
||||||
rec := httptest.NewRecorder()
|
|
||||||
c := e.NewContext(req, rec)
|
|
||||||
|
|
||||||
h := Decompress()(func(c echo.Context) error {
|
h := Decompress()(func(c echo.Context) error {
|
||||||
c.Response().Write([]byte("test")) // For Content-Type sniffing
|
c.Response().Write([]byte("test")) // For Content-Type sniffing
|
||||||
@ -91,10 +88,10 @@ func TestDecompressWithConfig_DefaultConfig(t *testing.T) {
|
|||||||
// Decompress
|
// Decompress
|
||||||
body := `{"name": "echo"}`
|
body := `{"name": "echo"}`
|
||||||
gz, _ := gzipString(body)
|
gz, _ := gzipString(body)
|
||||||
req = httptest.NewRequest(http.MethodPost, "/", strings.NewReader(string(gz)))
|
req := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(string(gz)))
|
||||||
req.Header.Set(echo.HeaderContentEncoding, GZIPEncoding)
|
req.Header.Set(echo.HeaderContentEncoding, GZIPEncoding)
|
||||||
rec = httptest.NewRecorder()
|
rec := httptest.NewRecorder()
|
||||||
c = e.NewContext(req, rec)
|
c := e.NewContext(req, rec)
|
||||||
|
|
||||||
err := h(c)
|
err := h(c)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
@ -32,7 +32,6 @@ func TestMethodOverride(t *testing.T) {
|
|||||||
|
|
||||||
func TestMethodOverride_formParam(t *testing.T) {
|
func TestMethodOverride_formParam(t *testing.T) {
|
||||||
e := echo.New()
|
e := echo.New()
|
||||||
m := MethodOverride()
|
|
||||||
h := func(c echo.Context) error {
|
h := func(c echo.Context) error {
|
||||||
return c.String(http.StatusOK, "test")
|
return c.String(http.StatusOK, "test")
|
||||||
}
|
}
|
||||||
@ -53,7 +52,6 @@ func TestMethodOverride_formParam(t *testing.T) {
|
|||||||
|
|
||||||
func TestMethodOverride_queryParam(t *testing.T) {
|
func TestMethodOverride_queryParam(t *testing.T) {
|
||||||
e := echo.New()
|
e := echo.New()
|
||||||
m := MethodOverride()
|
|
||||||
h := func(c echo.Context) error {
|
h := func(c echo.Context) error {
|
||||||
return c.String(http.StatusOK, "test")
|
return c.String(http.StatusOK, "test")
|
||||||
}
|
}
|
||||||
|
@ -341,10 +341,9 @@ func TestProxyError(t *testing.T) {
|
|||||||
e := echo.New()
|
e := echo.New()
|
||||||
e.Use(ProxyWithConfig(ProxyConfig{Balancer: rb}))
|
e.Use(ProxyWithConfig(ProxyConfig{Balancer: rb}))
|
||||||
req := httptest.NewRequest(http.MethodGet, "/", nil)
|
req := httptest.NewRequest(http.MethodGet, "/", nil)
|
||||||
rec := httptest.NewRecorder()
|
|
||||||
|
|
||||||
// Remote unreachable
|
// Remote unreachable
|
||||||
rec = httptest.NewRecorder()
|
rec := httptest.NewRecorder()
|
||||||
req.URL.Path = "/api/users"
|
req.URL.Path = "/api/users"
|
||||||
e.ServeHTTP(rec, req)
|
e.ServeHTTP(rec, req)
|
||||||
assert.Equal(t, "/api/users", req.URL.Path)
|
assert.Equal(t, "/api/users", req.URL.Path)
|
||||||
|
@ -56,9 +56,9 @@ func TestRecoverErrAbortHandler(t *testing.T) {
|
|||||||
req := httptest.NewRequest(http.MethodGet, "/", nil)
|
req := httptest.NewRequest(http.MethodGet, "/", nil)
|
||||||
rec := httptest.NewRecorder()
|
rec := httptest.NewRecorder()
|
||||||
c := e.NewContext(req, rec)
|
c := e.NewContext(req, rec)
|
||||||
h := Recover()(echo.HandlerFunc(func(c echo.Context) error {
|
h := Recover()(func(c echo.Context) error {
|
||||||
panic(http.ErrAbortHandler)
|
panic(http.ErrAbortHandler)
|
||||||
}))
|
})
|
||||||
defer func() {
|
defer func() {
|
||||||
r := recover()
|
r := recover()
|
||||||
if r == nil {
|
if r == nil {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package echo
|
package echo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
@ -3227,33 +3226,3 @@ func BenchmarkRouterGooglePlusAPIMisses(b *testing.B) {
|
|||||||
func BenchmarkRouterParamsAndAnyAPI(b *testing.B) {
|
func BenchmarkRouterParamsAndAnyAPI(b *testing.B) {
|
||||||
benchmarkRouterRoutes(b, paramAndAnyAPI, paramAndAnyAPIToFind)
|
benchmarkRouterRoutes(b, paramAndAnyAPI, paramAndAnyAPIToFind)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *node) printTree(pfx string, tail bool) {
|
|
||||||
p := prefix(tail, pfx, "└── ", "├── ")
|
|
||||||
fmt.Printf("%s%s, %p: type=%d, parent=%p, handler=%v, paramNames=%v\n", p, n.prefix, n, n.kind, n.parent, n.methods, n.paramsCount)
|
|
||||||
|
|
||||||
p = prefix(tail, pfx, " ", "│ ")
|
|
||||||
|
|
||||||
children := n.staticChildren
|
|
||||||
l := len(children)
|
|
||||||
|
|
||||||
if n.paramChild != nil {
|
|
||||||
n.paramChild.printTree(p, n.anyChild == nil && l == 0)
|
|
||||||
}
|
|
||||||
if n.anyChild != nil {
|
|
||||||
n.anyChild.printTree(p, l == 0)
|
|
||||||
}
|
|
||||||
for i := 0; i < l-1; i++ {
|
|
||||||
children[i].printTree(p, false)
|
|
||||||
}
|
|
||||||
if l > 0 {
|
|
||||||
children[l-1].printTree(p, true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func prefix(tail bool, p, on, off string) string {
|
|
||||||
if tail {
|
|
||||||
return fmt.Sprintf("%s%s", p, on)
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("%s%s", p, off)
|
|
||||||
}
|
|
||||||
|
@ -696,8 +696,7 @@ func TestStartConfig_WithHidePort(t *testing.T) {
|
|||||||
}
|
}
|
||||||
assert.NoError(t, <-errCh)
|
assert.NoError(t, <-errCh)
|
||||||
|
|
||||||
portMsg := fmt.Sprintf("http(s) server started on")
|
contains := strings.Contains(buf.String(), "http(s) server started on")
|
||||||
contains := strings.Contains(buf.String(), portMsg)
|
|
||||||
if tc.hidePort {
|
if tc.hidePort {
|
||||||
assert.False(t, contains)
|
assert.False(t, contains)
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user