Giter Site home page Giter Site logo

gin-swagger's Introduction

gin-swagger - DRY templates for go-swagger

gin-swagger is a tool assisting in writing golang REST APIs based on a API First Principle. Given a swagger spec of your REST API, gin-swagger can generate all the boring boilerplate stuff for you, so you only have to implement the core business logic of the API.

It is based on go-swagger which is used for the code generation.

Install

You can simply run go get to install gin-swagger.

$ go get github.com/mikkeloscar/gin-swagger
$ gin-swagger --help
usage: gin-swagger --application=APPLICATION [<flags>]

Flags:
      --help                     Show context-sensitive help (also try --help-long and --help-man).
  -A, --application=APPLICATION  Name of the application (passed directly to swagger).
  -f, --spec="./swagger.json"    the spec file to use.

How it works

gin-swagger generates a gin based REST API given a swagger spec.

Assuming the following swagger spec:

swagger: '2.0'
info:
  version: "0.0.1"
  title: My API
schemes:
    - "https"
basePath: /
produces:
  - application/json
consumes:
  - application/json
paths:
  '/persons/{name}':
    get:
      summary: get Person
      tags:
        - Person
      operationId: getPerson
      responses:
        200:
          description: Person by name.
          schema:
            '$ref': '#/definitions/Person'
parameters:
  name:
    name: name
    in: path
    type: string
    required: true
    pattern: "^[a-z][a-z0-9]$"
definitions:
  Person:
    type: object
    properties:
      name:
        type: string

You can generate the REST API using the following command:

$ gin-swagger -A my-api -f swagger.yaml

This will generate two folders models/ and restapi/. models/ contains model structs based on the definitions defined in your swagger file, including model validation, this is generated by go-swagger. restapi/ will contain everything generated by gin-swagger and can be overwritten when updating and regenerating your swagger spec. restapi/api.go will contain a generated Service interface which is all you have to implement in order to add logic to your REST api.

Given the above swagger spec, the Service interface will look like this:

type Service interface {
    Healthy() bool
    GetPerson(ctx *gin.Context, params *persons.GetPersonParams) *api.Response
}

The Healthy() bool method should return true if the service is considered healthy. The return value is used by the default health endpoint /healthz provided by gin-swagger.

The GetPerson() method should implement the business logic of the /persons/{name} path of your REST API.

A simple service implementation looks like this:

type mySvc struct {
    health bool
}

func (m *mySvc) GetPerson(ctx *gin.Context, params *persons.GetPersonParams) *api.Response {
    return &api.Response{
        Code: http.StatusOK,
        Body: &models.Person{Name: params.Name},
    }
}

func (m *mySvc) Healthy() bool {
    return m.health
}

With the service implemented the only thing left to do is plug it into gin-swagger and run it from your main.go (or wherever you like):

package main

import ...

var apiConfig restapi.Config

func main() {
    err := apiConfig.Parse()
    if err != nil {
        log.Fatal(err)
    }
    svc := &mySvc{health: true}
    api := restapi.NewServer(svc, &apiConfig)
    err = api.RunWithSigHandler()
    if err != nil {
        log.Fatal(err)
    }
}

restapi.Config is a default config object defined by gin-swagger it lets you configure default options through commandline flags when starting the server. For instance you can tell the server to serve HTTP only with the --insecure-http flag (default is to serve HTTPS).

For a full example see the example folder.

Features

  • Validate + bind input to gin ctx.
    • bind body input.
      • [Nice to have] custom input Models with required fields.
    • bind params input.
    • bind query params input.
    • consume more than application/json
  • Security.
    • basic
    • apiKey
    • OAuth2
      • password (Bearer token)
      • accessCode
      • application
      • implicit
    • Auth chain
    • Custom authorize on individual routes.
  • Set custom middleware on each router Pre/post 'main' handler.
    • Use case pre: custom authorization pre handler.
    • Use case post: audit report events post handler.
  • Ginize generated code.
  • Set and get user info (uid, realm) from gin context.
  • Response helper functions
  • Default metrics (prometheus)
  • OpenTracing support

gin-swagger's People

Contributors

alexanderyastrebov avatar cugu avatar dependabot[bot] avatar devil-maycry avatar firejump avatar jbellmann avatar mikkeloscar avatar raffo avatar superpan avatar tuxlife avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

gin-swagger's Issues

Parameter handling not working

In the generated config.go (before calling kingpin.Parse()) the following line is needed in order to handle the command-line parameters:

c.WithDefaultFlags()

Array parameters with default values

The code produced by this line of the Parameter template does not correctly handle default values of type Array, writing the array directly into the template with its values as raw text.

Example YML for a failing parameter:

        - name: Foo
          in: query
          description: >-
            A comma-delimited list of arbitrary values
          type: array
          items:
            type: string
          collectionFormat: csv
          default:
            - Bar
            - Bazz
            - Buzz

This produces the line:
defValue := swag.SplitByFormat([Bar Bazz Buzz], "csv")

If I understand the default templates correctly, they seem to be using the JSON parser as a middle man to handle these cases. Would that work for this lib as well?

Does not work with go1.13

When building with go1.13 the code generation fails with the following error:

./build/gin-swagger -A cluster-registry -f swagger.yaml
2019/09/04 10:10:14 validating spec /workspace/swagger.yaml
panic: Invalid schema provided to SchemaValidator: object has no key "default"
goroutine 1 [running]:
github.com/go-openapi/validate.NewSchemaValidator(0xc000908d80, 0xb38f80, 0xc000908d80, 0x0, 0x0, 0xc9ba20, 0xc000390660, 0xc000bc8280)
	/go/pkg/mod/github.com/go-openapi/[email protected]/schema.go:71 +0xf83
github.com/go-openapi/validate.(*SpecValidator).Validate(0xc00063c900, 0xafe500, 0xc0000aba90, 0xc000bd0000, 0xc000bd00b0)
	/go/pkg/mod/github.com/go-openapi/[email protected]/spec.go:92 +0x208
github.com/go-openapi/validate.Spec(0xc0000aba90, 0xc9ba20, 0xc000390660, 0x14, 0xbf54014182793a94)
	/go/pkg/mod/github.com/go-openapi/[email protected]/spec.go:47 +0xad
github.com/go-swagger/go-swagger/generator.validateSpec(0xc00033e740, 0x17, 0xc0000aba90, 0x1, 0x1)
	/go/pkg/mod/github.com/go-swagger/[email protected]/generator/shared.go:882 +0x89
github.com/go-swagger/go-swagger/generator.validateAndFlattenSpec(0xc00016e600, 0xc0000aba90, 0xc00033e740, 0x17, 0xc0000aba90)
	/go/pkg/mod/github.com/go-swagger/[email protected]/generator/shared.go:1055 +0x42e
github.com/go-swagger/go-swagger/generator.newAppGenerator(0x7fff9e029a98, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc00016e600, 0x9d7918, ...)
	/go/pkg/mod/github.com/go-swagger/[email protected]/generator/support.go:92 +0x15c
github.com/go-swagger/go-swagger/generator.GenerateServer(0x7fff9e029a98, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc00016e600, 0x0, ...)
	/go/pkg/mod/github.com/go-swagger/[email protected]/generator/support.go:39 +0x94
main.run(0x7fff9e029a98, 0x10, 0x7fff9e029aac, 0xc, 0xc00008f100, 0xc0002bc570)
	/go/pkg/mod/github.com/mikkeloscar/[email protected]/main.go:144 +0x5b0
main.main()
	/go/pkg/mod/github.com/mikkeloscar/[email protected]/main.go:34 +0x35b
Makefile:30: recipe for target 'generate' failed
make: *** [generate] Error 2
Step finished unsuccessfully.

It's not clear what is the issue but it works with go1.12. I suspect it's something inside reflect package that changed because of where it's crashing.

CORS problems

In order to run swagger-ui with API test, I have to enable CORS.

Now, I add code in each EndPoint. eg.:

func GetPersonEndpoint(handler func(ctx *gin.Context, params *GetPersonParams) *api.Response) gin.HandlerFunc {
return func(ctx *gin.Context) {

        //------------------------- BEGIN: ADDED CODE ------------------------
        ctx.Writer.Header().Set("Access-Control-Allow-Origin", "*")
        ctx.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
        ctx.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With")
        ctx.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT, DELETE")

        if ctx.Request.Method == "OPTIONS" {
            ctx.AbortWithStatus(204)
            return
        }
        ctx.Next()

        //------------------------- END: ADDED CODE ------------------------

       //.......................

}

}

I tried https://github.com/gin-contrib/cors but did not success!

Is there any better solution for this situation?

Thank you very much in advance!
Best regards,
jo

Is gin-swagger working for go1.15.3?

The installation command does not show any errors,
go get github.com/mikkeloscar/gin-swagger

but when i try using gin-swagger, it bounces off this error

-bash: gin-swagger: command not found

System:
Mac OS Mojave
go version go1.15.3 darwin/amd64

Can someone please point to me what might be wrong and how can i fix it?

Example code compiles, but doesn't run.

Maybe I did it wrong...

cd example
go build . 
./example --insecure-http
panic: handlers are already registered for path ''/healthz'

goroutine 1 [running]:
github.com/gin-gonic/gin.(*node).addRoute(0xc4201e52c0, 0xc4204ef1d0, 0x8, 0xc42032b340, 0x3, 0x3)
	/Users/raffo/Development/go/src/github.com/gin-gonic/gin/tree.go:235 +0xa9b
github.com/gin-gonic/gin.(*Engine).addRoute(0xc42026f440, 0x17859b6, 0x3, 0xc4204ef1d0, 0x8, 0xc42032b340, 0x3, 0x3)
	/Users/raffo/Development/go/src/github.com/gin-gonic/gin/gin.go:237 +0x1bc
github.com/gin-gonic/gin.(*RouterGroup).handle(0xc42026f440, 0x17859b6, 0x3, 0x1789ace, 0x8, 0xc4201d4960, 0x1, 0x1, 0xc420130d01, 0xc4201d4960)
	/Users/raffo/Development/go/src/github.com/gin-gonic/gin/routergroup.go:71 +0xe7
github.com/gin-gonic/gin.(*RouterGroup).GET(0xc42026f440, 0x1789ace, 0x8, 0xc4201d4960, 0x1, 0x1, 0xc420551f10, 0x1048a71)
	/Users/raffo/Development/go/src/github.com/gin-gonic/gin/routergroup.go:99 +0x7c
github.com/mikkeloscar/gin-swagger/example/restapi.NewAPI(0x1aef580, 0xc4204ef0e1, 0x1b37600, 0xc420376000)
	/Users/raffo/Development/go/src/github.com/mikkeloscar/gin-swagger/example/restapi/api.go:456 +0x280
main.main()
	/Users/raffo/Development/go/src/github.com/mikkeloscar/gin-swagger/example/main.go:19 +0xae

there is compile error when enum has special chars such as >, ==, <, <=, >=

In my swagger.json, there is a enum:
"operator": {
"type": "string",
"enum": [
"==",
"!=",
">",
">=",
"<",
"<=",
"before",
"after"
],
"description": "The operator for this filter: ==, !=, >, >=, <, <=, before, after"

the generated code will be
const (

// APIFilterOperator captures enum value "=="
APIFilterOperator string = "=="

// APIFilterOperatorBang captures enum value "!="
APIFilterOperatorBang string = "!="

// APIFilterOperator captures enum value ">"
APIFilterOperator string = ">"

// APIFilterOperator captures enum value ">="
APIFilterOperator string = ">="

// APIFilterOperator captures enum value "<"
APIFilterOperator string = "<"

// APIFilterOperator captures enum value "<="
APIFilterOperator string = "<="

// APIFilterOperatorBefore captures enum value "before"
APIFilterOperatorBefore string = "before"

// APIFilterOperatorAfter captures enum value "after"
APIFilterOperatorAfter string = "after"

)

so the APIFilterOperator const is redeclared .

Cannot define upload type in swagger file

I am trying to define a file upload file

/upload:
     post:
       summary: Uploads a CSV file.
       consumes:
         - multipart/form-data
       parameters:
         - in: formData
           name: customers
           type: string
           format: binary
           description: The file to upload.
         - name: update
           in: query
           type: boolean
           required: false
           default: false
         - name: import_id
           in: query
           type: string
           required: false

But it results in broken code gen

restapi/operations/post_upload_parameters.go:131:14: cannot use value.(*io.ReadCloser) (type *io.ReadCloser) as type io.ReadCloser in assignment:
	*io.ReadCloser is pointer to interface, not interface

Add documentation on how to extend the templates

I have extended the template in https://github.com/Raffo/gin-swagger/blob/master/templates/api.gotmpl#L93 but I don't really understand how I can make it possible to update the templates used for generation on my machine.

I tried:

make generate
make

The gin-swagger binary generates the same templates even if they were updated. Can you provide some more info on what to check and maybe we can add it to the readme as well?

NOTE: this was done at 5 AM at the airport, so it might be subject to "I didn't know what I was doing".

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.