init
continuous-integration/drone/push Build is failing
Details
continuous-integration/drone/push Build is failing
Details
This commit is contained in:
commit
27e470366a
|
@ -0,0 +1,54 @@
|
|||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: test
|
||||
|
||||
steps:
|
||||
- name: test
|
||||
image: golang:1.20
|
||||
commands:
|
||||
- go test -race -coverprofile=coverage.txt -covermode=atomic ./...
|
||||
|
||||
trigger:
|
||||
event:
|
||||
- push
|
||||
- pull_request
|
||||
branch:
|
||||
- master
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: check-go-mod
|
||||
|
||||
steps:
|
||||
- name: go.mod
|
||||
image: golang:1.20
|
||||
commands:
|
||||
- go mod tidy
|
||||
- git diff --exit-code go.mod
|
||||
|
||||
trigger:
|
||||
event:
|
||||
- push
|
||||
- pull_request
|
||||
branch:
|
||||
- master
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: golangci-lint
|
||||
|
||||
steps:
|
||||
- name: golangci-lint
|
||||
image: golangci/golangci-lint:v1.52
|
||||
commands:
|
||||
- golangci-lint run
|
||||
|
||||
trigger:
|
||||
event:
|
||||
- push
|
||||
- pull_request
|
||||
branch:
|
||||
- master
|
|
@ -0,0 +1 @@
|
|||
.idea
|
|
@ -0,0 +1,108 @@
|
|||
run:
|
||||
tests: true
|
||||
timeout: 5m
|
||||
|
||||
linters:
|
||||
disable-all: true
|
||||
enable:
|
||||
- asasalint
|
||||
- asciicheck
|
||||
- bodyclose
|
||||
- bidichk
|
||||
- exportloopref
|
||||
- depguard
|
||||
- errcheck
|
||||
- gocritic
|
||||
- gosec
|
||||
- gofmt
|
||||
- goimports
|
||||
- gosimple
|
||||
- govet
|
||||
- ineffassign
|
||||
- misspell
|
||||
- nakedret
|
||||
- prealloc
|
||||
- staticcheck
|
||||
- typecheck
|
||||
- unconvert
|
||||
- unused
|
||||
- lll
|
||||
- nestif
|
||||
- thelper
|
||||
- nonamedreturns
|
||||
- gocyclo
|
||||
- gomnd
|
||||
- tenv
|
||||
- testpackage
|
||||
- noctx
|
||||
- tparallel
|
||||
- usestdlibvars
|
||||
- unconvert
|
||||
- makezero
|
||||
- grouper
|
||||
- errname
|
||||
- exhaustive
|
||||
- tagliatelle
|
||||
- contextcheck
|
||||
- gocheckcompilerdirectives
|
||||
- errname
|
||||
- forcetypeassert
|
||||
- durationcheck
|
||||
- predeclared
|
||||
- promlinter
|
||||
- wastedassign
|
||||
|
||||
linters-settings:
|
||||
lll:
|
||||
line-length: 150
|
||||
gocyclo:
|
||||
min-complexity: 10
|
||||
govet:
|
||||
enable:
|
||||
- asmdecl
|
||||
- assign
|
||||
- atomic
|
||||
- atomicalign
|
||||
- bools
|
||||
- buildtag
|
||||
- cgocall
|
||||
- composites
|
||||
- copylocks
|
||||
- deepequalerrors
|
||||
- errorsas
|
||||
- findcall
|
||||
- framepointer
|
||||
- httpresponse
|
||||
- ifaceassert
|
||||
- loopclosure
|
||||
- lostcancel
|
||||
- nilfunc
|
||||
- nilness
|
||||
- printf
|
||||
- reflectvaluecompare
|
||||
- shadow
|
||||
- shift
|
||||
- sigchanyzer
|
||||
- sortslice
|
||||
- stdmethods
|
||||
- stringintconv
|
||||
- structtag
|
||||
- testinggoroutine
|
||||
- tests
|
||||
- unmarshal
|
||||
- unreachable
|
||||
- unsafeptr
|
||||
- unusedresult
|
||||
- unusedwrite
|
||||
gomnd:
|
||||
ignored-functions:
|
||||
- strconv.FormatInt
|
||||
- strconv.ParseInt
|
||||
|
||||
issues:
|
||||
exclude-rules:
|
||||
# Exclude some linters from running on tests files.
|
||||
- path: _test\.go
|
||||
linters:
|
||||
- dupl
|
||||
- gocyclo
|
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2023 Dawid Wysokiński
|
||||
|
||||
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.
|
|
@ -0,0 +1,53 @@
|
|||
# chiclientip [![Build Status](https://drone.dwysokinski.me/api/badges/Kichiyaki/chiclientip/status.svg)](https://drone.dwysokinski.me/Kichiyaki/chiclientip)
|
||||
|
||||
## Getting started
|
||||
|
||||
### Installation
|
||||
|
||||
```shell
|
||||
go get gitea.dwysokinski.me/Kichiyaki/chirealip
|
||||
```
|
||||
|
||||
### Usage
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"gitea.dwysokinski.me/Kichiyaki/chiclientip"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/realclientip/realclientip-go"
|
||||
)
|
||||
|
||||
func main() {
|
||||
stratXForwardedFor, err := realclientip.NewRightmostNonPrivateStrategy(http.CanonicalHeaderKey("X-Forwarded-For"))
|
||||
if err != nil {
|
||||
log.Fatalln("realclientip.NewRightmostNonPrivateStrategy", err)
|
||||
}
|
||||
strat := realclientip.NewChainStrategy(
|
||||
stratXForwardedFor,
|
||||
realclientip.RemoteAddrStrategy{},
|
||||
)
|
||||
|
||||
router := chi.NewRouter()
|
||||
router.Use(chiclientip.ClientIP(strat))
|
||||
router.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
clientIP, _ := chiclientip.ClientIPFromContext(r.Context())
|
||||
_, _ = w.Write([]byte(clientIP))
|
||||
})
|
||||
|
||||
http.ListenAndServe(":8080", router)
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
Distributed under the MIT License. See ``LICENSE`` for more information.
|
||||
|
||||
## Contact
|
||||
|
||||
Dawid Wysokiński - [contact@dwysokinski.me](mailto:contact@dwysokinski.me)
|
|
@ -0,0 +1,28 @@
|
|||
package chiclientip
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/realclientip/realclientip-go"
|
||||
)
|
||||
|
||||
type clientIPCtxKey struct{}
|
||||
|
||||
// ClientIP is a go-chi middleware that derives the client IP from realclientip.Strategy
|
||||
// and stores it in the http.Request Context.
|
||||
func ClientIP(strat realclientip.Strategy) func(next http.Handler) http.Handler {
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
clientIP := strat.ClientIP(r.Header, r.RemoteAddr)
|
||||
r = r.WithContext(context.WithValue(r.Context(), clientIPCtxKey{}, clientIP))
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// ClientIPFromContext returns the client ip in context.Context if exists.
|
||||
func ClientIPFromContext(ctx context.Context) (string, bool) {
|
||||
clientIP, ok := ctx.Value(clientIPCtxKey{}).(string)
|
||||
return clientIP, ok
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
package chiclientip_test
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"gitea.dwysokinski.me/Kichiyaki/chiclientip"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/realclientip/realclientip-go"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestClientIP(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
strategy func(t *testing.T) realclientip.Strategy
|
||||
remoteAddr string
|
||||
header func(header http.Header) http.Header
|
||||
expectedClientIP string
|
||||
}{
|
||||
{
|
||||
name: "OK: X-Forwarded-For",
|
||||
strategy: func(t *testing.T) realclientip.Strategy {
|
||||
strat, err := realclientip.NewRightmostNonPrivateStrategy(http.CanonicalHeaderKey("X-Forwarded-For"))
|
||||
require.NoError(t, err)
|
||||
return strat
|
||||
},
|
||||
remoteAddr: "192.0.2.1:1234",
|
||||
header: func(header http.Header) http.Header {
|
||||
header["X-Forwarded-For"] = []string{"10.0.42.1", "94.123.222.111", "10.0.42.3"}
|
||||
return header
|
||||
},
|
||||
expectedClientIP: "94.123.222.111",
|
||||
},
|
||||
{
|
||||
name: "OK: X-Forwarded-For, RemoteAddr",
|
||||
strategy: func(t *testing.T) realclientip.Strategy {
|
||||
stratXForwardedFor, err := realclientip.NewRightmostNonPrivateStrategy(http.CanonicalHeaderKey("X-Forwarded-For"))
|
||||
require.NoError(t, err)
|
||||
return realclientip.NewChainStrategy(
|
||||
stratXForwardedFor,
|
||||
realclientip.RemoteAddrStrategy{},
|
||||
)
|
||||
},
|
||||
remoteAddr: "192.0.2.1:1234",
|
||||
header: func(header http.Header) http.Header {
|
||||
return header
|
||||
},
|
||||
expectedClientIP: "192.0.2.1",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
router := chi.NewRouter()
|
||||
router.Use(chiclientip.ClientIP(tt.strategy(t)))
|
||||
router.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
clientIP, _ := chiclientip.ClientIPFromContext(r.Context())
|
||||
_, _ = w.Write([]byte(clientIP))
|
||||
})
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(http.MethodGet, "/", nil)
|
||||
req.RemoteAddr = tt.remoteAddr
|
||||
req.Header = tt.header(req.Header.Clone())
|
||||
router.ServeHTTP(rr, req)
|
||||
|
||||
assert.Equal(t, http.StatusOK, rr.Code)
|
||||
assert.Equal(t, tt.expectedClientIP, rr.Body.String())
|
||||
})
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
module gitea.dwysokinski.me/Kichiyaki/chiclientip
|
||||
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
github.com/go-chi/chi/v5 v5.0.8
|
||||
github.com/realclientip/realclientip-go v1.0.0
|
||||
github.com/stretchr/testify v1.8.2
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
|
@ -0,0 +1,21 @@
|
|||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0=
|
||||
github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/realclientip/realclientip-go v1.0.0 h1:+yPxeC0mEaJzq1BfCt2h4BxlyrvIIBzR6suDc3BEF1U=
|
||||
github.com/realclientip/realclientip-go v1.0.0/go.mod h1:CXnUdVwFRcXFJIRb/dTYqbT7ud48+Pi2pFm80bxDmcI=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
Loading…
Reference in New Issue