swaggest / rest Goto Github PK
View Code? Open in Web Editor NEWWeb services with OpenAPI and JSON Schema done quick in Go
Home Page: https://pkg.go.dev/github.com/swaggest/rest
License: MIT License
Web services with OpenAPI and JSON Schema done quick in Go
Home Page: https://pkg.go.dev/github.com/swaggest/rest
License: MIT License
Parameters have to be documented in query
and formData
.
Describe the bug
Custom error message struct is not used for response validation errors.
To Reproduce
Try calling /validation API method from advanced example with X-Input = 44; returned error is
{
"status": "INTERNAL",
"error": "internal: bad response: validation failed",
"context": {
"header:X-Output": [
"#: must be <= 20/1 but found 44"
]
}
}
Expected behavior
Error message should be generated using customErr
.
Additional context
Input validation errors are formatted as expected:
$ curl --silent -X 'POST' 'http://localhost:8011/validation' -H 'accept: application/json' -H 'X-Input: 4' -H 'Content-Type: application/json' -d '{ "data": { "value": "string" } }'| jq
{
"msg": "invalid argument: validation failed",
"details": {
"header:X-Input": [
"#: must be >= 10/1 but found 4"
]
}
}
Is there a way to support uuid.UUID as a string with format uuid? I couldn't find an example on how some of the more advanced reflect stuff worked.
I also don't have access to the type, so i can't add extra tags to the properly because it's part of an underlying framework :'(
Describe the bug
I'm trying to build an enum type that can be used for input. As a part of this, I'd like to be able to set a default value for the enum field as well. I'd like to be able to define this in code (for reuse) rather than as a struct tag (i.e make our actual inputs/outputs match the documentation).
However, when I try to use a custom type with the default struct tags, it seems as though the parser expects a json string/object rather than a string value. You can use a json string to get past this, but then default does something weird. Concrete example below.
To Reproduce
package main_test
import (
"bytes"
"context"
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/swaggest/rest/web"
"github.com/swaggest/usecase"
)
type Discover string
const (
DiscoverAll Discover = "all"
DiscoverNone Discover = "none"
)
func (d *Discover) Enum() []any {
return []any{DiscoverAll, DiscoverNone}
}
func TestFoo(t *testing.T) {
type NewThing struct {
DiscoverMode *Discover `json:"discover,omitempty" default:"all"`
}
s := web.DefaultService()
s.Post("/foo", usecase.NewInteractor(func(ctx context.Context, input NewThing, output *string) error {
disc := string(*input.DiscoverMode)
*output = disc
return nil
}))
req, err := http.NewRequest(http.MethodPost, "/foo", bytes.NewReader([]byte(`{}`)))
require.NoError(t, err)
req.Header.Set("Content-Type", "application/json")
rw := httptest.NewRecorder()
s.ServeHTTP(rw, req)
assert.Equal(t, `"all" `, rw.Body.String())
}
Observed behavior
=== RUN TestFoo
--- FAIL: TestFoo (0.00s)
panic: DiscoverMode: parsing default as JSON: invalid character 'a' looking for beginning of value [recovered]
panic: DiscoverMode: parsing default as JSON: invalid character 'a' looking for beginning of value
Expected behavior
The API returns all
.
Side note: you can change this so it reads default:"\"all\""
-- then the input validation passes, but your default ends up as the quoted json string "all"
, not all
(i.e. it is not possible to produce the valid enum option).
--
I'm happy to make a contribution here if you can point me in the right direction. I did step through the code a bit. I tried Implementing a TextUn/Marshaller so that maybe the type would properly get set as a string in jsonschema-go/reflect.go
, but that didn't seem to make anything better on the version I was using. I believe it's because string is added as "a" type, rather than "the" SimpleType, which causes the checkInlineValue
to fall into the default
rather than String
case (where it does a json.Unmarshal
)
How to generate openapi.json file without using http.ListenAndServe to start the service.
I just want to use 'go run .' to generate an openapi.json file, not start a http service.
Describe the bug
According to
https://stackoverflow.com/questions/5258977/are-http-headers-case-sensitive
HTTP header names should be compared in a case-insensitive fashion.
With example input header definition
HeaderSecFetchSite string `header:"sec-fetch-site" required:"true"`
request with
Sec-Fetch-Site: same-origin
throws request validation failure with
"header:sec-fetch-site": [
"missing value"
]
Expected behavior
Requests with any of below should be passed:
sec-fetch-site: same-origin
Sec-Fetch-Site: same-origin
sEc-fEtCh-sitE: same-origin
It's a very common issue that someone might have a typo on an optional API endpoint's query
/json body object property
/url-encoded form field
, and since it doesn't match the correct one, it's ignored but doesn't necessarily need to fail in a noticeable way, therefore causing a silent error.
How can I set this?
I have these additional questions regarding validation:
Describe the bug
When HTTP request in canceled on client side, write in progress may fail with broken pipe
error.
GZIP middleware propagates this error using panic
.
To Reproduce
Open a browser page that makes many http requests to your server and close the window before the page is fully loaded.
panic: BUG: cannot close gzip writer: write tcp 127.0.0.1:8008->127.0.0.1:33666: write: broken pipe
-> github.com/swaggest/rest/response/gzip.Middleware.func1.1
-> /home/vearutop/go/pkg/mod/github.com/swaggest/[email protected]/response/gzip/middleware.go:34
github.com/swaggest/rest/response/gzip.Middleware.func1
/home/vearutop/go/pkg/mod/github.com/swaggest/[email protected]/response/gzip/middleware.go:40
net/http.HandlerFunc.ServeHTTP
/home/vearutop/sdk/gotip/src/net/http/server.go:2166
github.com/bool64/brick.NewBaseLocator.HTTPTraceTransaction.func6.1
/home/vearutop/go/pkg/mod/github.com/bool64/[email protected]/log/http.go:30
net/http.HandlerFunc.ServeHTTP
/home/vearutop/sdk/gotip/src/net/http/server.go:2166
go.opencensus.io/plugin/ochttp.(*Handler).ServeHTTP
/home/vearutop/go/pkg/mod/[email protected]/plugin/ochttp/server.go:92
github.com/bool64/brick/opencensus.Middleware.WithRouteTag.func2
/home/vearutop/go/pkg/mod/[email protected]/plugin/ochttp/route.go:40
....
Expected behavior
Probably such an error should be silently "swallowed", as there is nothing you can do with client resets.
Describe the bug
When Test
response header is defined using embedded struct like this
type MyEmbedded struct {
Test string `header:"Test" json:"-"`
}
type MyResponse struct {
MyEmbedded
Other string `json:"other"`
}
such header is not present in API response. No such problem when header is defined directly i.e.
type MyResponse struct {
Test string `header:"Test" json:"-"`
Other string `json:"other"`
}
Expected behavior
Response header defined using embedded struct should be present in response.
Hi,
I started to use this module in a project but I can't get most of the middlewares to work with the chi wrapper.
When I use the default chi router it works without problem (e.g with CORS and StipSlashes middlewares):
r := chi.NewRouter()
r.Use(
middleware.StripSlashes,
cors.Handler(cors.Options{
AllowedOrigins: "*",
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
AllowedHeaders: []string{"Accept", "Authorization", "Content-Type", "X-CSRF-Token"},
AllowCredentials: false,
MaxAge: 300,
})
)
But with the wrapper it does not, as I am getting CORSed on preflight requests and end slashes are not stripped:
r := chirouter.NewWrapper(chi.NewRouter())
r.Use(...) //Same as above
Do you have any idea why?
Can I use echo as my default router instead of chi?
[There was a discussion about having the ability to define multiple success status. As it was proposed in discussion and it seemed to possibly be forgotten, I'll add this here as an issue.]
It's easy to specify multiple error statuses with u.SetExpectedErrors(...)
, and I can override the "success" status with nethttp.SuccessStatus(http.StatusCreated)
when creating the handler. But: my API needs to return either 200 or 201 status based on some logic, with essentially the same JSON response.
I cannot find a way to do that nicely: I don't want to override the whole response serialization, and I don't think treating 200 or 201 as an "error" is the right approach. Any ideas?
My API spec defines that error responses must have a certain shape, which doesn't match the one that validatorFactory := jsonschema.NewFactory(apiSchema, apiSchema)
provides.
Is there a way to customise this?
Describe the bug
When validating an input with an incorrect type we get an failed to decode json: json: cannot unmarshall...
error instead of a validation failed
error with a context
object pointing to the issue. This is because the un-marshalling fails before the validator is even run.
To Reproduce
package main
import (
"bytes"
"context"
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/swaggest/rest/web"
"github.com/swaggest/usecase"
)
func TestFoo(t *testing.T) {
type TestInput struct {
TestString string `json:"testString" default:"valid" required:"true" minLength:"5" maxLength:"10" pattern:"^[a-z]+$"`
}
s := web.DefaultService()
s.Post("/foo", usecase.NewInteractor(func(ctx context.Context, input TestInput, output *string) error {
*output = input.TestString
return nil
}))
req, err := http.NewRequest(http.MethodPost, "/foo", bytes.NewReader([]byte(`{"testString":77}`)))
require.NoError(t, err)
req.Header.Set("Content-Type", "application/json")
rw := httptest.NewRecorder()
s.ServeHTTP(rw, req)
assert.Contains(t, rw.Body.String(), "validation failed")
assert.Equal(t, http.StatusBadRequest, rw.Code)
}
Expected behavior
I would expect a type mismatch issue to be reported in the same way as any other validation error to the end user
I'm trying to add a security operation to a subset of routes. However, the security
op isn't set on the paths.
s.Route("/github", func(r chi.Router) {
r.Group(func(r chi.Router) {
r.Use(sessionMiddleware, nethttp.SecurityMiddleware(s.OpenAPICollector, "User", openapi3.SecurityScheme{
APIKeySecurityScheme: &openapi3.APIKeySecurityScheme{
In: "cookie",
Name: appcfg.CookieName,
},
}))
r.Method(http.MethodGet, "/connect", nethttp.NewHandler(controllers.Connect(appcfg.GitHubAppSlug), nethttp.SuccessStatus(http.StatusTemporaryRedirect)))
r.Method(http.MethodGet, "/install", nethttp.NewHandler(controllers.Install(orgManager, clientCreator), nethttp.SuccessfulResponseContentType("text/html")))
})
})
Output of json (no security :()
"/github/connect": {
"get": {
"summary": "Connect",
"description": "Connect to GitHub",
"operationId": "function/controllers.Connect",
"responses": {
"307": {
"description": "Temporary Redirect",
"headers": {
"Location": {
"style": "simple",
"description": "Redirect to GitHub",
"schema": {
"type": "string",
"description": "Redirect to GitHub"
}
}
}
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RestErrResponse"
}
}
}
}
}
}
},
Describe the bug
Response content type in openapi.json
is application\json
regardless of DefaultSuccessResponseContentType
and DefaultErrorResponseContentType
introduced in #116.
To Reproduce
In any API project with success and error reponses set
response.DefaultSuccessResponseContentType = "application/dummy+json"
response.DefaultErrorResponseContentType = "application/problem+json"
and see application\json
as 200 and error response content type in generated openapi.json
.
Expected behavior
In openapi.json
200 response should have content type set with DefaultSuccessResponseContentType
and error responses should have content type set with DefaultErrorResponseContentType
.
Additional context
Actual 200 and error API response content types are equal to DefaultSuccessResponseContentType
and DefaultErrorResponseContentType
accordingly so it's fine.
Issue is only about response content types in openapi.json
.
Describe bug
According to #132 (comment) it's possible to define default type value with schema.WithDefault
like this
type SortDir string
func (s SortDir) PrepareJSONSchema(schema *jsonschema.Schema) error {
schema.Enum = []interface{}{"asc", "desc"}
schema.WithDefault("asc")
schema.WithExamples("desc")
return nil
}
type ItemListRequest struct {
[...]
SortDir SortDir `query:"sort_dir"`
}
but when
decoderFactory.ApplyDefaults = true
interactor input contains empty SortDir
field for request without sort_dir
specified (should be default value asc
). After changing
- SortDir SortDir `query:"sort_dir"`
+ SortDir SortDir `query:"sort_dir" default:"asc"`
request without sort_dir
specified in query generate SortDir
= asc
in interactor input.
Expected behavior
(1) SortDir
default value asc
should be applied for requests without sort_dir
in query when default value is specified using schema.WithDefault
(similar how default
field tag works).
(2) When both schema.WithDefault
and default
field tag are specified, openapi.json does not contain default
definition from tag, just schema reference #/components/schemas/SortDir
so default
definition from field tag should be ignored in such scenario probably but is not (as above).
Hey guys,
Very good project for swagger 3.x, really appreciated your work.
I'd like to create a server with v1 and v2 server url, so was trying to follow https://github.com/swaggest/rest/blob/master/_examples/mount/main.go example to mount endpoints under api/v1
, but has following error with service.Mount("/api/v1", apiV1)
:
panic: reflect API schema for GET /api/v1/sum: operation already exists: get /api/v1/sum
goroutine 1 [running]:
github.com/swaggest/rest/nethttp.OpenAPIMiddleware.func1({0x1012d9600?, 0x14000373920?})
/Users/267121010/go/pkg/mod/github.com/swaggest/[email protected]/nethttp/openapi.go:35 +0x1a8
I also tried to use
r := openapi31.NewReflector()
r.Spec.WithServers(
openapi31.Server{
URL: "/api/v1",
})
s := web.NewService(r)
s.Route("/data", func(r chi.Router) {
r.Group(func(r chi.Router) {
r.Use(serviceTokenAuth, serviceTokenDoc, checkSize)
r.Method(http.MethodPost, "/", nethttp.NewHandler(handler.GenericPost()))
r.Method(http.MethodPost, "/file-upload", nethttp.NewHandler(handler.FileUploader()))
})
})
s.Docs(“/docs”, swgui.New)
with this code I can see server url options in the swagger gui, but the actual endpoint logic is not correctly mapped to server selection. I'd expect to be able to call endpoint <url>/api/v1/data
, but the server is actually only listening on <url>/data
, the swagger GUI call test does show correct curl example <url>/api/v1/data
though.
Describe the bug
According to #113 valid JSON Content-Type is application/json
but swaggest accepts by default any value matching application/json*
pattern, i.e.
application/json; charset=utf-8
application/json123
Expected behavior
Only application/json
should be allowed by default; allowing incorrect deviations like application/json; charset=utf-8
may be allowed only when explicitly requested (with option similar to existing tolerateFormData
).
Additional context
https://www.hyrumslaw.com/
Similar to having header
field tags in output structure, we can have cookie
. However, cookies have more additional parameters that perhaps can be configured as field tag options, e.g. cookie="foo,httponly,path=/foo"
.
Describe the bug
According to go-chi/chi#194 ; charset=utf-8
should be removed from
https://github.com/swaggest/rest/blob/master/response/encoder.go#L143
https://github.com/swaggest/rest/blob/master/response/encoder.go#L199
Describe the bug
Currently, when OpenAPI schema is generated, any regular expressions are filtered out from URL pattern to make URL pattern compatible with OpenAPI.
To Reproduce
r.Get("/{token:^\\.}", usecase.ShortURL(deps))
Expected behavior
Such endpoint should produce token
parameter with "pattern":"^\."
.
Describe the bug
status.InvalidArgument
and status.FailedPrecondition
are different statuses but are mapped to the same http.StatusBadRequest
:
https://github.com/swaggest/rest/blob/master/error.go#L130
https://github.com/swaggest/usecase/blob/master/status/status.go#L97
Expected behavior
status.FailedPrecondition
should be mapped to http.StatusPreconditionFailed
.
Additional context
Related: #145
I would like to be able to return (when paginating) an array in the response body and the total count of the query in a header response X-Total-Count.
But If I set a struct for the response like for instance
// Declare output port type.
type helloOutput struct {
TotalCount int64 header:"X-Total-Count" json:"-"
Data []Vehicles json:"vehicles"
}
I need the response to be
[{
vehicle:1
},{
vehicle:2}
]
and NOT
{
data: [{
vehicle:1
},{
vehicle:2}
]
}
Is there any suggestion ?
Describe the bug
The tags on netip.Prefix
types get ignored when generating the OpenAPI spec.
To Reproduce
Here is a full example:
package main
import (
"context"
"net/http"
"net/netip"
"github.com/swaggest/rest/web"
"github.com/swaggest/swgui/v4emb"
"github.com/swaggest/usecase"
)
type Prefix struct {
ID uint64 `json:"id" readonly:"yes"`
Name string `json:"name" required:"true" example:"My Name" description:"Some human-readable name"`
Owner string `json:"owner" example:"[email protected]" format:"idn-email"`
Prefix netip.Prefix `json:"prefix" required:"true" example:"192.168.0.0/24" description:"Prefix in CIDR notation" format:"cidr"`
}
func getPrefixes() usecase.Interactor {
u := usecase.NewInteractor(func(ctx context.Context, _ struct{}, output *[]Prefix) error {
*output = append(*output, Prefix{
ID: 1,
Name: "Example name",
Owner: "[email protected]",
Prefix: netip.MustParsePrefix("10.0.0.0/8"),
})
return nil
})
return u
}
func main() {
service := web.DefaultService()
service.Get("/prefixes", getPrefixes())
service.Docs("/docs", v4emb.New)
if err := http.ListenAndServe("localhost:8080", service); err != nil {
panic(err)
}
}
When looking at the schema returned by http://localhost:8080/docs/openapi.json I see:
{
"…",
"components": {
"schemas": {
"NetipPrefix": {
"type": "string"
},
"Prefix": {
"required": [
"name",
"prefix"
],
"type": "object",
"properties": {
"id": {
"minimum": 0,
"type": "integer"
},
"name": {
"type": "string",
"description": "Some human-readable name",
"example": "My Name"
},
"owner": {
"type": "string",
"format": "idn-email",
"example": "[email protected]"
},
"prefix": {
"$ref": "#/components/schemas/NetipPrefix"
}
}
}
}
}
}
Expected behaviour
I expected to see my example
, description
and format
tags represented in the schema output.
I also didn't expect that the netip.Prefix would be represented as
"NetipPrefix": {
"type": "string"
}
but that's just an implementation detail I guess.
My preferred output would be to have the prefix
field documented as
"prefix": {
"type": "string",
"format": "cidr",
"description": "Prefix in CIDR notation",
"example": "[email protected]"
}
Describe the bug
If you move example album handling stuff from https://dev.to/vearutop/tutorial-developing-a-restful-api-with-go-json-schema-validation-and-openapi-docs-2490 to separate package say mypackage
and then (after exporting function names with capital letter) try to register interactors from main package with
service.Get("/albums", mypackage.GetAlbums())
service.Get("/albums/{id}", mypackage.GetAlbumByID())
service.Post("/albums", mypackage.PostAlbums(), nethttp.SuccessStatus(http.StatusCreated))
everything works ok. But if you decide to change getAlbumByIDInput.ID
to unexported getAlbumByIDInput.id
than you'll get panic on app start saying
panic: failed to reflect API schema for GET /albums/{id}: undefined path parameter: id
If you restore getAlbumByIDInput.ID
and add another query param say
type getAlbumByIDInput struct {
ID string `path:"id"`
important string `query:"important"`
}
no panics/warnings/errors will be thrown on start and important
param won't be visible in OpenAPI nor defined in interactor even if present in request url.
If it's expected - consider adding info in manual about correlation between field name exporting and corresponding parameter visibility in API.
I'm using this framework in some projects at work and really love it, but the rough edge I've run up could be me missing something.
In the go-chi world, it's common to have different routers mounted to parent routers. This is a way of separating out / differentiating the middlewares as part of the radix tree. Thus your middlewares can be applied closer to your domain objects in a way that makes sense.
With this library, I've struggled with this, specifically because of the documentation side. If I create a default router:
baseRouter := web.DefaultService()
But then try to add a sub router to it (for endpoints that require authentication via JWT for example)
baseRouter := web.DefaultService()
authenticated := web.DefaultService()
baseRouter.Mount("/authenticated",authenticated)
Will work but without documentation. If I force the sub router to have the same collector as the parent during construction the docs are present but missing the /authenticated
prefix from the mount.
I wrote Usecase as a workaround by basically allowing this kind of setup as the UseCase
implementation layer as well to allow for HTTP level globals and the further down the stack to a more implementation specific one.
Is there something I'm just missing about how the collector is supposed to be traversing nodes to generate the docs?
Describe the bug
When declaring struct with list i.e.
Strings []string `json:"strings"`
Ints []int `json:"ints"`
final openapi.json
has nullable: true
on these fields.
If it's intentional: how to declare list field that must exist in json and when without items must be like "strings": []
?
After configuring the UUID as follows:
uuidDef := jsonschema.Schema{}
uuidDef.AddType(jsonschema.String)
uuidDef.WithFormat("uuid")
uuidDef.WithExamples("248df4b7-aa70-47b8-a036-33ac447e668d")
s.OpenAPICollector.Reflector().AddTypeMapping(uuid.UUID{}, uuidDef)
s.OpenAPICollector.Reflector().InlineDefinition(uuid.UUID{})
The second occurrence of a UUID in the schemes has a nullable property.
First Occurrence which is working fine:
type Organisation struct {
es.BaseAggregateSourced
Avatar string `json:"avatar" required:"true"`
Name string `json:"name" required:"true"`
Url string `json:"url" required:"true"`
}
"AggregatesOrganisation": {
"required": [
"id",
"namespace",
"avatar",
"name",
"url"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"example": "248df4b7-aa70-47b8-a036-33ac447e668d"
},
Second occurrence which is wrong
type Repository struct {
es.BaseAggregateSourced
OrganisationId uuid.UUID `json:"organisation_id" format:"uuid" required:"true"`
Name string `json:"name" required:"true"`
FullName string `json:"full_name" required:"true"`
DefaultBranch string `json:"default_branch" required:"true"`
CreatedAt time.Time `json:"created_at" required:"true"`
Url string `json:"url" required:"true"`
ClusterId uuid.UUID `json:"cluster_id" format:"uuid" required:"true"`
PlanId uuid.UUID `json:"plan_id" format:"uuid" required:"true"`
}
"AggregatesRepository": {
"required": [
"id",
"namespace",
"organisation_id",
"name",
"full_name",
"default_branch",
"created_at",
"url",
"cluster_id",
"plan_id"
],
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid",
"nullable": true,
"example": "248df4b7-aa70-47b8-a036-33ac447e668d"
},
An endpoint may fail for different reasons with the same status code, e.g.:
It would be useful to be able to document multiple reasons an endpoint request can fail with the same status code. In my use case, the client can create a "prediction" via a JSON blob, and there are a million things that can be wrong with it, but most of them will be a BadRequest.
OpenAPI v3 supports this feature via oneOf
: https://stackoverflow.com/questions/36576447/swagger-specify-two-responses-with-same-code-based-on-optional-parameter
As a separate easier question, the interface for SetExpectedErrors
takes a list of errors, but there are implicit requirements for those errors to actually appear on the docs, e.g. a .Status() int
function. Would you be able to clarify what exactly do I need to implement to make this work? Cheers.
Describe the bug
When using a *uuid.UUID
type in a body request the Validator Middleware is panicing. (See stack trace below)
It only happens with a pointer, when using uuid.UUID
it works fine.
This bug was introduced between:
github.com/swaggest/openapi-go v0.2.44 => v0.2.43
^^ found this after creating the bug might need to move this to the other repo?
To Reproduce
Add a pointer to a uuid.UUID
In my models I have
type NewThing struct {
ParentId *uuid.UUID `json:"parent_id" required:"false"`
}
Expected behavior
It shouldn't panic, and the field should not be validated.
Additional context
Exception has occurred: panic
"reflect: Zero(nil)"
Stack:
2 0x0000000000525ba5 in reflect.Zero
at /usr/local/go/src/reflect/value.go:3222
3 0x00000000012c5a90 in github.com/swaggest/openapi-go/internal.ReflectRequestBody.func3
at /home/chris/go/pkg/mod/github.com/swaggest/[email protected]/internal/json_schema.go:127
4 0x00000000012a3a95 in github.com/swaggest/jsonschema-go.InterceptNullability.func1.1
at /home/chris/go/pkg/mod/github.com/swaggest/[email protected]/context.go:106
5 0x00000000012bc0b5 in github.com/swaggest/jsonschema-go.checkNullability.func1
at /home/chris/go/pkg/mod/github.com/swaggest/[email protected]/reflect.go:1183
7 0x00000000012bbfb3 in github.com/swaggest/jsonschema-go.checkNullability
at /home/chris/go/pkg/mod/github.com/swaggest/[email protected]/reflect.go:1233
8 0x00000000012b9abd in github.com/swaggest/jsonschema-go.(*Reflector).walkProperties
at /home/chris/go/pkg/mod/github.com/swaggest/[email protected]/reflect.go:1007
9 0x00000000012b7065 in github.com/swaggest/jsonschema-go.(*Reflector).kindSwitch
at /home/chris/go/pkg/mod/github.com/swaggest/[email protected]/reflect.go:721
10 0x00000000012b31d6 in github.com/swaggest/jsonschema-go.(*Reflector).reflect
at /home/chris/go/pkg/mod/github.com/swaggest/[email protected]/reflect.go:510
11 0x00000000012b0446 in github.com/swaggest/jsonschema-go.(*Reflector).Reflect
at /home/chris/go/pkg/mod/github.com/swaggest/[email protected]/reflect.go:284
12 0x00000000012c2fb3 in github.com/swaggest/openapi-go/internal.ReflectRequestBody
at /home/chris/go/pkg/mod/github.com/swaggest/[email protected]/internal/json_schema.go:172
13 0x000000000134cbcc in github.com/swaggest/openapi-go/openapi3.(*Reflector).parseRequestBody
at /home/chris/go/pkg/mod/github.com/swaggest/[email protected]/openapi3/reflect.go:323
14 0x000000000134bc5b in github.com/swaggest/openapi-go/openapi3.(*Reflector).setupRequest
at /home/chris/go/pkg/mod/github.com/swaggest/[email protected]/openapi3/reflect.go:246
15 0x000000000135209d in github.com/swaggest/openapi-go/openapi3.(*Reflector).WalkRequestJSONSchemas
at /home/chris/go/pkg/mod/github.com/swaggest/[email protected]/openapi3/walk_schema.go:108
16 0x00000000013afd84 in github.com/swaggest/rest/openapi.(*Collector).ProvideRequestJSONSchemas
at /home/chris/go/pkg/mod/github.com/swaggest/[email protected]/openapi/collector.go:516
17 0x00000000013d8f97 in github.com/swaggest/rest/jsonschema.Factory.MakeRequestValidator
at /home/chris/go/pkg/mod/github.com/swaggest/[email protected]/jsonschema/validator.go:58
18 0x00000000013db2e9 in github.com/swaggest/rest/jsonschema.(*Factory).MakeRequestValidator
at <autogenerated>:1
19 0x00000000013f6417 in github.com/swaggest/rest/request.ValidatorMiddleware.func1
at /home/chris/go/pkg/mod/github.com/swaggest/[email protected]/request/middleware.go:87
20 0x00000000013b3347 in github.com/swaggest/rest/nethttp.WrapHandler
at /home/chris/go/pkg/mod/github.com/swaggest/[email protected]/nethttp/wrap.go:16
21 0x00000000013b6a4c in github.com/swaggest/rest/chirouter.(*Wrapper).prepareHandler
at /home/chris/go/pkg/mod/github.com/swaggest/[email protected]/chirouter/wrapper.go:223
22 0x00000000013b5fff in github.com/swaggest/rest/chirouter.(*Wrapper).Method
at /home/chris/go/pkg/mod/github.com/swaggest/[email protected]/chirouter/wrapper.go:147
23 0x00000000013fc716 in github.com/swaggest/rest/web.(*Service).Post
at /home/chris/go/pkg/mod/github.com/swaggest/[email protected]/web/service.go:152
24 0x000000000140637e in function/handler.NewHandler
at /home/chris/workspace/getnoops/dev/config/handler/handler.go:111
25 0x0000000001724f8e in main.main
at /home/chris/workspace/getnoops/dev/config/main.go:19
Describe the bug
Data Schema's not showing on swagger docs site. Usually the schema is near the bottom. The json schema looks correct
To Reproduce
git clone https://github.com/swaggest/rest.git
cd /home/david/src/swaggest_ex/_examples/advanced-generic-openapi31
go get ./..
go run .
Expected behavior
At the bottom of the docs site there should be a section for schema
Describe the bug
When declaring struct with list i.e.
Comments []string `json:"comments" required:"true"`
Keys []int `json:"ints" required:"true" minItems:"1"`
final openapi.json has nullable: true
on these fields. Using usecase.Interactor
it seems that there is no way to indicate those fields as non-nullable.
Expected behavior
Required lists should not be nullable.
Currently gzip
middleware hides http.Hijacker
and prevents connection upgrade.
Hi first let me say thank you for building these awesome api toolkits (rest & openapi)!
Great work :)
Right now I can't find out how describe that some endpoints are protected with JWT Bearer tokens and that I offer several URLs for oauth2 flows.
Are there any examples that show how to secure an API using swaggest/rest and generate the corresponding openapi specs etc?
I want to seperate concerns between usecases and transport it, so I tried nethttp.RequestMapping() as shown on README.md.
But I found it doesn't work for json body, and I started debug the package.
package rest has 6 const ParamIn
const (
// ParamInPath indicates path parameters, such as `/users/{id}`.
ParamInPath = ParamIn("path")
// ParamInQuery indicates query parameters, such as `/users?page=10`.
ParamInQuery = ParamIn("query")
// ParamInBody indicates body value, such as `{"id": 10}`.
ParamInBody = ParamIn("body")
// ParamInFormData indicates body form parameters.
ParamInFormData = ParamIn("formData")
// ParamInCookie indicates cookie parameters, which are passed ParamIn the `Cookie` header,
// such as `Cookie: debug=0; gdpr=2`.
ParamInCookie = ParamIn("cookie")
// ParamInHeader indicates header parameters, such as `X-Header: value`.
ParamInHeader = ParamIn("header")
)
But in RequestMapping
// RequestMapping creates rest.RequestMapping from struct tags.
//
// This can be used to decouple mapping from usecase input with additional struct.
func RequestMapping(v interface{}) func(h *Handler) {
return func(h *Handler) {
m := make(rest.RequestMapping)
for _, in := range []rest.ParamIn{
rest.ParamInFormData,
rest.ParamInQuery,
rest.ParamInHeader,
rest.ParamInPath,
rest.ParamInCookie,
} {
mm := make(map[string]string)
refl.WalkTaggedFields(reflect.ValueOf(v), func(v reflect.Value, sf reflect.StructField, tag string) {
mm[sf.Name] = tag
}, string(in))
if len(mm) > 0 {
m[in] = mm
}
}
if len(m) > 0 {
h.ReqMapping = m
}
}
}
only 5 of them are used without body for json input. I wonder is this intended.
I've been prototyping a project using this rest framework, but we've noticed that there's no support for OpenAPI specification extensions. These extensions allow service owners to add additional fields to the OpenAPI spec, provided that they are prefixed by x-
(for example x-internal
) and are quite useful when integrating an OpenAPI spec with other platforms and tools.
https://swagger.io/specification/#specification-extensions
In my use case, I have some automation that we want to use with my generated openapi spec file, however this automation relies on the existence of some specification extensions. Would it be possible to extend the IOInteractor with basic support for extensions?
In the process of migrating a project over to use this collection of modules, and was wondering if you may have any recommendations for handling non-json response types. So far it looks like I may have to build my own response encoder to take the output
interface and render it properly, but I feel like that's boiling the ocean.
Any insight would be much appreciated, this module has solved so many problems for our project!
Hi! I'm trying to build a custom error middleware and I noticed that I'm getting some validation errors squashed into one item.
I got:
[
"#: missing properties: \"foo\", \"bar\""
]
while I was expecting:
[
"missing property: \"foo\"",
"missing property:\"bar\""
]
when calling Fields()
. Is that something I could easily override or setup?
Describe the bug
Accrording to #119 header names should be compared in case insensitive fashion.
When ETag response header is defined with ETag
canonical name
ETag string `header:"ETag" json:"-" required:"true"`
response validation error is thrown (missing etag header value) even if ETag
field is populated in response struct. No such error when response struct is defined with Etag
header name
ETag string `header:"Etag" json:"-" required:"true"`
Expected behavior
No response validation error thrown when header:"ETag"
is used in struct definition.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.