diff --git a/.github/workflows/go-cross.yml b/.github/workflows/go-cross.yml index a89f0bb..3026c7b 100644 --- a/.github/workflows/go-cross.yml +++ b/.github/workflows/go-cross.yml @@ -11,37 +11,19 @@ jobs: strategy: matrix: - go-version: [ 1.16, 1.x ] + go-version: [ 1.24, 1.x ] os: [ubuntu-latest, macos-latest, windows-latest] steps: # https://github.com/marketplace/actions/setup-go-environment - name: Set up Go ${{ matrix.go-version }} - uses: actions/setup-go@v2 + uses: actions/setup-go@v6 with: go-version: ${{ matrix.go-version }} # https://github.com/marketplace/actions/checkout - name: Checkout code - uses: actions/checkout@v2 - - # https://github.com/marketplace/actions/cache - - name: Cache Go modules - uses: actions/cache@v2 - with: - # In order: - # * Module download cache - # * Build cache (Linux) - # * Build cache (Mac) - # * Build cache (Windows) - path: | - ~/go/pkg/mod - ~/.cache/go-build - ~/Library/Caches/go-build - %LocalAppData%\go-build - key: ${{ runner.os }}-${{ matrix.go-version }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-${{ matrix.go-version }}-go- + uses: actions/checkout@v6 - name: Test run: go test -v -cover ./... diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 01062b7..c1ba935 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -14,7 +14,7 @@ jobs: name: Main Process runs-on: ubuntu-latest env: - GO_VERSION: 1.15 + GO_VERSION: 1.25 GOLANGCI_LINT_VERSION: v1.41.1 YAEGI_VERSION: v0.9.20 CGO_ENABLED: 0 @@ -26,26 +26,17 @@ jobs: # https://github.com/marketplace/actions/setup-go-environment - name: Set up Go ${{ env.GO_VERSION }} - uses: actions/setup-go@v2 + uses: actions/setup-go@v6 with: go-version: ${{ env.GO_VERSION }} # https://github.com/marketplace/actions/checkout - name: Check out code - uses: actions/checkout@v2 + uses: actions/checkout@v6 with: path: go/src/github.com/${{ github.repository }} fetch-depth: 0 - # https://github.com/marketplace/actions/cache - - name: Cache Go modules - uses: actions/cache@v2 - with: - path: ${{ github.workspace }}/go/pkg/mod - key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-go- - # https://golangci-lint.run/usage/install#other-ci - name: Install golangci-lint ${{ env.GOLANGCI_LINT_VERSION }} run: curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin ${GOLANGCI_LINT_VERSION} diff --git a/README.md b/README.md index 22c4577..018fc6f 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,9 @@ [![Build Status](https://github.com/traefik/plugin-blockpath/workflows/Main/badge.svg?branch=master)](https://github.com/traefik/plugin-blockpath/actions) -Block Path is a middleware plugin for [Traefik](https://github.com/traefik/traefik) which sends an HTTP `403 Forbidden` -response when the requested HTTP path matches one the configured [regular expressions](https://github.com/google/re2/wiki/Syntax). +Block Path is a middleware plugin for [Traefik](https://github.com/traefik/traefik) which blocks requests +with a configurable status code (default `403 Forbidden`) when the requested HTTP path matches one of the +configured [regular expressions](https://github.com/google/re2/wiki/Syntax). ## Configuration @@ -35,6 +36,7 @@ and uses the `blockpath` middleware plugin to block all HTTP requests with a pat [http.middlewares] [http.middlewares.block-foo.plugin.blockpath] regex = ["^/foo(.*)"] + code = 404 # optional, responds with code 404 instead of 403 [http.services] [http.services.my-service] diff --git a/blockpath.go b/blockpath.go index bd45bd7..eb791fc 100644 --- a/blockpath.go +++ b/blockpath.go @@ -11,6 +11,7 @@ import ( // Config holds the plugin configuration. type Config struct { Regex []string `json:"regex,omitempty"` + Code *int `json:"code,omitempty"` // Optional: Status code to respond with, defaults to 403 Forbidden } // CreateConfig creates and initializes the plugin configuration. @@ -22,6 +23,7 @@ type blockPath struct { name string next http.Handler regexps []*regexp.Regexp + code int } // New creates and returns a plugin instance. @@ -37,10 +39,16 @@ func New(_ context.Context, next http.Handler, config *Config, name string) (htt regexps[i] = re } + code := http.StatusForbidden + if config.Code != nil { + code = *config.Code + } + return &blockPath{ name: name, next: next, regexps: regexps, + code: code, }, nil } @@ -49,7 +57,7 @@ func (b *blockPath) ServeHTTP(rw http.ResponseWriter, req *http.Request) { for _, re := range b.regexps { if re.MatchString(currentPath) { - rw.WriteHeader(http.StatusForbidden) + rw.WriteHeader(b.code) return } } diff --git a/blockpath_test.go b/blockpath_test.go index 6171907..a1976c6 100644 --- a/blockpath_test.go +++ b/blockpath_test.go @@ -12,6 +12,7 @@ func TestNew(t *testing.T) { tests := []struct { desc string regexps []string + code *int expErr bool }{ { @@ -40,9 +41,12 @@ func TestNew(t *testing.T) { } func TestServeHTTP(t *testing.T) { + customCode := http.StatusNotFound + tests := []struct { desc string regexps []string + code *int reqPath string expNextCall bool expStatusCode int @@ -88,12 +92,29 @@ func TestServeHTTP(t *testing.T) { expNextCall: true, expStatusCode: http.StatusOK, }, + { + desc: "custom status code (unmatched)", + regexps: []string{"^/api/woof"}, + code: &customCode, + reqPath: "/foo/bar", + expNextCall: true, + expStatusCode: http.StatusOK, + }, + { + desc: "custom status code (matched)", + regexps: []string{"^/api/woof"}, + code: &customCode, + reqPath: "/api/woof", + expNextCall: false, + expStatusCode: customCode, + }, } for _, test := range tests { t.Run(test.desc, func(t *testing.T) { cfg := &Config{ Regex: test.regexps, + Code: test.code, } nextCall := false diff --git a/go.mod b/go.mod index f2064e2..51e0bc3 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,3 @@ module github.com/traefik/plugin-blockpath -go 1.15 +go 1.24