I'm trying to implement go-swagger but this error keep flashing. I'm using windows machine. I appreciate any help.
My implementation:
opts := middleware.RedocOpts{RedocURL: "/swagger.yaml"}
sh := middleware.Redoc(opts, nil)
getRouter.Handle("/docs", sh)
getRouter.Handle("/swagger.yaml", http.FileServer(http.Dir("./")))
My swagger definition:
// Package classification of Product API.
//
// Documentation for Product API
// Schemes: http
// BasePath: /
// version: 1.0.0
//
// Consumes:
// - application/json
//
// Produces:
// - application/json
// swagger:meta
Error message:
The option of Redoc must be
SpecURL
opts := middleware.RedocOpts{SpecURL: "/swagger.yaml"}
instead of RedocURL
opts := middleware.RedocOpts{RedocURL: "/swagger.yaml"}
Related
i have a question. Is it possible to extract via metadata path from user request.
Here i have my proto file with defined method.
rpc AllPath(google.protobuf.Empty) returns (google.protobuf.Empty) {
option (google.api.http) = {
get: "/*",
};
}
rpc Auth(google.protobuf.Empty) returns (TokenRender) {
option (google.api.http) = {
get: "/auth"
};
}
}
In AllPath function in my server file im using something like this, found on grpc-gateway ecosystem website.
path := make(map[string]string)
if pattern, ok := runtime.HTTPPathPattern(ctx); ok {
path["pattern"] = pattern // /v1/example/login
}
fmt.Printf("Current path is: %v", path["pattern"])
but my current pattern/path is like i defined in proto file: Current path is: /*
If anyone have idea how to deal with this thing i would appreciate it :)
Best, Kacper
gRPC-Gateway passes various bits of information from the originating HTTP request via gRPC metadata. I don't believe the raw path is supplied, however. It is still possible to get the path passed through by registering a metadata annotator.
When calling github.com/grpc-ecosystem/grpc-gateway/v2/runtime.NewServeMux(), leverage the WithMetadata option func:
mux := runtime.NewServeMux(runtime.WithMetadata(func(_ context.Context, req *http.Request) metadata.MD {
return metadata.New(map[string]string{
"grpcgateway-http-path": req.URL.Path,
})
}))
Then in your gRPC service implementation, you can retrieve the value via the incoming context:
func (s *server) AllPath(ctx context.Context, _ *emptypb.Empty) (*emptypb.Empty, error) {
md, _ := metadata.FromIncomingContext(ctx)
log.Printf("path: %s", md["grpcgateway-http-path"][0])
return &emptypb.Empty{}, nil
}
When hitting, e.g. /foo, this should log:
2022/10/25 15:31:42 path: /foo
I am using oapi-codegen to generate my server code and Echo Labstack as the server.
When I pass a Group instance to Openapi.RegisterHandlers instead of an Echo instance, I always get a 400 error with {"message":"no matching operation was found"} for any request in that group:
swagger, err := Openapi.GetSwagger()
if err != nil {
fmt.Fprintf(os.Stderr, "Error loading swagger spec\n: %s", err)
os.Exit(1)
}
// Use oapi validation middleware to check all requests against the
// OpenAPI schema.
g := e.Group("/api", middleware.OapiRequestValidator(swagger))
Openapi.RegisterHandlers(g, &MyApi{})
If send request /api/foo, where foo is an API endpoint defined in the generated server code, I get a 400 error. If I do /api/<some undefined api> I also get 400. If I do send a request for /baz, I get 404 as expected, since that isn't a defined route. If I don't pass a prefix to Group(), I get a 400 error for every request. I get the same behavior if I use RegisterHandlersWithBaseURL()
There seems to be a bug where if you specify the a base path, either to the Group() function or to RegisterHandlersWithBaseURL(), theOapiRequestValidator middle ignores the base path when checking the request path against the routes. It uses the routes defined in the OpenAPI spec without the base path. To work around this, I overwrote the inline.tmpl template and hacked the GetSwagger() function to include this at the bottom:
func GetSwagger(pathPrefix string) (swagger *openapi3.T, err error) {
...
var updatedPaths openapi3.Paths = make(openapi3.Paths)
for key, value := range(swagger.Paths) {
updatedPaths[pathPrefix + key] = value
}
swagger.Paths = updatedPaths
}
The key in the Path map is the route. I just append the base path to every key.
I'm using deepmap/oapi-codegen to generate a chi-server from a openapi 3.0.3 specification, most of it works just fine but I'm having an issue with UUID validation. I've defined a path parameter like this (not a complete definition):
openapi: "3.0.3"
info:
title: "Example"
description: "Sites API"
version: "0.0.3"
paths:
/sites/{siteId}:
parameters:
- in: path
name: siteId
required: true
schema:
type: string
format: uuid
The generated validator seems to recognize invalid UUIDs correctly but insists on throwing a 500 error if the UUID is invalid. Looking at the code for the validation it seems it may have something to do with an upstream issue but as I'm completely new in the go world I'm not completely sure I'm following the flow correctly.
This is the code that sets up the chi-router:
swagger, err := Openapi.GetSwagger()
if err != nil {
s.logger.Error().Msg("Error loading swagger spec.")
}
swagger.Servers = nil
router := chi.NewRouter()
router.Use(middleware.OapiRequestValidator(swagger))
Openapi.HandlerFromMux(s.api, router)
api.Server = &http.Server{
Handler: router,
Addr: fmt.Sprintf("0.0.0.0:%s", config.Port),
}
Has anyone out there seen this issue? If so, is there a fix/workaround to this? Am I forgetting something obvious in my code?
I am trying to use generate swagger spec from my API handler.
I have installed the go-swagger from go get:
go get -u github.com/go-swagger/go-swagger/cmd/swagger
See the project structure below:
main.go uses handler definitions in products.go. (API works and is tested)
Swagger spec in product.go:
// Package classification of Product API.
//
// Documenting for Product API
//
//
//
// Schemes: http, https
// BasePath: /
// Version: 0.0.1
//
// Consumes:
// - application/json
//
// Produces:
// - application/json
//
// swagger:meta
Running the following command from main.go path:
GO111MODULE=off swagger generate spec -o ./swagger.yaml --scan-models
Response:
info: {}
paths: {}
swagger: "2.0"
Expected Response:
basePath: /
consumes:
- application/json
info:
description: Documenting for Product API
title:
version: 0.0.1
paths: {}
producrs:
- application/json
schemes:
- http
swagger: "2.0"
I assume you are following Nic's MSA Go tutorial.
In case you haven't figure out the issue yet, you forgot to add a space for the contents. (lines between the first and last line)
Your documentation comment should be as below
// Documentation for Product API
//
// Schemes: http
// BasePath: /
// Version: 1.0.0
//
// Consumes:
// - application/json
//
// Produces:
// - application/json
//
// swagger:meta
In adition to #sssang comment. Make sure you leave no space between Documentation comment and the package definition.
// Documentation for Product API
//
// Schemes: http
// BasePath: /
// Version: 1.0.0
//
// Consumes:
// - application/json
//
// Produces:
// - application/json
//
// swagger:meta
package handlers
[...rest of your code]
In documentation https://github.com/swaggo/swag is using gin to initialize server, but in my application i'm using http.ServeMux and how initialize swaggo without use gin server
in Docs use
r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
how can I use something like ...
mu.Handle("/swagger/*any", swaggerFiles.Handler)
......
follows as my initial idea, but don't work... rsrs
func Server() *http.ServeMux {
docs.SwaggerInfo.Title = "Swagger Example API"
docs.SwaggerInfo.Description = "This is a sample server Petstore server."
docs.SwaggerInfo.Version = "1.0"
docs.SwaggerInfo.Host = "petstore.swagger.io"
mu := http.NewServeMux()
mu.Handle("/metrics", promhttp.Handler())
mu.Handle("/swagger/*any", swaggerFiles.Handler)
mu.HandleFunc("/helloWorld", handlers.NewHelloWorldHandler().HelloWorldHandler)
mu.HandleFunc("/production/", handlers.NewProductionHandler().ProductionHandler)
return mu
}
If you have your swagger files built for distribution (i.e. static files) and are in say the directory: /some/dir/path/static/swagger
This should work with go's http router:
staticFilesPath := "/some/dir/path/static"
staticRoute := "/static/"
h := http.NewServeMux()
// static file handler for route '/static/*'
h.Handle(
staticRoute,
http.StripPrefix(
staticRoute,
http.FileServer(http.Dir(staticFilesPath)),
),
)
I find it helpful to add this also:
// (redirect a route if not recognized - remove in production)
//
// unrecognized routes will redirect to Swagger API docs
h.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, staticRoute + "swagger/", http.StatusSeeOther)
})