long2ice / swagin Goto Github PK
View Code? Open in Web Editor NEWSwagger + Gin = SwaGin, a web framework based on Gin and Swagger
Home Page: https://swagin.long2ice.io/docs
License: Apache License 2.0
Swagger + Gin = SwaGin, a web framework based on Gin and Swagger
Home Page: https://swagin.long2ice.io/docs
License: Apache License 2.0
Dear @long2ice,
I stumbled across your interseting article as I was searching for a manner in which to serve an openapi.yaml
swagger API instance using Gin
. Thank you for taking the time to write such an in-depth article.
When running the command go get -u github.com/long2ice/swagin
it returns with the following error:
$ go get -u github.com/long2ice/swagin
go: downloading github.com/getkin/kin-openapi v0.80.0
# github.com/long2ice/swagin/router
/home/ben/go/pkg/mod/github.com/long2ice/[email protected]/router/router.go:31:14: c.ShouldBindRequest undefined (type *gin.Context has no field or method ShouldBindRequest)
When following the error, it leads me to the below function in router/router.go
:
func BindModel(api IAPI) gin.HandlerFunc {
return func(c *gin.Context) {
if err := c.ShouldBindRequest(api); err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.Next()
}
}
which is strange because when reading about gin.Context
it takes you here:
// Context is the most important part of gin. It allows us to pass variables between middleware,
// manage the flow, validate the JSON of a request and render a JSON response for example.
type Context struct {
...
)
Prior to having tried this I followed your guide and had quite a few errors. I then used the code that you had in: swagin/examples/
instead and got the exact same mistake as is already outlined here above.
If you could please be so kind as to help me with this it'll be greatly appreciated :)
Furthermore, the reason I'm wanting to make use of your repository - and as mentioned earlier - is because I want to serve my already generated openapi.yaml
file using your repo. Is it possible to read a static yaml
specification as opposed to a json
specification? If so, how exactly would one go about this?
Lastly, I'm not wanting to serve the openapi
spec with the redoc
method but rather the swagger
method and as per this link: https://swagin.long2ice.io/docs
Thanks in advance for your appreciated assistance.
Kind regards,
Status code description is duplicated on all codes as shown in screenshot below:
Router is defined as follows:
var DeployProject = router.New(
&DeployProjectInput{},
router.Summary("Deploy Project"),
router.Description("Deploy project for given configuration"),
router.Responses(router.Response{
"204": router.ResponseItem{
Model: model.Created{},
Description: "Project created",
},
"400": router.ResponseItem{
Model: model.BadRequest{},
Description: "Bad request",
},
"404": router.ResponseItem{
Model: model.NotFound{},
Description: "Not found",
},
"500": router.ResponseItem{
Model: model.InternalServerError{},
Description: "Error response",
},
}),
)
`panic: reflect: call of reflect.Value.Field on zero Value
goroutine 51 [running]:
reflect.Value.Field({0x0?, 0x0?, 0x0?}, 0x0?)
/usr/local/go/src/reflect/value.go:1220 +0xef
github.com/long2ice/swagin/swagger.(*Swagger).getResponseSchemaByModel(0xc0009bb8b0?, {0xe5a400?, 0x0})
/home/yt/go/pkg/mod/github.com/long2ice/[email protected]/swagger/swagger.go:190 +0x55a
github.com/long2ice/swagin/swagger.(*Swagger).getSchemaByType(0xe5a400?, {0xe5a400?, 0x0}, 0x0)
/home/yt/go/pkg/mod/github.com/long2ice/[email protected]/swagger/swagger.go:110 +0x66b
github.com/long2ice/swagin/swagger.(*Swagger).getResponseSchemaByModel(0xf8a2a0?, {0x1053fc0?, 0xc00061f560})
/home/yt/go/pkg/mod/github.com/long2ice/[email protected]/swagger/swagger.go:191 +0x57a
github.com/long2ice/swagin/swagger.(*Swagger).getResponses(0xc0009bbd18?, 0xc0009abd70?, {0x0, 0x0})
/home/yt/go/pkg/mod/github.com/long2ice/[email protected]/swagger/swagger.go:228 +0x20a
github.com/long2ice/swagin/swagger.(*Swagger).getPaths(0xc000178a80)
/home/yt/go/pkg/mod/github.com/long2ice/[email protected]/swagger/swagger.go:333 +0x20d
github.com/long2ice/swagin/swagger.(*Swagger).BuildOpenAPI(0xc000178a80)
/home/yt/go/pkg/mod/github.com/long2ice/[email protected]/swagger/swagger.go:380 +0x214
github.com/long2ice/swagin.(*SwaGin).init(0xc00009edc0)
/home/yt/go/pkg/mod/github.com/long2ice/[email protected]/swagin.go:150 +0x33c
github.com/long2ice/swagin.(*SwaGin).Run(0xc00009edc0, {0xc0009bbf90, 0x1, 0x1})
/home/yt/go/pkg/mod/github.com/long2ice/[email protected]/swagin.go:196 +0x45
exit status 2
make: *** [Makefile:27: run] Error 1`
When I try to build example in its own directory, I get:
$ go build
# github.com/long2ice/swagin/router
../../.go/pkg/mod/github.com/long2ice/[email protected]/router/router.go:31:14: c.ShouldBindRequest undefined (type *gin.Context has no field or method ShouldBindRequest)
Swagin code calls method ShouldBindRequest() on Gin context but it doesn't exist in Gin code on official repository. This is defined in a fork on long2ice repository.
File go.mod is as follows (generated with go mod tidy
):
module test
go 1.17
require (
github.com/getkin/kin-openapi v0.88.0
github.com/gin-contrib/cors v1.3.1
github.com/gin-gonic/gin v1.7.4
github.com/long2ice/swagin v0.1.0
)
require (
github.com/fatih/structtag v1.2.0 // indirect
github.com/ghodss/yaml v1.0.0 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/swag v0.19.5 // indirect
github.com/go-playground/locales v0.13.0 // indirect
github.com/go-playground/universal-translator v0.17.0 // indirect
github.com/go-playground/validator/v10 v10.4.1 // indirect
github.com/golang/protobuf v1.3.3 // indirect
github.com/json-iterator/go v1.1.9 // indirect
github.com/leodido/go-urn v1.2.0 // indirect
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e // indirect
github.com/mattn/go-isatty v0.0.12 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 // indirect
github.com/ugorji/go/codec v1.1.7 // indirect
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e // indirect
gopkg.in/yaml.v2 v2.3.0 // indirect
)
What is strange, is that it works if, in the Swagin project, I run:
$ cd examples
$ go build
In following example:
package main
import (
"github.com/gin-gonic/gin"
"github.com/long2ice/swagin"
"github.com/long2ice/swagin/router"
"github.com/long2ice/swagin/swagger"
)
func main() {
app := swagin.New(swagger.New("SwaGin", "Swagger + Gin = SwaGin", "0.1.0"))
app.GET("/", test)
if err := app.Run(); err != nil {
panic(err)
}
}
var test = router.New(
&Test{},
router.Summary("Test query"),
router.Description("Test query model"),
)
type Test struct{
Authorization string `header:"authorization" binding:"required" json:"authorization" default:"authorization"`
Token string `header:"token" binding:"required" json:"token" default:"token"`
}
func (t *Test) Handler(ctx *gin.Context) {
println(">>>>>>>>>> authorization:", t.Authorization)
println(">>>>>>>>>> token:", t.Token)
}
I require two headers in request (Token and Authorization). They are both listed in documentation (at URL /docs) and I can set them to perform request. But validation fails for header Authorization which is missing, while Token is sent and received. Furthermore, in CURL example request Authorization header is missing while Token is set.
In my opinion, both headers should be sent. Why is Authorization missing?
This seems to be a collision with authorization bechanism in SwaGin, as it works fine with other headers.
❯ go get -u github.com/long2ice/swagin
go: downloading github.com/long2ice/swagin v0.1.0
go: downloading github.com/getkin/kin-openapi v0.72.0
go: downloading github.com/getkin/kin-openapi v0.81.0
go: downloading github.com/ghodss/yaml v1.0.0
go: downloading github.com/go-openapi/swag v0.19.5
go: downloading github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e
# github.com/long2ice/swagin/router
../../go/pkg/mod/github.com/long2ice/[email protected]/router/router.go:31:14: c.ShouldBindRequest undefined (type *gin.Context has no field or method ShouldBindRequest)
Hey everyone, wanted to see if there was any plan for a new release? It looks like the last release was in Sep 2021 and a lot has gone into the repo since then :)
When a panic is raised in an handler, server doesn't catch and manage this panic to return a status 500 (Internal Server Error) response. Instead, it returns nothing to the client. This is demonstrated with this code:
package main
import (
"github.com/gin-gonic/gin"
"github.com/long2ice/swagin"
"github.com/long2ice/swagin/router"
"github.com/long2ice/swagin/swagger"
)
func main() {
app := swagin.New(swagger.New("SwaGin", "Swagger + Gin = SwaGin", "0.1.0"))
app.GET("/", test)
if err := app.Run(); err != nil {
panic(err)
}
}
var test = router.New(
&Test{},
router.Summary("Test query"),
router.Description("Test query model"),
)
type Test struct{}
func (t *Test) Handler(ctx *gin.Context) {
panic("test")
}
This can be fixed adding a recovery handler to the Gin engine. This handler will trap the panic and return appropriate response to client.
Quick question, is there a way to enable a "hot reload" kind of option? I'd read that gin run main.go --all
does that trick when using the gin package directly, but I was not able to get that to work inside swagin
I'm very new at Go and this package is helping me a lot moving from python (FastAPI) to Go, great work!!!
This is more a question than an actual issue, but I think it is important to provide code samples to distribute the API docs directly in production, is there a way to use code sample objects? if anyone can point me in the right direction I can work in this functionality, as the official docs this object works like this in the API definition:
openapi: '3.0'
info: ...
tags: [...]
paths:
/example:
get:
summary: Example summary
description: Example description
operationId: examplePath
responses: [...]
parameters: [...]
x-codeSamples:
- lang: 'cURL'
label: 'CLI'
source: |
curl --request POST \
--url 'https://data.apiexample.com/api/example/batch_query/json?format=json' \
--header 'content-type: application/octet-stream: ' \
--data '{}'
This bug is related to the request value that is shared among all the requests. This crashed application when the request value is modified as in the example code. This is demonstrated in example application in the archive.
To run test, you must install test tool Hey. Then you can run application with make run
and run test with make test
.
The application will crash with a message like this:
fatal error: concurrent map iteration and map write
This is due to the fact that the request value is shared among all the requests. The request value is modified in the handler function and this causes the crash.
In following example:
package main
import (
"log"
"github.com/gin-gonic/gin"
"github.com/long2ice/swagin"
"github.com/long2ice/swagin/router"
"github.com/long2ice/swagin/swagger"
)
func main() {
app := swagin.New(NewSwagger())
group := app.Group("", swagin.Handlers(GroupHandler))
group.GET("/", test)
if err := app.Run(); err != nil {
panic(err)
}
}
func GroupHandler(ctx *gin.Context) {
log.Println(">>> in group handler")
}
func RouterHandler(ctx *gin.Context) {
log.Println(">>> in router handler")
}
var test = router.New(
&Test{},
router.Summary("Test query"),
router.Description("Test query model"),
router.Handlers(RouterHandler),
)
type Test struct{}
func (t *Test) Handler(ctx *gin.Context) {
log.Println(">>> in handler")
}
func NewSwagger() *swagger.Swagger {
return swagger.New("SwaGin", "Swagger + Gin = SwaGin", "0.1.0")
}
You would expect following ordering for handlers:
But when you run it, you get in logs:
2022/02/17 11:47:35 >>> in router handler
2022/02/17 11:47:35 >>> in group handler
2022/02/17 11:47:35 >>> in handler
Which means that the group handler runs after the router handler. In my opinion we should see in logs:
2022/02/17 11:47:35 >>> in group handler
2022/02/17 11:47:35 >>> in router handler
2022/02/17 11:47:35 >>> in handler
Let's consider following example code:
package main
import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/long2ice/swagin"
"github.com/long2ice/swagin/router"
"github.com/long2ice/swagin/swagger"
)
func main() {
app := swagin.New(swagger.New("SwaGin", "Swagger + Gin = SwaGin", "0.1.0"))
app.GET("/", test)
if err := app.Run(); err != nil {
panic(err)
}
}
var test = router.New(
&Input{},
router.Summary("Test query"),
router.Description("Test query model"),
router.Responses(router.Response{
"200": router.ResponseItem{
Model: Response{},
Description: "Bug",
},
}),
)
type Input struct{}
type Response struct {
Field map[string]string
}
func (t *Input) Handler(ctx *gin.Context) {
ctx.JSON(http.StatusOK, Response{})
}
If you run this code, il will crash in an infinite loop.
It seems that swagin is stable for a while. Any plans to create a new tag to works friendly with Go module or other version control toolkits?
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.