diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml new file mode 100644 index 0000000..79173ae --- /dev/null +++ b/.github/workflows/go.yml @@ -0,0 +1,45 @@ +name: Go +on: + push: + branches: [master] + pull_request: +env: + GOPROXY: "https://proxy.golang.org" + +jobs: + lint: + name: Lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Run golangci-lint + uses: actions-contrib/golangci-lint@v1 + + test: + name: Test + strategy: + matrix: + go-version: [1.13.x, 1.14.x] + platform: [ubuntu-latest, macos-latest, windows-latest] + runs-on: ${{ matrix.platform }} + steps: + - name: Install Go + uses: actions/setup-go@v1 + with: + go-version: ${{ matrix.go-version }} + - name: Checkout code + uses: actions/checkout@v2 + - name: Run unit tests + run: go test -v -race -coverprofile=coverage -covermode=atomic ./... + - name: Upload coverage report to Codecov + uses: codecov/codecov-action@v1.0.6 + with: + file: ./coverage + flags: unittests + - name: Cache downloaded modules + uses: actions/cache@v1 + with: + path: ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 9a0d5cb..0000000 --- a/.travis.yml +++ /dev/null @@ -1,20 +0,0 @@ -sudo: false -language: go -go: - - 1.6.x - - 1.7.x - - 1.8.x - - 1.9.x - - 1.10.x - - 1.11.x - - 1.12.x - -install: skip -script: - - go get golang.org/x/tools/cmd/cover - - go get github.com/smartystreets/goconvey - - mkdir -p $HOME/gopath/src/gopkg.in - - ln -s $HOME/gopath/src/github.com/go-macaron/macaron $HOME/gopath/src/gopkg.in/macaron.v1 - - cd $HOME/gopath/src/gopkg.in/macaron.v1 - - go get -t ./... - - go test -v -cover -race diff --git a/README.md b/README.md index b5d6abc..22856be 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ -Macaron [![Build Status](https://travis-ci.org/go-macaron/macaron.svg?branch=v1)](https://travis-ci.org/go-macaron/macaron) -======================= +# Macaron + +[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/go-macaron/macaron/Go?logo=github&style=for-the-badge)](https://github.com/go-macaron/macaron/actions?query=workflow%3AGo) +[![codecov](https://img.shields.io/codecov/c/github/go-macaron/macaron/master?logo=codecov&style=for-the-badge)](https://codecov.io/gh/go-macaron/macaron) +[![GoDoc](https://img.shields.io/badge/GoDoc-Reference-blue?style=for-the-badge&logo=go)](https://pkg.go.dev/gopkg.in/macaron.v1?tab=doc) +[![Sourcegraph](https://img.shields.io/badge/view%20on-Sourcegraph-brightgreen.svg?style=for-the-badge&logo=sourcegraph)](https://sourcegraph.com/github.com/go-macaron/macaron) ![Macaron Logo](https://raw.githubusercontent.com/go-macaron/macaron/v1/macaronlogo.png) diff --git a/context.go b/context.go index 147e310..be94d35 100644 --- a/context.go +++ b/context.go @@ -31,8 +31,8 @@ import ( "strings" "time" - "github.com/unknwon/com" "github.com/go-macaron/inject" + "github.com/unknwon/com" "golang.org/x/crypto/pbkdf2" ) @@ -193,9 +193,9 @@ func (ctx *Context) parseForm() { contentType := ctx.Req.Header.Get(_CONTENT_TYPE) if (ctx.Req.Method == "POST" || ctx.Req.Method == "PUT") && len(contentType) > 0 && strings.Contains(contentType, "multipart/form-data") { - ctx.Req.ParseMultipartForm(MaxMemory) + _ = ctx.Req.ParseMultipartForm(MaxMemory) } else { - ctx.Req.ParseForm() + _ = ctx.Req.ParseForm() } } diff --git a/context_test.go b/context_test.go index c1417d7..de2ffaa 100644 --- a/context_test.go +++ b/context_test.go @@ -20,6 +20,7 @@ import ( "net/http" "net/http/httptest" "net/url" + "runtime" "sort" "strings" "testing" @@ -176,23 +177,23 @@ func Test_Context(t *testing.T) { m.Get("/:arg/:param/:flag", func(ctx *Context) string { kvs := make([]string, 0, len(ctx.AllParams())) for k, v := range ctx.AllParams() { - kvs = append(kvs, k + "=" + v) + kvs = append(kvs, k+"="+v) } sort.Strings(kvs) return strings.Join(kvs, ",") }) - + resp := httptest.NewRecorder() req, err := http.NewRequest("GET", "/1/2/3", nil) So(err, ShouldBeNil) - m.ServeHTTP(resp,req) + m.ServeHTTP(resp, req) So(resp.Body.String(), ShouldEqual, ":arg=1,:flag=3,:param=2") }) Convey("Get file", func() { m.Post("/getfile", func(ctx *Context) { ctx.Query("") - ctx.GetFile("hi") + _, _, _ = ctx.GetFile("hi") }) resp := httptest.NewRecorder() @@ -311,7 +312,12 @@ func Test_Context(t *testing.T) { req, err = http.NewRequest("GET", "/file3", nil) So(err, ShouldBeNil) m.ServeHTTP(resp, req) - So(resp.Body.String(), ShouldEqual, "open 404.tmpl: no such file or directory\n") + + if runtime.GOOS == "windows" { + So(resp.Body.String(), ShouldEqual, "open 404.tmpl: The system cannot find the file specified.\n") + } else { + So(resp.Body.String(), ShouldEqual, "open 404.tmpl: no such file or directory\n") + } So(resp.Code, ShouldEqual, 500) }) @@ -381,7 +387,7 @@ func Test_Context_Redirect(t *testing.T) { ctx.Redirect("two") So(resp.Code, ShouldEqual, http.StatusFound) - So(resp.HeaderMap["Location"][0], ShouldEqual, "/path/two") + So(resp.Result().Header["Location"][0], ShouldEqual, "/path/two") }) Convey("Context with custom redirect", t, func() { @@ -400,6 +406,6 @@ func Test_Context_Redirect(t *testing.T) { ctx.Redirect("two", 307) So(resp.Code, ShouldEqual, http.StatusTemporaryRedirect) - So(resp.HeaderMap["Location"][0], ShouldEqual, "/path/two") + So(resp.Result().Header["Location"][0], ShouldEqual, "/path/two") }) } diff --git a/macaron_test.go b/macaron_test.go index 5aee0c5..3add528 100644 --- a/macaron_test.go +++ b/macaron_test.go @@ -138,7 +138,7 @@ func Test_Macaron_EarlyWrite(t *testing.T) { m := New() m.Use(func(res http.ResponseWriter) { result += "foobar" - res.Write([]byte("Hello world")) + _, _ = res.Write([]byte("Hello world")) }) m.Use(func() { result += "bat" diff --git a/recovery.go b/recovery.go index ea3bdac..c45c54c 100644 --- a/recovery.go +++ b/recovery.go @@ -153,7 +153,7 @@ func Recovery() Handler { res.WriteHeader(http.StatusInternalServerError) if nil != body { - res.Write(body) + _, _ = res.Write(body) } } }() diff --git a/recovery_test.go b/recovery_test.go index 111d749..239c8d5 100644 --- a/recovery_test.go +++ b/recovery_test.go @@ -46,7 +46,7 @@ func Test_Recovery(t *testing.T) { So(err, ShouldBeNil) m.ServeHTTP(resp, req) So(resp.Code, ShouldEqual, http.StatusInternalServerError) - So(resp.HeaderMap.Get("Content-Type"), ShouldEqual, "text/html") + So(resp.Header().Get("Content-Type"), ShouldEqual, "text/html") So(buf.String(), ShouldNotBeEmpty) }) @@ -68,7 +68,7 @@ func Test_Recovery(t *testing.T) { m.ServeHTTP(resp, req) So(resp2.Code, ShouldEqual, http.StatusInternalServerError) - So(resp2.HeaderMap.Get("Content-Type"), ShouldEqual, "text/html") + So(resp2.Header().Get("Content-Type"), ShouldEqual, "text/html") So(resp2.Body.Len(), ShouldBeGreaterThan, 0) }) } diff --git a/render.go b/render.go index 6f2e93f..04687c4 100644 --- a/render.go +++ b/render.go @@ -36,7 +36,6 @@ import ( const ( _CONTENT_TYPE = "Content-Type" - _CONTENT_LENGTH = "Content-Length" _CONTENT_BINARY = "application/octet-stream" _CONTENT_JSON = "application/json" _CONTENT_HTML = "text/html" @@ -200,7 +199,7 @@ func NewTemplateFileSystem(opt RenderOptions, omitData bool) TplFileSystem { lastDir := dirs[len(dirs)-1] // We still walk the last (original) directory because it's non-sense we load templates not exist in original directory. - if err = filepath.Walk(lastDir, func(path string, info os.FileInfo, err error) error { + if err = filepath.Walk(lastDir, func(path string, info os.FileInfo, _ error) error { r, err := filepath.Rel(lastDir, path) if err != nil { return err @@ -458,9 +457,9 @@ func (r *TplRender) JSON(status int, v interface{}) { r.Header().Set(_CONTENT_TYPE, _CONTENT_JSON+r.CompiledCharset) r.WriteHeader(status) if len(r.Opt.PrefixJSON) > 0 { - r.Write(r.Opt.PrefixJSON) + _, _ = r.Write(r.Opt.PrefixJSON) } - r.Write(result) + _, _ = r.Write(result) } func (r *TplRender) JSONString(v interface{}) (string, error) { @@ -494,9 +493,9 @@ func (r *TplRender) XML(status int, v interface{}) { r.Header().Set(_CONTENT_TYPE, _CONTENT_XML+r.CompiledCharset) r.WriteHeader(status) if len(r.Opt.PrefixXML) > 0 { - r.Write(r.Opt.PrefixXML) + _, _ = r.Write(r.Opt.PrefixXML) } - r.Write(result) + _, _ = r.Write(result) } func (r *TplRender) data(status int, contentType string, v []byte) { @@ -504,7 +503,7 @@ func (r *TplRender) data(status int, contentType string, v []byte) { r.Header().Set(_CONTENT_TYPE, contentType) } r.WriteHeader(status) - r.Write(v) + _, _ = r.Write(v) } func (r *TplRender) RawData(status int, v []byte) { @@ -612,7 +611,7 @@ func (r *TplRender) HTMLString(name string, data interface{}, htmlOpt ...HTMLOpt func (r *TplRender) Error(status int, message ...string) { r.WriteHeader(status) if len(message) > 0 { - r.Write([]byte(message[0])) + _, _ = r.Write([]byte(message[0])) } } diff --git a/render_test.go b/render_test.go index c1890a1..fa46cab 100644 --- a/render_test.go +++ b/render_test.go @@ -20,6 +20,7 @@ import ( "html/template" "net/http" "net/http/httptest" + "runtime" "testing" "time" @@ -574,6 +575,10 @@ func Test_Render_NoRace(t *testing.T) { } func Test_Render_Symlink(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("Skipping testing on Windows") + } + Convey("Render can follow symlinks", t, func() { m := Classic() m.Use(Renderer(RenderOptions{ @@ -661,7 +666,7 @@ func Test_dummyRender(t *testing.T) { }) m.Get("/jsonstring", func(ctx *Context) { defer shouldPanic() - ctx.JSONString(nil) + _, _ = ctx.JSONString(nil) }) m.Get("/rawdata", func(ctx *Context) { defer shouldPanic() @@ -681,19 +686,19 @@ func Test_dummyRender(t *testing.T) { }) m.Get("/htmlsetstring", func(ctx *Context) { defer shouldPanic() - ctx.Render.HTMLSetString("", "", nil) + _, _ = ctx.Render.HTMLSetString("", "", nil) }) m.Get("/htmlstring", func(ctx *Context) { defer shouldPanic() - ctx.Render.HTMLString("", nil) + _, _ = ctx.Render.HTMLString("", nil) }) m.Get("/htmlsetbytes", func(ctx *Context) { defer shouldPanic() - ctx.Render.HTMLSetBytes("", "", nil) + _, _ = ctx.Render.HTMLSetBytes("", "", nil) }) m.Get("/htmlbytes", func(ctx *Context) { defer shouldPanic() - ctx.Render.HTMLBytes("", nil) + _, _ = ctx.Render.HTMLBytes("", nil) }) m.Get("/xml", func(ctx *Context) { defer shouldPanic() diff --git a/response_writer.go b/response_writer.go index 59485d4..eeb35f6 100644 --- a/response_writer.go +++ b/response_writer.go @@ -17,7 +17,6 @@ package macaron import ( "bufio" "errors" - "fmt" "net" "net/http" ) @@ -98,6 +97,7 @@ func (rw *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { return hijacker.Hijack() } +//nolint func (rw *responseWriter) CloseNotify() <-chan bool { return rw.ResponseWriter.(http.CloseNotifier).CloseNotify() } diff --git a/response_writer_test.go b/response_writer_test.go index 4ce2d11..c5e7b2e 100644 --- a/response_writer_test.go +++ b/response_writer_test.go @@ -68,7 +68,7 @@ func Test_ResponseWriter(t *testing.T) { Convey("Write string to response writer", t, func() { resp := httptest.NewRecorder() rw := NewResponseWriter("GET", resp) - rw.Write([]byte("Hello world")) + _, _ = rw.Write([]byte("Hello world")) So(resp.Code, ShouldEqual, rw.Status()) So(resp.Body.String(), ShouldEqual, "Hello world") @@ -80,8 +80,8 @@ func Test_ResponseWriter(t *testing.T) { Convey("Write strings to response writer", t, func() { resp := httptest.NewRecorder() rw := NewResponseWriter("GET", resp) - rw.Write([]byte("Hello world")) - rw.Write([]byte("foo bar bat baz")) + _, _ = rw.Write([]byte("Hello world")) + _, _ = rw.Write([]byte("foo bar bat baz")) So(resp.Code, ShouldEqual, rw.Status()) So(resp.Body.String(), ShouldEqual, "Hello worldfoo bar bat baz") @@ -143,7 +143,7 @@ func Test_ResponseWriter(t *testing.T) { resp := newCloseNotifyingRecorder() rw := NewResponseWriter("GET", resp) closed := false - notifier := rw.(http.CloseNotifier).CloseNotify() + notifier := rw.(http.CloseNotifier).CloseNotify() //nolint resp.close() select { case <-notifier: @@ -172,7 +172,7 @@ func Test_ResponseWriter(t *testing.T) { for i := 0; i < 2; i++ { time.Sleep(10 * time.Millisecond) - io.WriteString(w, "data: Hello\n\n") + _, _ = io.WriteString(w, "data: Hello\n\n") f.Flush() } }) diff --git a/return_handler.go b/return_handler.go index db6eec3..33b7fd2 100644 --- a/return_handler.go +++ b/return_handler.go @@ -68,9 +68,9 @@ func defaultReturnHandler() ReturnHandler { respVal = respVal.Elem() } if isByteSlice(respVal) { - resp.Write(respVal.Bytes()) + _, _ = resp.Write(respVal.Bytes()) } else { - resp.Write([]byte(respVal.String())) + _, _ = resp.Write([]byte(respVal.String())) } } } diff --git a/router_test.go b/router_test.go index 0dc596d..3e38b98 100644 --- a/router_test.go +++ b/router_test.go @@ -321,7 +321,7 @@ func Test_Router_InternalServerError(t *testing.T) { }) m.InternalServerError(func(rw http.ResponseWriter, err error) { rw.WriteHeader(500) - rw.Write([]byte(err.Error())) + _, _ = rw.Write([]byte(err.Error())) }) resp := httptest.NewRecorder() req, err := http.NewRequest("GET", "/", nil) diff --git a/static_test.go b/static_test.go index 33bc413..3ee7950 100644 --- a/static_test.go +++ b/static_test.go @@ -69,7 +69,7 @@ func Test_Static(t *testing.T) { Root = os.TempDir() f, err := ioutil.TempFile(Root, "static_content") So(err, ShouldBeNil) - f.WriteString("Expected Content") + _, _ = f.WriteString("Expected Content") f.Close() m := New()