Skip to content
Open
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
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ lcov.info
go.work

# Local .env files
*.local
*.local.idea/
13 changes: 12 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/lambda-feedback/shimmy

go 1.24.5
go 1.25

require (
github.com/aws/aws-lambda-go v1.46.0
Expand All @@ -23,12 +23,23 @@ require (
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/StackExchange/wmi v1.2.1 // indirect
github.com/deckarep/golang-set/v2 v2.6.0 // indirect
github.com/getkin/kin-openapi v0.138.0 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/swag v0.23.0 // indirect
github.com/gorilla/websocket v1.4.2 // indirect
github.com/holiman/uint256 v1.2.4 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/oasdiff/yaml v0.0.9 // indirect
github.com/oasdiff/yaml3 v0.0.12 // indirect
github.com/perimeterx/marshmallow v1.1.5 // indirect
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 // indirect
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/woodsbury/decimal128 v1.3.0 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
golang.org/x/crypto v0.24.0 // indirect
Expand Down
22 changes: 22 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,19 @@ github.com/ethereum/go-ethereum v1.14.5 h1:szuFzO1MhJmweXjoM5nSAeDvjNUH3vIQoMzzQ
github.com/ethereum/go-ethereum v1.14.5/go.mod h1:VEDGGhSxY7IEjn98hJRFXl/uFvpRgbIIf2PpXiyGGgc=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/getkin/kin-openapi v0.138.0 h1:ebfE0JAmF6AqHrNBy1KO3Fs68K9tPs48HalvLPo7Rv4=
github.com/getkin/kin-openapi v0.138.0/go.mod h1:vUYWaKyMqj7PfTybelXtLuLN9tReS12vxnzMRK+z2GY=
github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps=
github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c=
github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
Expand All @@ -48,6 +54,8 @@ github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU
github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E=
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs=
github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI=
github.com/knadh/koanf/parsers/json v0.1.0 h1:dzSZl5pf5bBcW0Acnu20Djleto19T0CfHcvZ14NJ6fU=
Expand All @@ -60,18 +68,28 @@ github.com/knadh/koanf/providers/file v0.1.0 h1:fs6U7nrV58d3CFAFh8VTde8TM262ObYf
github.com/knadh/koanf/providers/file v0.1.0/go.mod h1:rjJ/nHQl64iYCtAW2QQnF0eSmDEX/YZ/eNFj5yR6BvA=
github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8=
github.com/knadh/koanf/v2 v2.1.0/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY=
github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY=
github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc=
github.com/oasdiff/yaml v0.0.9 h1:zQOvd2UKoozsSsAknnWoDJlSK4lC0mpmjfDsfqNwX48=
github.com/oasdiff/yaml v0.0.9/go.mod h1:8lvhgJG4xiKPj3HN5lDow4jZHPlx1i7dIwzkdAo6oAM=
github.com/oasdiff/yaml3 v0.0.12 h1:75urAtPeDg2/iDEWwzNrLOWxI9N/dCh81nTTJtokt2M=
github.com/oasdiff/yaml3 v0.0.12/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/gomega v1.27.7 h1:fVih9JD6ogIiHUN6ePK7HJidyEDpWGVB5mzM7cWNXoU=
github.com/onsi/gomega v1.27.7/go.mod h1:1p8OOlwo2iUUDsHnOrjE5UKYJ+e3W8eQ3qSlRahPmr4=
github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s=
github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw=
github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
Expand All @@ -80,6 +98,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 h1:KRzFb2m7YtdldCEkzs6KqmJw4nqEVZGK7IN2kJkjTuQ=
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU=
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU=
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
Expand All @@ -96,6 +116,8 @@ github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+F
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
github.com/urfave/cli/v2 v2.27.1 h1:8xSQ6szndafKVRmfyeUMxkNUJQMjL1F2zmsZ+qHpfho=
github.com/urfave/cli/v2 v2.27.1/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
github.com/woodsbury/decimal128 v1.3.0 h1:8pffMNWIlC0O5vbyHWFZAt5yWvWcrHA+3ovIIjVWss0=
github.com/woodsbury/decimal128 v1.3.0/go.mod h1:C5UTmyTjW3JftjUFzOVhC20BEQa2a4ZKOB5I6Zjb+ds=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
Expand Down
45 changes: 44 additions & 1 deletion handler/mued.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package handler

import (
"encoding/json"
"fmt"
"io"
"net/http"

Expand All @@ -12,6 +13,8 @@ import (
"github.com/lambda-feedback/shimmy/runtime"
)

const muEdVersionHeader = "X-Api-Version"

type MuEdHandlerParams struct {
fx.In

Expand All @@ -37,6 +40,32 @@ func NewMuEdHandler(params MuEdHandlerParams) *MuEdHandler {
}
}

// checkMuEdVersion validates the X-Api-Version request header.
// Returns (resolvedVersion, true) on success, or writes a 406 and returns ("", false).
func (h *MuEdHandler) checkMuEdVersion(w http.ResponseWriter, r *http.Request) (string, bool) {
requested := r.Header.Get(muEdVersionHeader)
if requested != "" && !runtime.MuEdIsVersionSupported(requested) {
body, _ := json.Marshal(map[string]any{
"title": "API version not supported",
"message": fmt.Sprintf(
"The requested API version '%s' is not supported. Supported versions are: %v.",
requested, runtime.SupportedMuEdVersions,
),
"code": "VERSION_NOT_SUPPORTED",
"details": map[string]any{
"requestedVersion": requested,
"supportedVersions": runtime.SupportedMuEdVersions,
},
})
w.Header().Set(muEdVersionHeader, runtime.MuEdResolveVersion(requested))
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusNotAcceptable)
w.Write(body) //nolint:errcheck
return "", false
}
return runtime.MuEdResolveVersion(requested), true
}

func (h *MuEdHandler) checkAuth(w http.ResponseWriter, r *http.Request) bool {
if h.config.Auth.Key != "" && r.Header.Get("api-key") != h.config.Auth.Key {
h.log.Debug("unauthorized request", zap.String("path", r.URL.Path))
Expand All @@ -52,6 +81,11 @@ func (h *MuEdHandler) ServeEvaluate(w http.ResponseWriter, r *http.Request) {
return
}

version, ok := h.checkMuEdVersion(w, r)
if !ok {
return
}

if r.Method != http.MethodPost {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
Expand Down Expand Up @@ -136,6 +170,7 @@ func (h *MuEdHandler) ServeEvaluate(w http.ResponseWriter, r *http.Request) {
}

w.Header().Set("Content-Type", "application/json")
w.Header().Set(muEdVersionHeader, version)
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(feedback) //nolint:errcheck
}
Expand All @@ -146,6 +181,11 @@ func (h *MuEdHandler) ServeHealth(w http.ResponseWriter, r *http.Request) {
return
}

version, ok := h.checkMuEdVersion(w, r)
if !ok {
return
}

if r.Method != http.MethodGet {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
Expand All @@ -160,13 +200,16 @@ func (h *MuEdHandler) ServeHealth(w http.ResponseWriter, r *http.Request) {
return
}

result, ok := resp["result"]
legacyResult, ok := resp["result"].(map[string]any)
if !ok {
http.Error(w, "invalid health response", http.StatusInternalServerError)
return
}

result := runtime.MuEdToHealthResponse(legacyResult)

w.Header().Set("Content-Type", "application/json")
w.Header().Set(muEdVersionHeader, version)
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(result) //nolint:errcheck
}
115 changes: 114 additions & 1 deletion handler/mued_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ func TestMuEdServeEvaluate_Success(t *testing.T) {

assert.Equal(t, http.StatusOK, res.StatusCode)
assert.Equal(t, "application/json", res.Header.Get("Content-Type"))
assert.Equal(t, "0.1.0", res.Header.Get("X-Api-Version"))

var feedback []map[string]any
require.NoError(t, json.Unmarshal(body, &feedback))
Expand Down Expand Up @@ -277,10 +278,16 @@ func TestMuEdServeHealth_Success(t *testing.T) {

assert.Equal(t, http.StatusOK, res.StatusCode)
assert.Equal(t, "application/json", res.Header.Get("Content-Type"))
assert.Equal(t, "0.1.0", res.Header.Get("X-Api-Version"))

var result map[string]any
require.NoError(t, json.Unmarshal(raw, &result))
assert.Equal(t, true, result["tests_passed"])
assert.Equal(t, "OK", result["status"])
caps, ok := result["capabilities"].(map[string]any)
require.True(t, ok)
versions, ok := caps["supportedAPIVersions"].([]any)
require.True(t, ok)
assert.Contains(t, versions, "0.1.0")

mockRuntime.AssertExpectations(t)
}
Expand Down Expand Up @@ -323,3 +330,109 @@ func TestMuEdServeHealth_RuntimeError(t *testing.T) {
assert.Equal(t, http.StatusInternalServerError, w.Result().StatusCode)
mockRuntime.AssertExpectations(t)
}

// --- Version header tests (ServeEvaluate) ---

func TestMuEdServeEvaluate_AbsentVersionHeader(t *testing.T) {
mockHandler := new(MockHandler)
mockHandler.On("Handle", mock.Anything, mock.Anything).
Return(evalHandlerResponse(true, "ok"))

req := httptest.NewRequest(http.MethodPost, "/evaluate", bytes.NewReader(mathEvalBody(t)))
w := httptest.NewRecorder()

newMuEdHandler(mockHandler, nil, "").ServeEvaluate(w, req)

res := w.Result()
assert.Equal(t, http.StatusOK, res.StatusCode)
assert.Equal(t, "0.1.0", res.Header.Get("X-Api-Version"))
}

func TestMuEdServeEvaluate_SupportedVersionHeader(t *testing.T) {
mockHandler := new(MockHandler)
mockHandler.On("Handle", mock.Anything, mock.Anything).
Return(evalHandlerResponse(true, "ok"))

req := httptest.NewRequest(http.MethodPost, "/evaluate", bytes.NewReader(mathEvalBody(t)))
req.Header.Set("X-Api-Version", "0.1.0")
w := httptest.NewRecorder()

newMuEdHandler(mockHandler, nil, "").ServeEvaluate(w, req)

res := w.Result()
assert.Equal(t, http.StatusOK, res.StatusCode)
assert.Equal(t, "0.1.0", res.Header.Get("X-Api-Version"))
}

func TestMuEdServeEvaluate_UnsupportedVersionHeader(t *testing.T) {
mockHandler := new(MockHandler)

req := httptest.NewRequest(http.MethodPost, "/evaluate", bytes.NewReader(mathEvalBody(t)))
req.Header.Set("X-Api-Version", "99.0.0")
w := httptest.NewRecorder()

newMuEdHandler(mockHandler, nil, "").ServeEvaluate(w, req)

res := w.Result()
defer res.Body.Close()
raw, _ := io.ReadAll(res.Body)

assert.Equal(t, http.StatusNotAcceptable, res.StatusCode)
assert.Equal(t, "0.1.0", res.Header.Get("X-Api-Version"))

var body map[string]any
require.NoError(t, json.Unmarshal(raw, &body))
assert.Equal(t, "VERSION_NOT_SUPPORTED", body["code"])
details, ok := body["details"].(map[string]any)
require.True(t, ok)
assert.Equal(t, "99.0.0", details["requestedVersion"])

mockHandler.AssertNotCalled(t, "Handle", mock.Anything, mock.Anything)
}

// --- Version header tests (ServeHealth) ---

func TestMuEdServeHealth_AbsentVersionHeader(t *testing.T) {
healthResult := map[string]any{"tests_passed": true, "successes": []any{}, "failures": []any{}, "errors": []any{}}
mockRuntime := new(MockRuntime)
mockRuntime.On("Handle", mock.Anything, runtime.EvaluationRequest{
Command: runtime.CommandHealth,
Data: map[string]any{},
}).Return(runtime.EvaluationResponse{
"command": "healthcheck",
"result": healthResult,
}, nil)

req := httptest.NewRequest(http.MethodGet, "/evaluate/health", nil)
w := httptest.NewRecorder()

newMuEdHandler(nil, mockRuntime, "").ServeHealth(w, req)

res := w.Result()
assert.Equal(t, http.StatusOK, res.StatusCode)
assert.Equal(t, "0.1.0", res.Header.Get("X-Api-Version"))
mockRuntime.AssertExpectations(t)
}

func TestMuEdServeHealth_UnsupportedVersionHeader(t *testing.T) {
mockRuntime := new(MockRuntime)

req := httptest.NewRequest(http.MethodGet, "/evaluate/health", nil)
req.Header.Set("X-Api-Version", "99.0.0")
w := httptest.NewRecorder()

newMuEdHandler(nil, mockRuntime, "").ServeHealth(w, req)

res := w.Result()
defer res.Body.Close()
raw, _ := io.ReadAll(res.Body)

assert.Equal(t, http.StatusNotAcceptable, res.StatusCode)
assert.Equal(t, "0.1.0", res.Header.Get("X-Api-Version"))

var body map[string]any
require.NoError(t, json.Unmarshal(raw, &body))
assert.Equal(t, "VERSION_NOT_SUPPORTED", body["code"])

mockRuntime.AssertNotCalled(t, "Handle", mock.Anything, mock.Anything)
}
2 changes: 2 additions & 0 deletions internal/server/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ func Module(config HttpConfig) fx.Option {
return fx.Module("server",
// provide config
fx.Supply(config),
// provide openapi spec
fx.Provide(LoadOpenAPISpec),
// provide server
fx.Provide(NewLifecycleServer),
// invoke server
Expand Down
Loading
Loading