Compare commits

..

No commits in common. "main" and "v3.0.0-beta.2" have entirely different histories.

14 changed files with 181 additions and 193 deletions

View file

@ -1,81 +0,0 @@
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 .

View file

@ -1,20 +0,0 @@
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 Normal file
View file

@ -0,0 +1,135 @@
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

View file

@ -61,12 +61,6 @@
}
}
],
[
"@semantic-release/github",
{
"successCommentCondition": false,
"failTitle": false
}
]
"@semantic-release/gitlab"
]
}

View file

@ -1,19 +1,17 @@
# httprouter
[![release](https://git.martin-riedl.de/golang/httprouter/badges/release.svg)](https://git.martin-riedl.de/golang/httprouter/tags)
[![pipeline status](https://git.martin-riedl.de/golang/httprouter/badges/workflows/build.yml/badge.svg)](https://git.martin-riedl.de/golang/httprouter/actions)
# goHTTPRouter
[![GoDoc](https://godoc.org/gitlab.com/martinr92/gohttprouter?status.svg)](https://godoc.org/gitlab.com/martinr92/gohttprouter)
[![pipeline status](https://gitlab.com/martinr92/gohttprouter/badges/master/pipeline.svg)](https://gitlab.com/martinr92/gohttprouter/commits/master)
[![coverage report](https://gitlab.com/martinr92/gohttprouter/badges/master/coverage.svg)](https://gitlab.com/martinr92/gohttprouter/commits/master)
[![codecov](https://codecov.io/gl/martinr92/gohttprouter/branch/master/graph/badge.svg)](https://codecov.io/gl/martinr92/gohttprouter)
[![Go Report Card](https://goreportcard.com/badge/gitlab.com/martinr92/gohttprouter)](https://goreportcard.com/report/gitlab.com/martinr92/gohttprouter)
httprouter is a framework used for HTTP request routing.
goHTTPRouter is a framework used for HTTP request routing.
# Examples
## Simple Routing
Just replace the standard router of golang with this one:
```golang
import "git.martin-riedl.de/golang/httprouter/v4"
import httprouter "gitlab.com/martinr92/gohttprouter/v3"
```
```golang
router := httprouter.New()
@ -24,10 +22,9 @@ 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 "git.martin-riedl.de/golang/httprouter/v4"
import httprouter "gitlab.com/martinr92/gohttprouter/v3"
```
```golang
router := httprouter.New()
@ -41,12 +38,11 @@ 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 "git.martin-riedl.de/golang/httprouter/v4"
import httprouter "gitlab.com/martinr92/gohttprouter/v3"
//go:embed files/static/*
//go:embed files/statc/*
var staticFiles embed.FS
```
```golang
@ -55,12 +51,9 @@ 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 "git.martin-riedl.de/golang/httprouter/v4"
import httprouter "gitlab.com/martinr92/gohttprouter/v3"
```
```golang
staticFS := httprouter.NewFS(&staticFiles)
@ -69,9 +62,8 @@ staticFS.LocalFolderPrefix = "some/folder" // optional
```
# License
```
Copyright 2018-2025 Martin Riedl
Copyright 2018-2021 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
View file

@ -1,4 +1,4 @@
// Copyright 2021-2025 Martin Riedl
// Copyright 2021 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 httprouter
package gohttprouter
import (
"embed"

View file

@ -1,18 +1,4 @@
// 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
package gohttprouter
import (
"embed"

2
go.mod
View file

@ -1,3 +1,3 @@
module git.martin-riedl.de/golang/httprouter/v4
module gitlab.com/martinr92/gohttprouter/v3
go 1.19

View file

@ -1,9 +0,0 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"local>ci/renovate//configs/base"
],
"baseBranches": [
"develop"
]
}

View file

@ -1,4 +1,4 @@
// Copyright 2018-2025 Martin Riedl
// Copyright 2018-2021 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 httprouter
package gohttprouter
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 {
} else if !ok && create {
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

View file

@ -1,18 +1,4 @@
// 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
package gohttprouter
import (
"testing"
@ -73,7 +59,7 @@ func TestRoutePlaceholder(t *testing.T) {
t.Error("error during placeholder name validation;", placeholderElement.placeholderName)
}
// check pathfinder
// check path finder
foundRoute, _, foundParameters := route.parsePath("/user/123/home/martin", false)
if foundRoute != homePathElement.routes[":"] {
t.Error("wrong path element returned form path finding")

View file

@ -1,4 +1,4 @@
// Copyright 2018-2025 Martin Riedl
// Copyright 2018-2021 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 httprouter
package gohttprouter
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 {
} else if !ok && create {
methodRoute = newRoute()
router.registry[methodUpper] = methodRoute
created = true

View file

@ -1,18 +1,4 @@
// 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
package gohttprouter
import (
"net"

19
sonar-project.properties Normal file
View file

@ -0,0 +1,19 @@
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