Compare commits
11 commits
Author | SHA1 | Date | |
---|---|---|---|
0a0fc645fc | |||
107c873b4b | |||
851ecb345a | |||
f4ceca90ab | |||
b4cff38dca | |||
7b5e1d0254 | |||
18a84b9b92 | |||
8d8f8b0c99 | |||
203438dc8c | |||
ceb7d04edd | |||
2fb1b35713 |
14 changed files with 193 additions and 181 deletions
81
.forgejo/workflows/build.yml
Normal file
81
.forgejo/workflows/build.yml
Normal file
|
@ -0,0 +1,81 @@
|
|||
name: Build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- beta
|
||||
- develop
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
checks:
|
||||
name: Checks
|
||||
runs-on: docker
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.23.x'
|
||||
check-latest: true
|
||||
- name: Run go fmt and go vet
|
||||
run: |
|
||||
go fmt $(go list ./...)
|
||||
go vet $(go list ./...)
|
||||
|
||||
code-coverage:
|
||||
name: Code Coverage
|
||||
runs-on: docker
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.23.x'
|
||||
check-latest: true
|
||||
- name: Run tests and generate coverage report
|
||||
run: |
|
||||
go test -covermode=count -coverprofile coverage.cov $(go list ./...)
|
||||
go tool cover -func=coverage.cov
|
||||
go tool cover -html=coverage.cov -o coverage.html
|
||||
- name: Upload coverage artifacts
|
||||
uses: https://code.forgejo.org/forgejo/upload-artifact@v4
|
||||
with:
|
||||
name: coverage-reports
|
||||
path: |
|
||||
coverage.cov
|
||||
coverage.html
|
||||
|
||||
build:
|
||||
name: Build
|
||||
runs-on: docker
|
||||
strategy:
|
||||
matrix:
|
||||
go:
|
||||
- GOOS: darwin
|
||||
GOARCH: amd64
|
||||
- GOOS: darwin
|
||||
GOARCH: arm64
|
||||
- GOOS: linux
|
||||
GOARCH: amd64
|
||||
- GOOS: linux
|
||||
GOARCH: arm64
|
||||
- GOOS: windows
|
||||
GOARCH: amd64
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.23.x'
|
||||
check-latest: true
|
||||
- name: Set environment variables
|
||||
run: |
|
||||
echo "GOOS=${{ matrix.go.GOOS }}" >> $GITHUB_ENV
|
||||
echo "GOARCH=${{ matrix.go.GOARCH }}" >> $GITHUB_ENV
|
||||
- name: Build
|
||||
run: go build .
|
20
.forgejo/workflows/release.yml
Normal file
20
.forgejo/workflows/release.yml
Normal file
|
@ -0,0 +1,20 @@
|
|||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- beta
|
||||
|
||||
jobs:
|
||||
release:
|
||||
name: Semantic Release
|
||||
runs-on: docker
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Semantic Release
|
||||
shell: bash
|
||||
run: |
|
||||
npm install -g semantic-release@23 conventional-changelog-conventionalcommits@7
|
||||
semantic-release
|
135
.gitlab-ci.yml
135
.gitlab-ci.yml
|
@ -1,135 +0,0 @@
|
|||
image: golang:1.19
|
||||
|
||||
stages:
|
||||
- test
|
||||
- build
|
||||
- pre-release
|
||||
|
||||
checks:
|
||||
stage: test
|
||||
script:
|
||||
- go fmt $(go list ./...)
|
||||
- go vet $(go list ./...)
|
||||
tags:
|
||||
- docker
|
||||
|
||||
code coverage:
|
||||
stage: test
|
||||
script:
|
||||
- go install honnef.co/go/tools/cmd/staticcheck@latest
|
||||
- go fmt $(go list ./...)
|
||||
- go vet $(go list ./...)
|
||||
- staticcheck ./...
|
||||
- go test -coverprofile coverage.cov -p 1 $(go list ./...)
|
||||
- go tool cover -html=coverage.cov -o coverage.html
|
||||
- go tool cover -func=coverage.cov
|
||||
coverage: '/\(statements\)\W+\d+\.\d+%/'
|
||||
artifacts:
|
||||
paths:
|
||||
- coverage.cov
|
||||
- coverage.html
|
||||
tags:
|
||||
- docker
|
||||
|
||||
codecov.io:
|
||||
stage: test
|
||||
script:
|
||||
- curl https://keybase.io/codecovsecurity/pgp_keys.asc | gpg --import
|
||||
- curl -Os https://uploader.codecov.io/latest/linux/codecov
|
||||
- curl -Os https://uploader.codecov.io/latest/linux/codecov.SHA256SUM
|
||||
- curl -Os https://uploader.codecov.io/latest/linux/codecov.SHA256SUM.sig
|
||||
- gpg --verify codecov.SHA256SUM.sig codecov.SHA256SUM
|
||||
- shasum -a 256 -c codecov.SHA256SUM
|
||||
- chmod +x codecov
|
||||
- go test -race -coverprofile=coverage.out -covermode=atomic
|
||||
- ./codecov -t ${CODECOV_TOKEN}
|
||||
rules:
|
||||
- if: $CODECOV_TOKEN
|
||||
when: on_success
|
||||
tags:
|
||||
- docker
|
||||
|
||||
# stage "sonarcloud" is only needed because of this issue:
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/issues/30632
|
||||
sonarcloud-check:
|
||||
stage: test
|
||||
needs:
|
||||
- checks
|
||||
image:
|
||||
name: sonarsource/sonar-scanner-cli:latest
|
||||
entrypoint: [""]
|
||||
variables:
|
||||
SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar" # Defines the location of the analysis task cache
|
||||
GIT_DEPTH: "0" # Tells git to fetch all the branches of the project, required by the analysis task
|
||||
cache:
|
||||
key: "${CI_JOB_NAME}"
|
||||
paths:
|
||||
- .sonar/cache
|
||||
script:
|
||||
- sonar-scanner
|
||||
tags:
|
||||
- docker
|
||||
allow_failure: true
|
||||
|
||||
# build template
|
||||
# execute the following command for all os/arch combinations: go tool dist list
|
||||
.compile:
|
||||
stage: build
|
||||
# no dependencies -> no download of artifacts from previous jobs/stages
|
||||
dependencies: []
|
||||
script:
|
||||
- go build .
|
||||
tags:
|
||||
- docker
|
||||
|
||||
darwin-amd64:
|
||||
extends: .compile
|
||||
variables:
|
||||
GOOS: "darwin"
|
||||
GOARCH: "amd64"
|
||||
|
||||
linux-amd64:
|
||||
extends: .compile
|
||||
variables:
|
||||
GOOS: "linux"
|
||||
GOARCH: "amd64"
|
||||
|
||||
linux-arm64:
|
||||
extends: .compile
|
||||
variables:
|
||||
GOOS: "linux"
|
||||
GOARCH: "arm64"
|
||||
|
||||
windows-amd64:
|
||||
extends: .compile
|
||||
variables:
|
||||
GOOS: "windows"
|
||||
GOARCH: "amd64"
|
||||
|
||||
.semantic-release:
|
||||
stage: pre-release
|
||||
image: node:20-buster-slim
|
||||
dependencies: []
|
||||
before_script:
|
||||
- apt-get update && apt-get install -y --no-install-recommends git-core ca-certificates
|
||||
- npm install -g semantic-release@23 @semantic-release/gitlab@13 conventional-changelog-conventionalcommits@7
|
||||
script:
|
||||
- semantic-release -d $DRY_RUN
|
||||
variables:
|
||||
GL_TOKEN: $SEMANTIC_RELEASE_TOKEN
|
||||
DRY_RUN: "false"
|
||||
tags:
|
||||
- docker
|
||||
|
||||
semantic-release-dry-run:
|
||||
extends: .semantic-release
|
||||
variables:
|
||||
DRY_RUN: "true"
|
||||
rules:
|
||||
- if: '$CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "beta"'
|
||||
|
||||
semantic-release:
|
||||
extends: .semantic-release
|
||||
rules:
|
||||
- if: '$CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "beta"'
|
||||
when: manual
|
|
@ -61,6 +61,12 @@
|
|||
}
|
||||
}
|
||||
],
|
||||
"@semantic-release/gitlab"
|
||||
[
|
||||
"@semantic-release/github",
|
||||
{
|
||||
"successCommentCondition": false,
|
||||
"failTitle": false
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
32
README.md
32
README.md
|
@ -1,17 +1,19 @@
|
|||
# goHTTPRouter
|
||||
# httprouter
|
||||
|
||||
[](https://git.martin-riedl.de/golang/httprouter/tags)
|
||||
[](https://git.martin-riedl.de/golang/httprouter/actions)
|
||||
[](https://godoc.org/gitlab.com/martinr92/gohttprouter)
|
||||
[](https://gitlab.com/martinr92/gohttprouter/commits/master)
|
||||
[](https://gitlab.com/martinr92/gohttprouter/commits/master)
|
||||
[](https://codecov.io/gl/martinr92/gohttprouter)
|
||||
[](https://goreportcard.com/report/gitlab.com/martinr92/gohttprouter)
|
||||
|
||||
goHTTPRouter is a framework used for HTTP request routing.
|
||||
httprouter is a framework used for HTTP request routing.
|
||||
|
||||
# Examples
|
||||
|
||||
## Simple Routing
|
||||
|
||||
Just replace the standard router of golang with this one:
|
||||
```golang
|
||||
import httprouter "gitlab.com/martinr92/gohttprouter/v3"
|
||||
import "git.martin-riedl.de/golang/httprouter/v4"
|
||||
```
|
||||
```golang
|
||||
router := httprouter.New()
|
||||
|
@ -22,9 +24,10 @@ err := http.ListenAndServe("localhost:8080", router)
|
|||
```
|
||||
|
||||
## Routing with placeholder
|
||||
|
||||
A path can also contain placeholder (like :id). If then a request is sent to the url "/user/123" the method gets executed and the URL part (in this case "123") is passed as parameter into your handler function.
|
||||
```golang
|
||||
import httprouter "gitlab.com/martinr92/gohttprouter/v3"
|
||||
import "git.martin-riedl.de/golang/httprouter/v4"
|
||||
```
|
||||
```golang
|
||||
router := httprouter.New()
|
||||
|
@ -38,11 +41,12 @@ err := http.ListenAndServe("localhost:8080", router)
|
|||
```
|
||||
|
||||
## Serve Static Content
|
||||
|
||||
Static files (like JavaScript or CSS) can be served automatically (including caching header and MIME type). It uses the `embed.FS` (since go 1.16) to serve static content.
|
||||
```golang
|
||||
import httprouter "gitlab.com/martinr92/gohttprouter/v3"
|
||||
import "git.martin-riedl.de/golang/httprouter/v4"
|
||||
|
||||
//go:embed files/statc/*
|
||||
//go:embed files/static/*
|
||||
var staticFiles embed.FS
|
||||
```
|
||||
```golang
|
||||
|
@ -51,9 +55,12 @@ router := httprouter.New()
|
|||
router.Handle(http.MethodGet, "/static/*", staticFS)
|
||||
```
|
||||
|
||||
For development purpose you can enable the local file serving additionally. The framework checks first, if the file exists locally and serves it directly. If not, the file is served from the `embed.FS`. This helps you during local development so you can modify a CSS file without recompiling everything.
|
||||
For development purpose you can enable the local file serving additionally.
|
||||
The framework checks first, if the file exists locally and serves it directly.
|
||||
If not, the file is served from the `embed.FS`.
|
||||
This helps you during local development so you can modify a CSS file without recompiling everything.
|
||||
```golang
|
||||
import httprouter "gitlab.com/martinr92/gohttprouter/v3"
|
||||
import "git.martin-riedl.de/golang/httprouter/v4"
|
||||
```
|
||||
```golang
|
||||
staticFS := httprouter.NewFS(&staticFiles)
|
||||
|
@ -62,8 +69,9 @@ staticFS.LocalFolderPrefix = "some/folder" // optional
|
|||
```
|
||||
|
||||
# License
|
||||
|
||||
```
|
||||
Copyright 2018-2021 Martin Riedl
|
||||
Copyright 2018-2025 Martin Riedl
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
|
4
fs.go
4
fs.go
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2021 Martin Riedl
|
||||
// Copyright 2021-2025 Martin Riedl
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package gohttprouter
|
||||
package httprouter
|
||||
|
||||
import (
|
||||
"embed"
|
||||
|
|
16
fs_test.go
16
fs_test.go
|
@ -1,4 +1,18 @@
|
|||
package gohttprouter
|
||||
// Copyright 2025 Martin Riedl
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package httprouter
|
||||
|
||||
import (
|
||||
"embed"
|
||||
|
|
2
go.mod
2
go.mod
|
@ -1,3 +1,3 @@
|
|||
module gitlab.com/martinr92/gohttprouter/v3
|
||||
module git.martin-riedl.de/golang/httprouter/v4
|
||||
|
||||
go 1.19
|
9
renovate.json
Normal file
9
renovate.json
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": [
|
||||
"local>ci/renovate//configs/base"
|
||||
],
|
||||
"baseBranches": [
|
||||
"develop"
|
||||
]
|
||||
}
|
8
route.go
8
route.go
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2018-2021 Martin Riedl
|
||||
// Copyright 2018-2025 Martin Riedl
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package gohttprouter
|
||||
package httprouter
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
@ -82,7 +82,7 @@ func (r *route) parsePath(path string, create bool) (*route, bool, map[string]st
|
|||
if !ok && !create {
|
||||
// no route found
|
||||
return nil, false, nil
|
||||
} else if !ok && create {
|
||||
} else if !ok {
|
||||
subRoute = newRoute()
|
||||
subRoute.parseName(subName)
|
||||
r.routes[subRoute.name] = subRoute
|
||||
|
@ -91,7 +91,7 @@ func (r *route) parsePath(path string, create bool) (*route, bool, map[string]st
|
|||
|
||||
// parse sub-route
|
||||
matchingRoute, created, subParameters := subRoute.parsePath(parts[1], create)
|
||||
return matchingRoute, (subRouteCreated || created), mergeParameterMaps(parameters, subParameters)
|
||||
return matchingRoute, subRouteCreated || created, mergeParameterMaps(parameters, subParameters)
|
||||
}
|
||||
|
||||
// last element in path
|
||||
|
|
|
@ -1,4 +1,18 @@
|
|||
package gohttprouter
|
||||
// Copyright 2025 Martin Riedl
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package httprouter
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
@ -59,7 +73,7 @@ func TestRoutePlaceholder(t *testing.T) {
|
|||
t.Error("error during placeholder name validation;", placeholderElement.placeholderName)
|
||||
}
|
||||
|
||||
// check path finder
|
||||
// check pathfinder
|
||||
foundRoute, _, foundParameters := route.parsePath("/user/123/home/martin", false)
|
||||
if foundRoute != homePathElement.routes[":"] {
|
||||
t.Error("wrong path element returned form path finding")
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2018-2021 Martin Riedl
|
||||
// Copyright 2018-2025 Martin Riedl
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package gohttprouter
|
||||
package httprouter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
@ -85,7 +85,7 @@ func (router *Router) findRoute(method string, path string, create bool) (route
|
|||
methodRoute, ok := router.registry[methodUpper]
|
||||
if !ok && !create {
|
||||
return nil, false, nil
|
||||
} else if !ok && create {
|
||||
} else if !ok {
|
||||
methodRoute = newRoute()
|
||||
router.registry[methodUpper] = methodRoute
|
||||
created = true
|
||||
|
|
|
@ -1,4 +1,18 @@
|
|||
package gohttprouter
|
||||
// Copyright 2025 Martin Riedl
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package httprouter
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
sonar.projectKey=martinr92_gohttprouter
|
||||
sonar.organization=martinr92
|
||||
|
||||
# This is the name and version displayed in the SonarCloud UI.
|
||||
#sonar.projectName=goHTTPRouter
|
||||
#sonar.projectVersion=1.0
|
||||
|
||||
# Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows.
|
||||
sonar.sources=.
|
||||
sonar.exclusions=**/*_test.go,coverage.cov,coverage.html
|
||||
|
||||
sonar.tests=.
|
||||
sonar.test.inclusions=**/*_test.go
|
||||
|
||||
# Encoding of the source code. Default is default system encoding
|
||||
#sonar.sourceEncoding=UTF-8
|
||||
|
||||
# Golang
|
||||
sonar.go.coverage.reportPaths=coverage.cov
|
Loading…
Add table
Reference in a new issue