pax_global_header00006660000000000000000000000064136051304440014512gustar00rootroot0000000000000052 comment=b847c2f2bec9d7a31e7d9bd67ce07a0213f12d48 gofight-2.1.2/000077500000000000000000000000001360513044400131435ustar00rootroot00000000000000gofight-2.1.2/.drone.yml000066400000000000000000000015431360513044400150560ustar00rootroot00000000000000kind: pipeline name: lint clone: depth: 1 steps: - name: testing image: golang:1.13 pull: true commands: - make vet - make lint - make embedmd-check - make misspell-check trigger: event: - push - pull_request --- kind: pipeline name: testing clone: depth: 1 steps: - name: testing image: golang:1.13 pull: true commands: - make test - name: codecov image: robertstettner/drone-codecov settings: token: from_secret: codecov_token trigger: event: - push --- kind: pipeline name: notification clone: disable: true steps: - name: discord pull: always image: appleboy/drone-discord environment: DISCORD_WEBHOOK_ID: from_secret: discord_webhook_id DISCORD_WEBHOOK_TOKEN: from_secret: discord_webhook_token when: status: - success - failure depends_on: - testing - lint gofight-2.1.2/.editorconfig000066400000000000000000000016311360513044400156210ustar00rootroot00000000000000# unifying the coding style for different editors and IDEs => editorconfig.org ; indicate this is the root of the project root = true ########################################################### ; common ########################################################### [*] charset = utf-8 end_of_line = LF insert_final_newline = true trim_trailing_whitespace = true indent_style = space indent_size = 2 ########################################################### ; make ########################################################### [Makefile] indent_style = tab [makefile] indent_style = tab ########################################################### ; markdown ########################################################### [*.md] trim_trailing_whitespace = false ########################################################### ; golang ########################################################### [*.go] indent_style = tabgofight-2.1.2/.gitignore000066400000000000000000000004301360513044400151300ustar00rootroot00000000000000# Compiled Object files, Static and Dynamic libs (Shared Objects) *.o *.a *.so # Folders _obj _test # Architecture specific extensions/prefixes *.[568vq] [568vq].out *.cgo1.go *.cgo2.c _cgo_defun.c _cgo_gotypes.go _cgo_export.* _testmain.go *.exe *.test *.prof coverage.txt gofight-2.1.2/.revive.toml000066400000000000000000000007601360513044400154210ustar00rootroot00000000000000ignoreGeneratedHeader = false severity = "warning" confidence = 0.8 errorCode = 1 warningCode = 1 [rule.blank-imports] [rule.context-as-argument] [rule.context-keys-type] [rule.dot-imports] [rule.error-return] [rule.error-strings] [rule.error-naming] [rule.exported] [rule.if-return] [rule.increment-decrement] [rule.var-naming] [rule.var-declaration] [rule.package-comments] [rule.range] [rule.receiver-naming] [rule.time-naming] [rule.unexported-return] [rule.indent-error-flow] [rule.errorf] gofight-2.1.2/LICENSE000066400000000000000000000020631360513044400141510ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2016 Bo-Yi Wu Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. gofight-2.1.2/Makefile000066400000000000000000000024401360513044400146030ustar00rootroot00000000000000.PHONY: test GO ?= go GOFMT ?= gofmt "-s" PACKAGES ?= $(shell $(GO) list ./...) GOFILES := $(shell find . -name "*.go" -type f) install-embedmd: @hash embedmd > /dev/null 2>&1; if [ $$? -ne 0 ]; then \ $(GO) get -u github.com/campoy/embedmd; \ fi embedmd-check: install-embedmd embedmd -d *.md embedmd: install-embedmd embedmd -w *.md .PHONY: fmt fmt: $(GOFMT) -w $(GOFILES) .PHONY: fmt-check fmt-check: @diff=$$($(GOFMT) -d $(GOFILES)); \ if [ -n "$$diff" ]; then \ echo "Please run 'make fmt' and commit the result:"; \ echo "$${diff}"; \ exit 1; \ fi; test: fmt-check @$(GO) test -v -cover -coverprofile coverage.txt ./... && echo "\n==>\033[32m Ok\033[m\n" || exit 1 vet: $(GO) vet ./... lint: @hash revive > /dev/null 2>&1; if [ $$? -ne 0 ]; then \ $(GO) get -u github.com/mgechev/revive; \ fi revive -config .revive.toml ./... || exit 1 .PHONY: misspell-check misspell-check: @hash misspell > /dev/null 2>&1; if [ $$? -ne 0 ]; then \ $(GO) get -u github.com/client9/misspell/cmd/misspell; \ fi misspell -error ./... .PHONY: misspell misspell: @hash misspell > /dev/null 2>&1; if [ $$? -ne 0 ]; then \ $(GO) get -u github.com/client9/misspell/cmd/misspell; \ fi misspell -w $(GOFILES) clean: $(GO) clean -modcache -cache -i find . -name "coverage.txt" -delete gofight-2.1.2/README.md000066400000000000000000000240141360513044400144230ustar00rootroot00000000000000# Gofight [![GoDoc](https://godoc.org/github.com/appleboy/gofight?status.svg)](https://godoc.org/github.com/appleboy/gofight) [![Build Status](https://cloud.drone.io/api/badges/appleboy/gofight/status.svg)](https://cloud.drone.io/appleboy/gofight) [![Go Report Card](https://goreportcard.com/badge/github.com/appleboy/gofight)](https://goreportcard.com/report/github.com/appleboy/gofight) [![codebeat badge](https://codebeat.co/badges/4d8b58ae-67ec-469e-bde6-be3dd336b30d)](https://codebeat.co/projects/github-com-appleboy-gofight) [![codecov](https://codecov.io/gh/appleboy/gofight/branch/master/graph/badge.svg)](https://codecov.io/gh/appleboy/gofight) [![Sourcegraph](https://sourcegraph.com/github.com/appleboy/gofight/-/badge.svg)](https://sourcegraph.com/github.com/appleboy/gofight?badge) API Handler Testing for Golang Web framework. ## Support Framework * [x] [Http Handler](https://golang.org/pkg/net/http/) Golang package http provides HTTP client and server implementations. * [x] [Gin](https://github.com/gin-gonic/gin) * [x] [Echo](https://github.com/labstack/echo) support [v3.0.0](https://github.com/labstack/echo/releases/tag/v3.0.0) up * [x] [Mux](https://github.com/gorilla/mux) * [x] [HttpRouter](https://github.com/julienschmidt/httprouter) * [x] [Pat](https://github.com/gorilla/pat) * [x] [beego](https://github.com/astaxie/beego) ## Usage Download this package. ```bash $ go get github.com/appleboy/gofight/v2 ``` To import this package, add the following line to your code: ```go import "github.com/appleboy/gofight/v2" ``` ## Usage The following is basic testing example. Main Program: ```go package main import ( "io" "net/http" ) func BasicHelloHandler(w http.ResponseWriter, r *http.Request) { io.WriteString(w, "Hello World") } func BasicEngine() http.Handler { mux := http.NewServeMux() mux.HandleFunc("/", BasicHelloHandler) return mux } ``` Testing: ```go package main import ( "net/http" "testing" "github.com/appleboy/gofight/v2" "github.com/stretchr/testify/assert" ) func TestBasicHelloWorld(t *testing.T) { r := gofight.New() r.GET("/"). // turn on the debug mode. SetDebug(true). Run(BasicEngine(), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) { assert.Equal(t, "Hello World", r.Body.String()) assert.Equal(t, http.StatusOK, r.Code) }) } ``` ### Set Header You can add custom header via `SetHeader` func. ```go func TestBasicHelloWorld(t *testing.T) { r := gofight.New() version := "0.0.1" r.GET("/"). // turn on the debug mode. SetDebug(true). SetHeader(gofight.H{ "X-Version": version, }). Run(BasicEngine(), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) { assert.Equal(t, version, rq.Header.Get("X-Version")) assert.Equal(t, "Hello World", r.Body.String()) assert.Equal(t, http.StatusOK, r.Code) }) } ``` ### POST FORM Data Using `SetForm` to generate form data. ```go func TestPostFormData(t *testing.T) { r := gofight.New() r.POST("/form"). SetForm(gofight.H{ "a": "1", "b": "2", }). Run(BasicEngine(), func(r HTTPResponse, rq HTTPRequest) { data := []byte(r.Body.String()) a, _ := jsonparser.GetString(data, "a") b, _ := jsonparser.GetString(data, "b") assert.Equal(t, "1", a) assert.Equal(t, "2", b) assert.Equal(t, http.StatusOK, r.Code) }) } ``` ### POST JSON Data Using `SetJSON` to generate JSON data. ```go func TestPostJSONData(t *testing.T) { r := gofight.New() r.POST("/json"). SetJSON(gofight.D{ "a": 1, "b": 2, }). Run(BasicEngine, func(r HTTPResponse, rq HTTPRequest) { data := []byte(r.Body.String()) a, _ := jsonparser.GetInt(data, "a") b, _ := jsonparser.GetInt(data, "b") assert.Equal(t, 1, int(a)) assert.Equal(t, 2, int(b)) assert.Equal(t, http.StatusOK, r.Code) assert.Equal(t, "application/json; charset=utf-8", r.HeaderMap.Get("Content-Type")) }) } ``` ### POST RAW Data Using `SetBody` to generate raw data. ```go func TestPostRawData(t *testing.T) { r := gofight.New() r.POST("/raw"). SetBody("a=1&b=1"). Run(BasicEngine, func(r HTTPResponse, rq HTTPRequest) { data := []byte(r.Body.String()) a, _ := jsonparser.GetString(data, "a") b, _ := jsonparser.GetString(data, "b") assert.Equal(t, "1", a) assert.Equal(t, "2", b) assert.Equal(t, http.StatusOK, r.Code) }) } ``` ### Set Query String Using `SetQuery` to generate raw data. ```go func TestQueryString(t *testing.T) { r := gofight.New() r.GET("/hello"). SetQuery(gofight.H{ "a": "1", "b": "2", }). Run(BasicEngine, func(r HTTPResponse, rq HTTPRequest) { assert.Equal(t, http.StatusOK, r.Code) }) } ``` or append exist query parameter. ```go func TestQueryString(t *testing.T) { r := gofight.New() r.GET("/hello?foo=bar"). SetQuery(gofight.H{ "a": "1", "b": "2", }). Run(BasicEngine, func(r HTTPResponse, rq HTTPRequest) { assert.Equal(t, http.StatusOK, r.Code) }) } ``` ### Set Cookie String Using `SetCookie` to generate raw data. ```go func TestQueryString(t *testing.T) { r := gofight.New() r.GET("/hello"). SetCookie(gofight.H{ "foo": "bar", }). Run(BasicEngine, func(r HTTPResponse, rq HTTPRequest) { assert.Equal(t, http.StatusOK, r.Code) assert.Equal(t, "foo=bar", rq.Header.Get("cookie")) }) } ``` ### Set JSON Struct ```go type User struct { // Username user name Username string `json:"username"` // Password account password Password string `json:"password"` } func TestSetJSONInterface(t *testing.T) { r := New() r.POST("/user"). SetJSONInterface(User{ Username: "foo", Password: "bar", }). Run(framework.GinEngine(), func(r HTTPResponse, rq HTTPRequest) { data := []byte(r.Body.String()) username := gjson.GetBytes(data, "username") password := gjson.GetBytes(data, "password") assert.Equal(t, "foo", username.String()) assert.Equal(t, "bar", password.String()) assert.Equal(t, http.StatusOK, r.Code) assert.Equal(t, "application/json; charset=utf-8", r.HeaderMap.Get("Content-Type")) }) } ``` ### Upload multiple file with absolute path and parameter The following is route using gin ```go func gintFileUploadHandler(c *gin.Context) { ip := c.ClientIP() hello, err := c.FormFile("hello") if err != nil { c.JSON(http.StatusBadRequest, gin.H{ "error": err.Error(), }) return } helloFile, _ := hello.Open() helloBytes := make([]byte, 6) helloFile.Read(helloBytes) world, err := c.FormFile("world") if err != nil { c.JSON(http.StatusBadRequest, gin.H{ "error": err.Error(), }) return } worldFile, _ := world.Open() worldBytes := make([]byte, 6) worldFile.Read(worldBytes) foo := c.PostForm("foo") bar := c.PostForm("bar") c.JSON(http.StatusOK, gin.H{ "hello": hello.Filename, "world": world.Filename, "foo": foo, "bar": bar, "ip": ip, "helloSize": string(helloBytes), "worldSize": string(worldBytes), }) } ``` Write the testing: ```go func TestUploadFile(t *testing.T) { r := New() r.POST("/upload"). SetDebug(true). SetFileFromPath([]UploadFile{ { Path: "./testdata/hello.txt", Name: "hello", }, { Path: "./testdata/world.txt", Name: "world", }, }, H{ "foo": "bar", "bar": "foo", }). Run(framework.GinEngine(), func(r HTTPResponse, rq HTTPRequest) { data := []byte(r.Body.String()) hello := gjson.GetBytes(data, "hello") world := gjson.GetBytes(data, "world") foo := gjson.GetBytes(data, "foo") bar := gjson.GetBytes(data, "bar") ip := gjson.GetBytes(data, "ip") helloSize := gjson.GetBytes(data, "helloSize") worldSize := gjson.GetBytes(data, "worldSize") assert.Equal(t, "world\n", helloSize.String()) assert.Equal(t, "hello\n", worldSize.String()) assert.Equal(t, "hello.txt", hello.String()) assert.Equal(t, "world.txt", world.String()) assert.Equal(t, "bar", foo.String()) assert.Equal(t, "foo", bar.String()) assert.Equal(t, "", ip.String()) assert.Equal(t, http.StatusOK, r.Code) assert.Equal(t, "application/json; charset=utf-8", r.HeaderMap.Get("Content-Type")) }) } ``` ### Upload multiple file with content `[]byte` path and parameter ```go func TestUploadFileByContent(t *testing.T) { r := New() helloContent, err := ioutil.ReadFile("./testdata/hello.txt") if err != nil { log.Fatal(err) } worldContent, err := ioutil.ReadFile("./testdata/world.txt") if err != nil { log.Fatal(err) } r.POST("/upload"). SetDebug(true). SetFileFromPath([]UploadFile{ { Path: "hello.txt", Name: "hello", Content: helloContent, }, { Path: "world.txt", Name: "world", Content: worldContent, }, }, H{ "foo": "bar", "bar": "foo", }). Run(framework.GinEngine(), func(r HTTPResponse, rq HTTPRequest) { data := []byte(r.Body.String()) hello := gjson.GetBytes(data, "hello") world := gjson.GetBytes(data, "world") foo := gjson.GetBytes(data, "foo") bar := gjson.GetBytes(data, "bar") ip := gjson.GetBytes(data, "ip") helloSize := gjson.GetBytes(data, "helloSize") worldSize := gjson.GetBytes(data, "worldSize") assert.Equal(t, "world\n", helloSize.String()) assert.Equal(t, "hello\n", worldSize.String()) assert.Equal(t, "hello.txt", hello.String()) assert.Equal(t, "world.txt", world.String()) assert.Equal(t, "bar", foo.String()) assert.Equal(t, "foo", bar.String()) assert.Equal(t, "", ip.String()) assert.Equal(t, http.StatusOK, r.Code) assert.Equal(t, "application/json; charset=utf-8", r.HeaderMap.Get("Content-Type")) }) } ``` ## Example * Basic HTTP Router: [basic.go](_example/basic.go), [basic_test.go](_example/basic_test.go) * Gin Framework: [gin.go](_example/gin.go), [gin_test.go](_example/gin_test.go) * Echo Framework: [echo.go](_example/echo.go), [echo_test.go](_example/echo_test.go) * Mux Framework: [mux.go](_example/mux.go), [mux_test.go](_example/mux_test.go) * HttpRouter Framework: [httprouter.go](_example/httprouter.go), [httprouter_test.go](_example/httprouter_test.go) * Beego Framework: [beego.go](_example/beego.go), [beego_test.go](_example/beego_test.go) ## License Copyright 2019 Bo-Yi Wu [@appleboy](https://twitter.com/appleboy). Licensed under the MIT License. gofight-2.1.2/_example/000077500000000000000000000000001360513044400147355ustar00rootroot00000000000000gofight-2.1.2/_example/basic.go000066400000000000000000000004511360513044400163450ustar00rootroot00000000000000package example import ( "io" "net/http" ) func basicHelloHandler(w http.ResponseWriter, r *http.Request) { io.WriteString(w, "Hello World") } // BasicEngine is basic router. func BasicEngine() http.Handler { mux := http.NewServeMux() mux.HandleFunc("/", basicHelloHandler) return mux } gofight-2.1.2/_example/basic_test.go000066400000000000000000000017161360513044400174110ustar00rootroot00000000000000package example import ( "net/http" "testing" "github.com/appleboy/gofight/v2" "github.com/stretchr/testify/assert" ) func TestBasicHelloWorld(t *testing.T) { r := gofight.New() version := "0.0.1" r.GET("/"). // trun on the debug mode. SetDebug(true). SetHeader(gofight.H{ "X-Version": version, }). Run(BasicEngine(), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) { assert.Equal(t, version, rq.Header.Get("X-Version")) assert.Equal(t, "Hello World", r.Body.String()) assert.Equal(t, http.StatusOK, r.Code) }) } func basicHTTPHelloHandler() { http.HandleFunc("/hello", basicHelloHandler) } func TestBasicHttpHelloWorld(t *testing.T) { basicHTTPHelloHandler() r := gofight.New() r.GET("/hello"). // trun on the debug mode. SetDebug(true). Run(http.DefaultServeMux, func(r gofight.HTTPResponse, rq gofight.HTTPRequest) { assert.Equal(t, "Hello World", r.Body.String()) assert.Equal(t, http.StatusOK, r.Code) }) } gofight-2.1.2/_example/beego.go000066400000000000000000000004611360513044400163460ustar00rootroot00000000000000package example import ( "github.com/astaxie/beego" ) // UserController for beego router type UserController struct { beego.Controller } // SayHelloWorld for say hello func (c *UserController) SayHelloWorld() { c.Ctx.ResponseWriter.Status = 200 c.Ctx.ResponseWriter.Write([]byte("Hello, World")) } gofight-2.1.2/_example/beego_test.go000066400000000000000000000012171360513044400174050ustar00rootroot00000000000000package example import ( "fmt" "net/http" "testing" "github.com/appleboy/gofight/v2" "github.com/astaxie/beego" "github.com/stretchr/testify/assert" ) func TestSayHelloWorld(t *testing.T) { uri := "/say" // LoadAppConfig allow developer to apply a config file // beego.LoadAppConfig("ini", "../conf/app.conf") c := beego.NewControllerRegister() c.Add(uri, &UserController{}, "get:SayHelloWorld") r := gofight.New() r.GET(uri). SetDebug(true). Run(c, func(rp gofight.HTTPResponse, rq gofight.HTTPRequest) { fmt.Println(rp.Code) assert.Equal(t, "Hello, World", rp.Body.String()) assert.Equal(t, http.StatusOK, rp.Code) }) } gofight-2.1.2/_example/echo.go000066400000000000000000000005501360513044400162020ustar00rootroot00000000000000package example import ( "net/http" "github.com/labstack/echo/v4" ) func echoHelloHandler() echo.HandlerFunc { return func(c echo.Context) error { return c.String(http.StatusOK, "Hello World") } } // EchoEngine is echo router. func EchoEngine() *echo.Echo { // Echo instance e := echo.New() // Routes e.GET("/", echoHelloHandler()) return e } gofight-2.1.2/_example/echo_test.go000066400000000000000000000006101360513044400172360ustar00rootroot00000000000000package example import ( "net/http" "testing" "github.com/appleboy/gofight/v2" "github.com/stretchr/testify/assert" ) func TestEchoHelloWorld(t *testing.T) { r := gofight.New() r.GET("/"). SetDebug(true). Run(EchoEngine(), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) { assert.Equal(t, "Hello World", r.Body.String()) assert.Equal(t, http.StatusOK, r.Code) }) } gofight-2.1.2/_example/gin.go000066400000000000000000000007211360513044400160410ustar00rootroot00000000000000package example import ( "fmt" "net/http" "github.com/gin-gonic/gin" ) func ginHelloHandler(c *gin.Context) { c.String(http.StatusOK, "Hello World") } func ginUserHandler(c *gin.Context) { name := c.Param("name") c.String(http.StatusOK, fmt.Sprintf("Hello, %s", name)) } // GinEngine is gin router. func GinEngine() *gin.Engine { gin.SetMode(gin.TestMode) r := gin.New() r.GET("/", ginHelloHandler) r.GET("/user/:name", ginUserHandler) return r } gofight-2.1.2/_example/gin_test.go000066400000000000000000000012431360513044400171000ustar00rootroot00000000000000package example import ( "net/http" "testing" "github.com/appleboy/gofight/v2" "github.com/stretchr/testify/assert" ) func TestGinHelloWorld(t *testing.T) { r := gofight.New() r.GET("/"). SetDebug(true). Run(GinEngine(), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) { assert.Equal(t, "Hello World", r.Body.String()) assert.Equal(t, http.StatusOK, r.Code) }) } func TestGinHelloHandler(t *testing.T) { r := gofight.New() r.GET("/user/appleboy"). SetDebug(true). Run(GinEngine(), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) { assert.Equal(t, "Hello, appleboy", r.Body.String()) assert.Equal(t, http.StatusOK, r.Code) }) } gofight-2.1.2/_example/httprouter.go000066400000000000000000000005551360513044400175110ustar00rootroot00000000000000package example import ( "fmt" "github.com/julienschmidt/httprouter" "net/http" ) func httpRouterHelloHandler(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { fmt.Fprint(w, "Hello World") } // HTTPRouterEngine is httprouter router. func HTTPRouterEngine() http.Handler { r := httprouter.New() r.GET("/", httpRouterHelloHandler) return r } gofight-2.1.2/_example/httprouter_test.go000066400000000000000000000006021360513044400205410ustar00rootroot00000000000000package example import ( "net/http" "testing" "github.com/appleboy/gofight/v2" "github.com/stretchr/testify/assert" ) func TestHttpRouterHelloWorld(t *testing.T) { r := gofight.New() r.GET("/"). Run(HTTPRouterEngine(), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) { assert.Equal(t, "Hello World", r.Body.String()) assert.Equal(t, http.StatusOK, r.Code) }) } gofight-2.1.2/_example/mux.go000066400000000000000000000004471360513044400161020ustar00rootroot00000000000000package example import ( "github.com/gorilla/mux" "net/http" ) func muxHelloHandler(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Hello World")) } // MuxEngine is mux router. func MuxEngine() *mux.Router { r := mux.NewRouter() r.HandleFunc("/", muxHelloHandler) return r } gofight-2.1.2/_example/mux_test.go000066400000000000000000000006061360513044400171360ustar00rootroot00000000000000package example import ( "net/http" "testing" "github.com/appleboy/gofight/v2" "github.com/stretchr/testify/assert" ) func TestMuxHelloWorld(t *testing.T) { r := gofight.New() r.GET("/"). SetDebug(true). Run(MuxEngine(), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) { assert.Equal(t, "Hello World", r.Body.String()) assert.Equal(t, http.StatusOK, r.Code) }) } gofight-2.1.2/_example/pat.go000066400000000000000000000010231360513044400160440ustar00rootroot00000000000000package example import ( "net/http" "github.com/gorilla/pat" ) func patHelloHandler(wr http.ResponseWriter, req *http.Request) { wr.WriteHeader(http.StatusOK) wr.Write([]byte("Hello World")) } func patUserHandler(wr http.ResponseWriter, req *http.Request) { name := req.URL.Query().Get(":name") wr.WriteHeader(http.StatusOK) wr.Write([]byte("Hello, " + name)) } // PatEngine is pat router. func PatEngine() *pat.Router { r := pat.New() r.Get("/user/{name}", patUserHandler) r.Get("/", patHelloHandler) return r } gofight-2.1.2/_example/pat_test.go000066400000000000000000000012431360513044400171070ustar00rootroot00000000000000package example import ( "net/http" "testing" "github.com/appleboy/gofight/v2" "github.com/stretchr/testify/assert" ) func TestPatHelloWorld(t *testing.T) { r := gofight.New() r.GET("/"). SetDebug(true). Run(PatEngine(), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) { assert.Equal(t, "Hello World", r.Body.String()) assert.Equal(t, http.StatusOK, r.Code) }) } func TestPatHelloHandler(t *testing.T) { r := gofight.New() r.GET("/user/appleboy"). SetDebug(true). Run(PatEngine(), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) { assert.Equal(t, "Hello, appleboy", r.Body.String()) assert.Equal(t, http.StatusOK, r.Code) }) } gofight-2.1.2/_example/tango.go000066400000000000000000000003461360513044400163770ustar00rootroot00000000000000package example import ( "gitea.com/lunny/tango" ) // HelloAction for tango router type HelloAction struct { tango.Ctx } // Get will be executed when GET requests func (c *HelloAction) Get() string { return "Hello, World" } gofight-2.1.2/_example/tango_test.go000066400000000000000000000007761360513044400174450ustar00rootroot00000000000000package example import ( "fmt" "net/http" "testing" "gitea.com/lunny/tango" "github.com/appleboy/gofight/v2" "github.com/stretchr/testify/assert" ) func TestTangoHelloWorld(t *testing.T) { tan := tango.New(tango.Return()) tan.Get("/", new(HelloAction)) r := gofight.New() r.GET("/"). SetDebug(true). Run(tan, func(rp gofight.HTTPResponse, rq gofight.HTTPRequest) { fmt.Println(rp.Code) assert.Equal(t, "Hello, World", rp.Body.String()) assert.Equal(t, http.StatusOK, rp.Code) }) } gofight-2.1.2/_framework/000077500000000000000000000000001360513044400152775ustar00rootroot00000000000000gofight-2.1.2/_framework/echo.go000066400000000000000000000042011360513044400165410ustar00rootroot00000000000000package framework import ( "log" "net/http" "github.com/labstack/echo/v4" ) type echoContent struct { Hello string `json:"hello"` Foo string `json:"foo"` A string `json:"a"` B string `json:"b"` C string `json:"c"` D string `json:"d"` } // Binding from JSON type echoJSONContent struct { A int `json:"a" binding:"required"` B int `json:"b" binding:"required"` } func echoHelloHandler() echo.HandlerFunc { return func(c echo.Context) error { return c.JSON(http.StatusOK, &echoContent{ Hello: "world", }) } } func echoTextHandler() echo.HandlerFunc { return func(c echo.Context) error { return c.String(http.StatusOK, "Hello World") } } func echoQueryHandler() echo.HandlerFunc { return func(c echo.Context) error { text := c.QueryParam("text") foo := c.QueryParam("foo") return c.JSON(http.StatusOK, &echoContent{ Hello: text, Foo: foo, }) } } func echoPostFormHandler() echo.HandlerFunc { return func(c echo.Context) error { a := c.FormValue("a") b := c.FormValue("b") return c.JSON(http.StatusOK, &echoContent{ A: a, B: b, }) } } func echoJSONHandler() echo.HandlerFunc { return func(c echo.Context) error { json := new(echoJSONContent) err := c.Bind(json) if err != nil { log.Println(err) } return c.JSON(http.StatusOK, json) } } func echoPutHandler() echo.HandlerFunc { return func(c echo.Context) error { foo := c.FormValue("c") bar := c.FormValue("d") return c.JSON(http.StatusOK, &echoContent{ C: foo, D: bar, }) } } func echoDeleteHandler() echo.HandlerFunc { return func(c echo.Context) error { return c.JSON(http.StatusOK, &echoContent{ Hello: "world", }) } } // EchoEngine is echo router. func EchoEngine() *echo.Echo { e := echo.New() e.GET("/hello", echoHelloHandler()) e.GET("/text", echoTextHandler()) e.GET("/query", echoQueryHandler()) e.POST("/form", echoPostFormHandler()) e.POST("/json", echoJSONHandler()) e.PUT("/update", echoPutHandler()) e.DELETE("/delete", echoDeleteHandler()) e.PATCH("/patch", echoHelloHandler()) e.OPTIONS("/options", echoHelloHandler()) e.HEAD("/head", echoHelloHandler()) return e } gofight-2.1.2/_framework/gin.go000066400000000000000000000056111360513044400164060ustar00rootroot00000000000000package framework import ( "net/http" "time" "github.com/gin-gonic/gin" ) // Binding from JSON type ginJSONContent struct { A int `json:"a" binding:"required"` B int `json:"b" binding:"required"` } func ginHelloHandler(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "hello": "world", }) } func ginTextHandler(c *gin.Context) { c.String(http.StatusOK, "Hello World") } func ginQueryHandler(c *gin.Context) { text := c.Query("text") foo := c.Query("foo") c.JSON(http.StatusOK, gin.H{ "hello": text, "foo": foo, }) } func ginPostFormHandler(c *gin.Context) { a := c.PostForm("a") b := c.PostForm("b") c.JSON(http.StatusOK, gin.H{ "a": a, "b": b, }) } func ginJSONHandler(c *gin.Context) { var json ginJSONContent if c.BindJSON(&json) == nil { c.JSON(http.StatusOK, gin.H{ "a": json.A, "b": json.B, }) } } type ginUserContent struct { // Username user name Username string `json:"account"` // Password account password Password string `json:"password"` } func ginUserHandler(c *gin.Context) { var json ginUserContent if c.ShouldBind(&json) == nil { c.JSON(http.StatusOK, gin.H{ "username": json.Username, "password": json.Password, }) } } func ginPutHandler(c *gin.Context) { foo := c.PostForm("c") bar := c.PostForm("d") c.JSON(http.StatusOK, gin.H{ "c": foo, "d": bar, }) } func ginDeleteHandler(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "hello": "world", }) } func gintTimeoutHandler(c *gin.Context) { time.Sleep(10 * time.Second) c.JSON(http.StatusOK, gin.H{ "hello": "world", }) } func gintFileUploadHandler(c *gin.Context) { ip := c.ClientIP() hello, err := c.FormFile("hello") if err != nil { c.JSON(http.StatusBadRequest, gin.H{ "error": err.Error(), }) return } helloFile, _ := hello.Open() helloBytes := make([]byte, 6) helloFile.Read(helloBytes) world, err := c.FormFile("world") if err != nil { c.JSON(http.StatusBadRequest, gin.H{ "error": err.Error(), }) return } worldFile, _ := world.Open() worldBytes := make([]byte, 6) worldFile.Read(worldBytes) foo := c.PostForm("foo") bar := c.PostForm("bar") c.JSON(http.StatusOK, gin.H{ "hello": hello.Filename, "world": world.Filename, "foo": foo, "bar": bar, "ip": ip, "helloSize": string(helloBytes), "worldSize": string(worldBytes), }) } // GinEngine is gin router. func GinEngine() *gin.Engine { gin.SetMode(gin.TestMode) r := gin.New() r.GET("/hello", ginHelloHandler) r.GET("/text", ginTextHandler) r.GET("/query", ginQueryHandler) r.GET("/timeout", gintTimeoutHandler) r.POST("/form", ginPostFormHandler) r.POST("/json", ginJSONHandler) r.POST("/user", ginUserHandler) r.PUT("/update", ginPutHandler) r.DELETE("/delete", ginDeleteHandler) r.PATCH("/patch", ginJSONHandler) r.HEAD("/head", ginJSONHandler) r.OPTIONS("/options", ginJSONHandler) r.POST("/upload", gintFileUploadHandler) return r } gofight-2.1.2/_framework/gofight_test.go000066400000000000000000000315351360513044400203230ustar00rootroot00000000000000package gofight import ( "crypto/tls" "io/ioutil" "log" "net/http" "runtime" "testing" "time" "github.com/appleboy/gofight/v2/framework" "github.com/gin-gonic/gin" "github.com/stretchr/testify/assert" "github.com/tidwall/gjson" ) var goVersion = runtime.Version() // TestRequest is testing url string if server is running func TestRequest(t *testing.T, url string) { tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, } client := &http.Client{ Timeout: Timeout, Transport: tr, } resp, err := client.Get(url) defer func() { if err := resp.Body.Close(); err != nil { log.Println("close body err:", err) } }() assert.NoError(t, err) _, ioerr := ioutil.ReadAll(resp.Body) assert.NoError(t, ioerr) assert.Equal(t, "200 OK", resp.Status, "should get a 200") } func TestHttpURL(t *testing.T) { gin.SetMode(gin.TestMode) router := gin.New() router.GET("/example", func(c *gin.Context) { c.String(http.StatusOK, "it worked") }) go func() { assert.NoError(t, router.Run()) }() // have to wait for the goroutine to start and run the server // otherwise the main thread will complete time.Sleep(5 * time.Millisecond) TestRequest(t, "http://localhost:8080/example") } func TestHttpsURL(t *testing.T) { gin.SetMode(gin.TestMode) router := gin.New() router.GET("/example", func(c *gin.Context) { c.String(http.StatusOK, "it worked") }) go func() { assert.NoError(t, router.RunTLS(":8088", "certificate/localhost.cert", "certificate/localhost.key")) }() // have to wait for the goroutine to start and run the server // otherwise the main thread will complete time.Sleep(5 * time.Millisecond) TestRequest(t, "https://localhost:8088/example") } func TestGinHelloWorld(t *testing.T) { r := New() r.GET("/hello"). SetDebug(true). Run(framework.GinEngine(), func(r HTTPResponse, rq HTTPRequest) { data := []byte(r.Body.String()) value := gjson.GetBytes(data, "hello") assert.Equal(t, "world", value.String()) assert.Equal(t, http.StatusOK, r.Code) }) } func TestGinHeader(t *testing.T) { r := New() r.GET("/text"). SetHeader(H{ "Content-Type": "text/plain", "Go-Version": goVersion, }). Run(framework.GinEngine(), func(r HTTPResponse, rq HTTPRequest) { assert.Equal(t, goVersion, rq.Header.Get("Go-Version")) assert.Equal(t, "Gofight-client/"+Version, rq.Header.Get(UserAgent)) assert.Equal(t, "text/plain", rq.Header.Get(ContentType)) assert.Equal(t, "Hello World", r.Body.String()) assert.Equal(t, http.StatusOK, r.Code) }) } func TestGinCookie(t *testing.T) { r := New() r.GET("/text"). SetCookie(H{ "foo": "bar", }). Run(framework.GinEngine(), func(r HTTPResponse, rq HTTPRequest) { assert.Equal(t, http.StatusOK, r.Code) assert.Equal(t, "foo=bar", rq.Header.Get("cookie")) }) } func TestGinQuery(t *testing.T) { r := New() r.GET("/query?text=world&foo=bar"). Run(framework.GinEngine(), func(r HTTPResponse, rq HTTPRequest) { data := []byte(r.Body.String()) value := gjson.GetBytes(data, "hello") foo := gjson.GetBytes(data, "foo") assert.Equal(t, "world", value.String()) assert.Equal(t, "bar", foo.String()) assert.Equal(t, http.StatusOK, r.Code) }) } func TestGinPostFormData(t *testing.T) { r := New() r.POST("/form"). SetForm(H{ "a": "1", "b": "2", }). Run(framework.GinEngine(), func(r HTTPResponse, rq HTTPRequest) { data := []byte(r.Body.String()) a := gjson.GetBytes(data, "a") b := gjson.GetBytes(data, "b") assert.Equal(t, "1", a.String()) assert.Equal(t, "2", b.String()) assert.Equal(t, http.StatusOK, r.Code) }) } func TestGinPostJSONData(t *testing.T) { r := New() r.POST("/json"). SetJSON(D{ "a": 1, "b": 2, }). Run(framework.GinEngine(), func(r HTTPResponse, rq HTTPRequest) { data := []byte(r.Body.String()) a := gjson.GetBytes(data, "a") b := gjson.GetBytes(data, "b") assert.Equal(t, int64(1), a.Int()) assert.Equal(t, int64(2), b.Int()) assert.Equal(t, http.StatusOK, r.Code) assert.Equal(t, "application/json; charset=utf-8", r.HeaderMap.Get("Content-Type")) }) } func TestGinPut(t *testing.T) { r := New() r.PUT("/update"). SetBody("c=1&d=2"). Run(framework.GinEngine(), func(r HTTPResponse, rq HTTPRequest) { data := []byte(r.Body.String()) c := gjson.GetBytes(data, "c") d := gjson.GetBytes(data, "d") assert.Equal(t, "1", c.String()) assert.Equal(t, "2", d.String()) assert.Equal(t, http.StatusOK, r.Code) }) } func TestGinDelete(t *testing.T) { r := New() r.DELETE("/delete"). Run(framework.GinEngine(), func(r HTTPResponse, rq HTTPRequest) { data := []byte(r.Body.String()) hello := gjson.GetBytes(data, "hello") assert.Equal(t, "world", hello.String()) assert.Equal(t, http.StatusOK, r.Code) }) } func TestGinPatch(t *testing.T) { r := New() r.PATCH("/patch"). SetJSON(D{ "a": 1, "b": 2, }). Run(framework.GinEngine(), func(r HTTPResponse, rq HTTPRequest) { data := []byte(r.Body.String()) a := gjson.GetBytes(data, "a") b := gjson.GetBytes(data, "b") assert.Equal(t, int64(1), a.Int()) assert.Equal(t, int64(2), b.Int()) assert.Equal(t, http.StatusOK, r.Code) }) } func TestGinHead(t *testing.T) { r := New() r.HEAD("/head"). SetJSON(D{ "a": 1, "b": 2, }). Run(framework.GinEngine(), func(r HTTPResponse, rq HTTPRequest) { data := []byte(r.Body.String()) a := gjson.GetBytes(data, "a") b := gjson.GetBytes(data, "b") assert.Equal(t, int64(1), a.Int()) assert.Equal(t, int64(2), b.Int()) assert.Equal(t, http.StatusOK, r.Code) }) } func TestGinOptions(t *testing.T) { r := New() r.OPTIONS("/options"). SetJSON(D{ "a": 1, "b": 2, }). Run(framework.GinEngine(), func(r HTTPResponse, rq HTTPRequest) { data := []byte(r.Body.String()) a := gjson.GetBytes(data, "a") b := gjson.GetBytes(data, "b") assert.Equal(t, int64(1), a.Int()) assert.Equal(t, int64(2), b.Int()) assert.Equal(t, http.StatusOK, r.Code) }) } func TestEchoHelloWorld(t *testing.T) { r := New() r.GET("/hello"). SetDebug(true). Run(framework.EchoEngine(), func(r HTTPResponse, rq HTTPRequest) { data := []byte(r.Body.String()) hello := gjson.GetBytes(data, "hello") assert.Equal(t, "world", hello.String()) assert.Equal(t, http.StatusOK, r.Code) }) } func TestEchoHeader(t *testing.T) { r := New() r.GET("/text"). SetHeader(H{ "Content-Type": "text/plain", "Go-Version": goVersion, }). Run(framework.EchoEngine(), func(r HTTPResponse, rq HTTPRequest) { assert.Equal(t, goVersion, rq.Header.Get("Go-Version")) assert.Equal(t, r.Body.String(), "Hello World") assert.Equal(t, r.Code, http.StatusOK) }) } func TestEchoQuery(t *testing.T) { r := New() r.GET("/query?text=world&foo=bar"). Run(framework.EchoEngine(), func(r HTTPResponse, rq HTTPRequest) { data := []byte(r.Body.String()) value := gjson.GetBytes(data, "hello") foo := gjson.GetBytes(data, "foo") assert.Equal(t, "world", value.String()) assert.Equal(t, "bar", foo.String()) assert.Equal(t, http.StatusOK, r.Code) }) } func TestEchoPostFormData(t *testing.T) { r := New() r.POST("/form"). SetBody("a=1&b=2"). Run(framework.EchoEngine(), func(r HTTPResponse, rq HTTPRequest) { data := []byte(r.Body.String()) a := gjson.GetBytes(data, "a") b := gjson.GetBytes(data, "b") assert.Equal(t, "1", a.String()) assert.Equal(t, "2", b.String()) assert.Equal(t, http.StatusOK, r.Code) }) } func TestEchoPostJSONData(t *testing.T) { r := New() r.POST("/json"). SetJSON(D{ "a": 1, "b": 2, }). Run(framework.EchoEngine(), func(r HTTPResponse, rq HTTPRequest) { data := []byte(r.Body.String()) a := gjson.GetBytes(data, "a") b := gjson.GetBytes(data, "b") assert.Equal(t, int64(1), a.Int()) assert.Equal(t, int64(2), b.Int()) assert.Equal(t, http.StatusOK, r.Code) }) } func TestEchoPut(t *testing.T) { r := New() r.PUT("/update"). SetBody("c=1&d=2"). Run(framework.EchoEngine(), func(r HTTPResponse, rq HTTPRequest) { data := []byte(r.Body.String()) c := gjson.GetBytes(data, "c") d := gjson.GetBytes(data, "d") assert.Equal(t, "1", c.String()) assert.Equal(t, "2", d.String()) assert.Equal(t, http.StatusOK, r.Code) }) } func TestEchoDelete(t *testing.T) { r := New() r.DELETE("/delete"). Run(framework.EchoEngine(), func(r HTTPResponse, rq HTTPRequest) { data := []byte(r.Body.String()) hello := gjson.GetBytes(data, "hello") assert.Equal(t, "world", hello.String()) assert.Equal(t, http.StatusOK, r.Code) }) } func TestEchoPatch(t *testing.T) { r := New() r.PATCH("/patch"). Run(framework.EchoEngine(), func(r HTTPResponse, rq HTTPRequest) { data := []byte(r.Body.String()) hello := gjson.GetBytes(data, "hello") assert.Equal(t, "world", hello.String()) assert.Equal(t, http.StatusOK, r.Code) }) } func TestEchoHead(t *testing.T) { r := New() r.HEAD("/head"). Run(framework.EchoEngine(), func(r HTTPResponse, rq HTTPRequest) { data := []byte(r.Body.String()) hello := gjson.GetBytes(data, "hello") assert.Equal(t, "world", hello.String()) assert.Equal(t, http.StatusOK, r.Code) }) } func TestEchoOptions(t *testing.T) { r := New() r.OPTIONS("/options"). Run(framework.EchoEngine(), func(r HTTPResponse, rq HTTPRequest) { data := []byte(r.Body.String()) hello := gjson.GetBytes(data, "hello") assert.Equal(t, "world", hello.String()) assert.Equal(t, http.StatusOK, r.Code) }) } func TestSetQueryString(t *testing.T) { r := New() r.GET("/hello"). SetQuery(H{ "a": "1", "b": "2", }) assert.Equal(t, "/hello?a=1&b=2", r.Path) r.GET("/hello?foo=bar"). SetQuery(H{ "a": "1", "b": "2", }) assert.Equal(t, "/hello?foo=bar&a=1&b=2", r.Path) } type User struct { // Username user name Username string `json:"account"` // Password account password Password string `json:"password"` } func TestSetJSONInterface(t *testing.T) { r := New() r.POST("/user"). SetJSONInterface(User{ Username: "foo", Password: "bar", }). Run(framework.GinEngine(), func(r HTTPResponse, rq HTTPRequest) { data := []byte(r.Body.String()) username := gjson.GetBytes(data, "username") password := gjson.GetBytes(data, "password") assert.Equal(t, "foo", username.String()) assert.Equal(t, "bar", password.String()) assert.Equal(t, http.StatusOK, r.Code) assert.Equal(t, "application/json; charset=utf-8", r.HeaderMap.Get("Content-Type")) }) } func TestUploadFile(t *testing.T) { r := New() r.POST("/upload"). SetDebug(true). SetFileFromPath([]UploadFile{ { Path: "./testdata/hello.txt", Name: "hello", }, { Path: "./testdata/world.txt", Name: "world", }, }, H{ "foo": "bar", "bar": "foo", }). Run(framework.GinEngine(), func(r HTTPResponse, rq HTTPRequest) { data := []byte(r.Body.String()) hello := gjson.GetBytes(data, "hello") world := gjson.GetBytes(data, "world") foo := gjson.GetBytes(data, "foo") bar := gjson.GetBytes(data, "bar") ip := gjson.GetBytes(data, "ip") helloSize := gjson.GetBytes(data, "helloSize") worldSize := gjson.GetBytes(data, "worldSize") assert.Equal(t, "world\n", helloSize.String()) assert.Equal(t, "hello\n", worldSize.String()) assert.Equal(t, "hello.txt", hello.String()) assert.Equal(t, "world.txt", world.String()) assert.Equal(t, "bar", foo.String()) assert.Equal(t, "foo", bar.String()) assert.Equal(t, "", ip.String()) assert.Equal(t, http.StatusOK, r.Code) assert.Equal(t, "application/json; charset=utf-8", r.HeaderMap.Get("Content-Type")) }) } func TestUploadFileByContent(t *testing.T) { r := New() helloContent, err := ioutil.ReadFile("./testdata/hello.txt") if err != nil { log.Fatal(err) } worldContent, err := ioutil.ReadFile("./testdata/world.txt") if err != nil { log.Fatal(err) } r.POST("/upload"). SetDebug(true). SetFileFromPath([]UploadFile{ { Path: "hello.txt", Name: "hello", Content: helloContent, }, { Path: "world.txt", Name: "world", Content: worldContent, }, }, H{ "foo": "bar", "bar": "foo", }). Run(framework.GinEngine(), func(r HTTPResponse, rq HTTPRequest) { data := []byte(r.Body.String()) hello := gjson.GetBytes(data, "hello") world := gjson.GetBytes(data, "world") foo := gjson.GetBytes(data, "foo") bar := gjson.GetBytes(data, "bar") ip := gjson.GetBytes(data, "ip") helloSize := gjson.GetBytes(data, "helloSize") worldSize := gjson.GetBytes(data, "worldSize") assert.Equal(t, "world\n", helloSize.String()) assert.Equal(t, "hello\n", worldSize.String()) assert.Equal(t, "hello.txt", hello.String()) assert.Equal(t, "world.txt", world.String()) assert.Equal(t, "bar", foo.String()) assert.Equal(t, "foo", bar.String()) assert.Equal(t, "", ip.String()) assert.Equal(t, http.StatusOK, r.Code) assert.Equal(t, "application/json; charset=utf-8", r.HeaderMap.Get("Content-Type")) }) } gofight-2.1.2/certificate/000077500000000000000000000000001360513044400154255ustar00rootroot00000000000000gofight-2.1.2/certificate/localhost.cert000066400000000000000000000021061360513044400202730ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIC+zCCAeOgAwIBAgIJALbZEDvUQrFKMA0GCSqGSIb3DQEBBQUAMBQxEjAQBgNV BAMMCWxvY2FsaG9zdDAeFw0xNjAzMjgwMzMwNDFaFw0yNjAzMjYwMzMwNDFaMBQx EjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC ggEBAMj1+xg4jVLzVnB5j7n1ul30WEE4BCzcNFxg5AOB5H5q+wje0YYiVFg6PQyv GCipqIRXVRdVQ1hHSeunYGKe8lq3Sb1X8PUJ12v9uRbpS9DK1Owqk8rsPDu6sVTL qKKgH1Z8yazzaS0AbXuA5e9gO/RzijbnpEP+quM4dueiMPVEJyLq+EoIQY+MM8MP 8dZzL4XZl7wL4UsCN7rPcO6W3tlnT0iO3h9c/Ym2hFhz+KNJ9KRRCvtPGZESigtK bHsXH099WDo8v/Wp5/evBw/+JD0opxmCfHIBALHt9v53RvvsDZ1t33Rpu5C8znEY Y2Ay7NgxhqjqoWJqA48lJeA0clsCAwEAAaNQME4wHQYDVR0OBBYEFC0bTU1Xofeh NKIelashIsqKidDYMB8GA1UdIwQYMBaAFC0bTU1XofehNKIelashIsqKidDYMAwG A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAiJL8IMTwNX9XqQWYDFgkG4 AnrVwQhreAqC9rSxDCjqqnMHPHGzcCeDMLAMoh0kOy20nowUGNtCZ0uBvnX2q1bN g1jt+GBcLJDR3LL4CpNOlm3YhOycuNfWMxTA7BXkmnSrZD/7KhArsBEY8aulxwKJ HRgNlIwe1oFD1YdX1BS5pp4t25B6Vq4A3FMMUkVoWE688nE168hvQgwjrHkgHhwe eN8lGE2DhFraXnWmDMdwaHD3HRFGhyppIFN+f7BqbWX9gM+T2YRTfObIXLWbqJLD 3Mk/NkxqVcg4eY54wJ1ufCUGAYAIaY6fQqiNUz8nhwK3t45NBVT9y/uJXqnTLyY= -----END CERTIFICATE----- gofight-2.1.2/certificate/localhost.key000066400000000000000000000032131360513044400201260ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIIEogIBAAKCAQEAyPX7GDiNUvNWcHmPufW6XfRYQTgELNw0XGDkA4Hkfmr7CN7R hiJUWDo9DK8YKKmohFdVF1VDWEdJ66dgYp7yWrdJvVfw9QnXa/25FulL0MrU7CqT yuw8O7qxVMuooqAfVnzJrPNpLQBte4Dl72A79HOKNuekQ/6q4zh256Iw9UQnIur4 SghBj4wzww/x1nMvhdmXvAvhSwI3us9w7pbe2WdPSI7eH1z9ibaEWHP4o0n0pFEK +08ZkRKKC0psexcfT31YOjy/9ann968HD/4kPSinGYJ8cgEAse32/ndG++wNnW3f dGm7kLzOcRhjYDLs2DGGqOqhYmoDjyUl4DRyWwIDAQABAoIBAGTKqsN9KbSfA42q CqI0UuLouJMNa1qsnz5uAi6YKWgWdA4A44mpEjCmFRSVhUJvxWuK+cyYIQzXxIWD D16nZdqF72AeCWZ9JySsvvZ00GfKM3y35iRy08sJWgOzmcLnGJCiSeyKsQe3HTJC dhDXbXqvsHTVPZg01LTeDxUiTffU8NMKqR2AecQ2sTDwXEhAnTyAtnzl/XaBgFzu U6G7FzGM5y9bxkfQVkvy+DEJkHGNOjzwcVfByyVl610ixmG1vmxVj9PbWmIPsUV8 ySmjhvDQbOfoxW0h9vTlTqGtQcBw962osnDDMWFCdM7lzO0T7RRnPVGIRpCJOKhq keqHKwECgYEA8wwI/iZughoTXTNG9LnQQ/WAtsqO80EjMTUheo5I1kOzmUz09pyh iAsUDoN0/26tZ5WNjlnyZu7dvTc/x3dTZpmNnoo8gcVbQNECDRzqfuQ9PPXm1SN5 6peBqAvBv78hjV05aXzPG/VBbeig7l299EarEA+a/oH3KrgDoqVqE0ECgYEA06vA YJmgg4fZRucAYoaYsLz9Z9rCFjTe1PBTmUJkbOR8vFIHHTTEWi/SuxXL0wDSeoE2 7BQm86gCC7/KgRdrzoBqZ5qS9Mv2dsLgY635VSgjjfZkVLiH1VRRpSQObYnfoysg gatcHSKMExd4SLQByAuImXP+L5ayDBcEJfbqSpsCgYB78Is1b0uzNLDjOh7Y9Vhr D2qPzEORcIoNsdZctOoXuXaAmmngyIbm5R9ZN1gWWc47oFwLV3rxWqXgs6fmg8cX 7v309vFcC9Q4/Vxaa4B5LNK9n3gTAIBPTOtlUnl+2my1tfBtBqRm0W6IKbTHWS5g vxjEm/CiEIyGUEgqTMgHAQKBgBKuXdQoutng63QufwIzDtbKVzMLQ4XiNKhmbXph OavCnp+gPbB+L7Yl8ltAmTSOJgVZ0hcT0DxA361Zx+2Mu58GBl4OblnchmwE1vj1 KcQyPrEQxdoUTyiswGfqvrs8J9imvb+z9/U6T1KAB8Wi3WViXzPr4MsiaaRXg642 FIdxAoGAZ7/735dkhJcyOfs+LKsLr68JSstoorXOYvdMu1+JGa9iLuhnHEcMVWC8 IuihzPfloZtMbGYkZJn8l3BeGd8hmfFtgTgZGPoVRetft2LDFLnPxp2sEH5OFLsQ R+K/kAOul8eStWuMXOFA9pMzGkGEgIFJMJOyaJON3kedQI8deCM= -----END RSA PRIVATE KEY----- gofight-2.1.2/go.mod000066400000000000000000000000571360513044400142530ustar00rootroot00000000000000module github.com/appleboy/gofight/v2 go 1.13 gofight-2.1.2/go.sum000066400000000000000000000000001360513044400142640ustar00rootroot00000000000000gofight-2.1.2/gofight.go000066400000000000000000000162331360513044400151260ustar00rootroot00000000000000// Package gofight offers simple API http handler testing for Golang framework. // // Details about the gofight project are found in github page: // // https://github.com/appleboy/gofight // // Installation: // // $ go get -u github.com/appleboy/gofight // // Set Header: You can add custom header via SetHeader func. // // SetHeader(gofight.H{ // "X-Version": version, // }) // // Set Cookie: You can add custom cookie via SetCookie func. // // SetCookie(gofight.H{ // "foo": "bar", // }) // // Set query string: Using SetQuery to generate query string data. // // SetQuery(gofight.H{ // "a": "1", // "b": "2", // }) // // POST FORM Data: Using SetForm to generate form data. // // SetForm(gofight.H{ // "a": "1", // "b": "2", // }) // // POST JSON Data: Using SetJSON to generate json data. // // SetJSON(gofight.H{ // "a": "1", // "b": "2", // }) // // POST RAW Data: Using SetBody to generate raw data. // // SetBody("a=1&b=1") // // For more details, see the documentation and example. // package gofight import ( "bytes" "encoding/json" "io" "log" "mime/multipart" "net/http" "net/http/httptest" "net/url" "os" "path/filepath" "strings" "time" ) // Media types const ( Version = "1.0" UserAgent = "User-Agent" ContentType = "Content-Type" ApplicationJSON = "application/json" ApplicationForm = "application/x-www-form-urlencoded" ) // Timeout for http client // see https://medium.com/@nate510/don-t-use-go-s-default-http-client-4804cb19f779 var Timeout = time.Second * 10 // HTTPResponse is basic HTTP response type type HTTPResponse *httptest.ResponseRecorder // HTTPRequest is basic HTTP request type type HTTPRequest *http.Request // ResponseFunc response handling func type type ResponseFunc func(HTTPResponse, HTTPRequest) // H is HTTP Header Type type H map[string]string // D is HTTP Data Type type D map[string]interface{} // RequestConfig provide user input request structure type RequestConfig struct { Method string Path string Body string Headers H Cookies H Debug bool ContentType string } // UploadFile for upload file struct type UploadFile struct { Path string Name string Content []byte } // New supply initial structure func New() *RequestConfig { return &RequestConfig{} } // SetDebug supply enable debug mode. func (rc *RequestConfig) SetDebug(enable bool) *RequestConfig { rc.Debug = enable return rc } // GET is request method. func (rc *RequestConfig) GET(path string) *RequestConfig { rc.Path = path rc.Method = "GET" return rc } // POST is request method. func (rc *RequestConfig) POST(path string) *RequestConfig { rc.Path = path rc.Method = "POST" return rc } // PUT is request method. func (rc *RequestConfig) PUT(path string) *RequestConfig { rc.Path = path rc.Method = "PUT" return rc } // DELETE is request method. func (rc *RequestConfig) DELETE(path string) *RequestConfig { rc.Path = path rc.Method = "DELETE" return rc } // PATCH is request method. func (rc *RequestConfig) PATCH(path string) *RequestConfig { rc.Path = path rc.Method = "PATCH" return rc } // HEAD is request method. func (rc *RequestConfig) HEAD(path string) *RequestConfig { rc.Path = path rc.Method = "HEAD" return rc } // OPTIONS is request method. func (rc *RequestConfig) OPTIONS(path string) *RequestConfig { rc.Path = path rc.Method = "OPTIONS" return rc } // SetHeader supply http header what you defined. func (rc *RequestConfig) SetHeader(headers H) *RequestConfig { if len(headers) > 0 { rc.Headers = headers } return rc } // SetJSON supply JSON body. func (rc *RequestConfig) SetJSON(body D) *RequestConfig { if b, err := json.Marshal(body); err == nil { rc.Body = string(b) } return rc } // SetJSONInterface supply JSON body func (rc *RequestConfig) SetJSONInterface(body interface{}) *RequestConfig { if b, err := json.Marshal(body); err == nil { rc.Body = string(b) } return rc } // SetForm supply form body. func (rc *RequestConfig) SetForm(body H) *RequestConfig { f := make(url.Values) for k, v := range body { f.Set(k, v) } rc.Body = f.Encode() return rc } // SetFileFromPath upload new file. func (rc *RequestConfig) SetFileFromPath(uploads []UploadFile, params ...H) *RequestConfig { body := new(bytes.Buffer) writer := multipart.NewWriter(body) for _, f := range uploads { reader := bytes.NewReader(f.Content) if reader.Size() == 0 { file, err := os.Open(f.Path) if err != nil { log.Fatal(err) } defer file.Close() part, err := writer.CreateFormFile(f.Name, filepath.Base(f.Path)) if err != nil { log.Fatal(err) } _, err = io.Copy(part, file) if err != nil { log.Fatal(err) } } else { part, err := writer.CreateFormFile(f.Name, filepath.Base(f.Path)) if err != nil { log.Fatal(err) } _, err = reader.WriteTo(part) if err != nil { log.Fatal(err) } } } if len(params) > 0 { for key, val := range params[0] { _ = writer.WriteField(key, val) } } err := writer.Close() if err != nil { log.Fatal(err) } rc.ContentType = writer.FormDataContentType() rc.Body = body.String() return rc } // SetQuery supply query string. func (rc *RequestConfig) SetQuery(query H) *RequestConfig { f := make(url.Values) for k, v := range query { f.Set(k, v) } if strings.Contains(rc.Path, "?") { rc.Path = rc.Path + "&" + f.Encode() } else { rc.Path = rc.Path + "?" + f.Encode() } return rc } // SetBody supply raw body. func (rc *RequestConfig) SetBody(body string) *RequestConfig { if len(body) > 0 { rc.Body = body } return rc } // SetCookie supply cookies what you defined. func (rc *RequestConfig) SetCookie(cookies H) *RequestConfig { if len(cookies) > 0 { rc.Cookies = cookies } return rc } func (rc *RequestConfig) initTest() (*http.Request, *httptest.ResponseRecorder) { qs := "" if strings.Contains(rc.Path, "?") { ss := strings.Split(rc.Path, "?") rc.Path = ss[0] qs = ss[1] } body := bytes.NewBufferString(rc.Body) req, _ := http.NewRequest(rc.Method, rc.Path, body) if len(qs) > 0 { req.URL.RawQuery = qs } // Auto add user agent req.Header.Set(UserAgent, "Gofight-client/"+Version) if rc.Method == "POST" || rc.Method == "PUT" || rc.Method == "PATCH" { if strings.HasPrefix(rc.Body, "{") { req.Header.Set(ContentType, ApplicationJSON) } else { req.Header.Set(ContentType, ApplicationForm) } } if rc.ContentType != "" { req.Header.Set(ContentType, rc.ContentType) } if len(rc.Headers) > 0 { for k, v := range rc.Headers { req.Header.Set(k, v) } } if len(rc.Cookies) > 0 { for k, v := range rc.Cookies { req.AddCookie(&http.Cookie{Name: k, Value: v}) } } if rc.Debug { log.Printf("Request Method: %s", rc.Method) log.Printf("Request Path: %s", rc.Path) log.Printf("Request Body: %s", rc.Body) log.Printf("Request Headers: %s", rc.Headers) log.Printf("Request Cookies: %s", rc.Cookies) log.Printf("Request Header: %s", req.Header) } w := httptest.NewRecorder() return req, w } // Run execute http request func (rc *RequestConfig) Run(r http.Handler, response ResponseFunc) { req, w := rc.initTest() r.ServeHTTP(w, req) response(w, req) } gofight-2.1.2/testdata/000077500000000000000000000000001360513044400147545ustar00rootroot00000000000000gofight-2.1.2/testdata/hello.txt000066400000000000000000000000061360513044400166140ustar00rootroot00000000000000world gofight-2.1.2/testdata/world.txt000066400000000000000000000000061360513044400166400ustar00rootroot00000000000000hello