Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use http library instead of chi #48

Merged
merged 3 commits into from
Nov 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 9 additions & 10 deletions .github/workflows/checks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,33 +26,33 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Initialize CodeQL
uses: github/codeql-action/init@v3
uses: github/codeql-action/init@ea9e4e37992a54ee68a9622e985e60c8e8f12d9f # v3.27.4
with:
languages: go

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
uses: github/codeql-action/analyze@ea9e4e37992a54ee68a9622e985e60c8e8f12d9f # v3.27.4

UnitTests:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Install Go
uses: actions/setup-go@v5
uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0
with:
go-version: ${{ env.GO }}

- name: Run Unit Tests
run: go test -race -cover -coverprofile=coverage.out -covermode=atomic

- name: Codecov
uses: codecov/[email protected]
uses: codecov/codecov-action@985343d70564a82044c1b7fcb84c2fa05405c1a2 # v5.0.4
with:
file: ./coverage.out

Expand All @@ -61,15 +61,14 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Install Go
uses: actions/setup-go@v5
uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0
with:
go-version: ${{ env.GO }}

- name: Run GolangCi-Lint
uses: golangci/[email protected]
uses: golangci/golangci-lint-action@971e284b6050e8a5849b72094c50ab08da042db8 # v6.1.1
with:
version: latest
skip-build-cache: true
6 changes: 3 additions & 3 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ jobs:
DOCKER_CLI_EXPERIMENTAL: "enabled"
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Install Go
uses: actions/setup-go@v5
uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0
with:
go-version: ${{ env.GO }}

Expand All @@ -43,7 +43,7 @@ jobs:
password: ${{ secrets.DOCKER_HUB_TOKEN }}

- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v6
uses: goreleaser/goreleaser-action@9ed2f89a662bf1735a48bc8557fd212fa902bebf # v6.1.0
with:
version: latest
args: release --config .github/goreleaser-cli.yml
Expand Down
9 changes: 6 additions & 3 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ linters:
enable: # keep in ascending order
- asciicheck
- bodyclose
- copyloopvar
- dupl
- durationcheck
- err113
- exhaustive
- exportloopref
- gci
- goconst
- gocritic
- goerr113
- gofumpt
- goprintffuncname
- gosec
Expand Down Expand Up @@ -41,7 +41,10 @@ linters-settings:
disable:
- shadow
gci:
local-prefixes: github.com/sv-tools/mock-http-server
sections:
- standard
- default
- prefix(github.com/sv-tools/mock-http-server)
gocognit:
min-complexity: 15
gocyclo:
Expand Down
18 changes: 17 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,23 @@

A simple HTTP Server to be used for the unit or end-to-end or integrations tests.
* yaml based configuration, see an [example config file](example_config.yaml).
* docker image is published in this repo or docker hub
* docker image is published in this repo and on the docker hub

## Usage

```shell
docker run -p 8080:8080 -v $(pwd)/example_config.yaml:/config.yaml -e CONFIG=config.yaml ghcr.io/sv-tools/mock-http-server:latest
```

in second shell
```shell
curl http://localhost:8080/users -H"X-Request-Id: 123"
> {"id":1,"name":"John","id":2,"name":"Jane"}

curl http://localhost:8080/users/1 -H"X-Request-Id: 123"
> {"id":1,"name":"John"}
```


## License

Expand Down
26 changes: 22 additions & 4 deletions config.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package main

import (
"bytes"
"fmt"
"net/http"
"os"
"text/template"

"golang.org/x/exp/slog"
)
Expand All @@ -14,7 +17,6 @@ type Config struct {
}

type Route struct {
Method string `json:"method,omitempty" yaml:"method,omitempty"`
Pattern string `json:"pattern,omitempty" yaml:"pattern,omitempty"`
Responses []Response `json:"responses" yaml:"responses"`
}
Expand Down Expand Up @@ -53,8 +55,12 @@ func responsesWriter(responses []Response, log *slog.Logger) http.HandlerFunc {
http.Error(writer, err.Error(), http.StatusInternalServerError)
return
}
} else if response.Body != "" {
data = []byte(response.Body)
} else if body := response.Body; body != "" {
var err error
data, err = executeTemplate(body, request)
if err != nil {
panic(err)
}
}

for name, header := range response.Headers {
Expand All @@ -71,10 +77,22 @@ func responsesWriter(responses []Response, log *slog.Logger) http.HandlerFunc {

if len(data) > 0 {
if _, err := writer.Write(data); err != nil {
log.Error("sending response failed", err)
log.ErrorContext(request.Context(), "sending response failed", slog.String("error", err.Error()))
}
}
return
}
}
}

func executeTemplate(body string, request *http.Request) ([]byte, error) {
tmpl, err := template.New("response").Parse(body)
if err != nil {
return nil, fmt.Errorf("parse template failed: %w", err)
}
buf := bytes.NewBuffer(nil)
if err := tmpl.Execute(buf, request); err != nil {
return nil, fmt.Errorf("execute template failed: %w", err)
}
return buf.Bytes(), nil
}
5 changes: 0 additions & 5 deletions config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,6 @@
"items": {
"type": "object",
"properties": {
"method": {
"description": "The HTTP method, any of the standard or custom.",
"default": "GET",
"type": "string"
},
"pattern": {
"description": "An url pattern",
"default": "/",
Expand Down
34 changes: 25 additions & 9 deletions example_config.yaml
Original file line number Diff line number Diff line change
@@ -1,30 +1,46 @@
request_id_header: "X-Request-ID" # to be logged if present in the request headers
routes:
- method: get
pattern: /users
- pattern: GET /users # see https://go.dev/blog/routing-enhancements for more information about patterns
responses:
- code: 200
- code: 200 # first 3 responses: 200 OK
body: |
[
{
"name": "foo"
"id": 1,
"name": "John"
},
{
"name": "bar"
"id": 2,
"name": "Jane"
}
]
is_json: true
repeat: 3
- code: 500
- code: 500 # 4th response: 500 Internal Server Error
repeat: 1
body: "something is broken"
- code: 200
- code: 200 # all other responses: 200 OK
body: |
[
{
"name": "foo"
"id": 1,
"name": "John"
},
{
"name": "bar"
"id": 2,
"name": "Jane"
}
]
is_json: true
- pattern: GET /users/{id}
responses:
- code: 200
body: | # supports Go templates: https://pkg.go.dev/text/template
{
"id": "{{.PathValue "id"}}",
"name": "John"
}
is_json: true
repeat: 1
- code: 404
body: user "{{.PathValue "id"}}" not found
3 changes: 1 addition & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ module github.com/sv-tools/mock-http-server
go 1.23.0

require (
github.com/go-chi/chi/v5 v5.1.0
github.com/spf13/pflag v1.0.5
golang.org/x/exp v0.0.0-20240823005443-9b4947da3948
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f
gopkg.in/yaml.v3 v3.0.1
)
6 changes: 2 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw=
github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
golang.org/x/exp v0.0.0-20240823005443-9b4947da3948 h1:kx6Ds3MlpiUHKj7syVnbp57++8WpuKPcR5yjLBjvLEA=
golang.org/x/exp v0.0.0-20240823005443-9b4947da3948/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo=
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak=
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.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
Expand Down
Loading
Loading