Giter VIP home page Giter VIP logo

go-swagger3's Introduction

Demo

Click here for Youtube Demo Link

go-swagger3

Generate OpenAPI Specification v3 file with comments in Go.

Table of content

1. Install

go install github.com/parvez3019/go-swagger3@latest

2. Documentation Generation

Using binary

Go to the folder where is main.go in

// go.mod and main file are in the same directory
go-swagger3 --module-path . --output oas.json --schema-without-pkg --generate-yaml true

// go.mod and main file are in the different directory
go-swagger3 --module-path . --main-file-path ./cmd/xxx/main.go --output oas.json --schema-without-pkg --generate-yaml true

// in case you get 'command not found: go-swagger3' error, please export add GOPATH/bin to PATH
export PATH="$HOME/go/bin:$PATH"

Notes - 
- Pass schema-without-pkg flag as true if you want to generate schemas without package names
- Pass generate-yaml as trus if you want to generate yaml spec file instead of json

Using docker

// go.mod and main file are in the same directory
docker run -t --rm -v $(pwd):/app -w /app parvez3019/go-swagger3:latest --module-path . --output oas.json --schema-without-pkg --generate-yaml true

// go.mod and main file are in the different directory
docker run -t --rm -v $(pwd):/app -w /app parvez3019/go-swagger3:latest --module-path . --main-file-path ./cmd/xxx/main.go --output oas.json --schema-without-pkg --generate-yaml true

Notes - 
- Pass schema-without-pkg flag as true if you want to generate schemas without package names
- Pass generate-yaml as trus if you want to generate yaml spec file instead of json

3. Usage

You can document your service by placing annotations inside your godoc at various places in your code.

Service Description

The service description comments can be located in any of your .go files. They provide general information about the service you are documenting.

// @Version 1.0.0
// @Title Backend API
// @Description API usually works as expected. But sometimes its not true.
// @ContactName Parvez
// @ContactEmail [email protected]
// @ContactURL http://someurl.oxox
// @TermsOfServiceUrl http://someurl.oxox
// @LicenseName MIT
// @LicenseURL https://en.wikipedia.org/wiki/MIT_License
// @Server http://www.fake.com Server-1
// @Server http://www.fake2.com Server-2
// @Security AuthorizationHeader read write
// @SecurityScheme AuthorizationHeader http bearer Input your token

Handler Functions

By adding comments to your handler func godoc, you can document individual actions as well as their input and output.

type User struct {
  ID   uint64 `json:"id" example:"100" description:"User identity"`
  Name string `json:"name" example:"Parvez"` 
}

type UsersResponse struct {
  Data []Users `json:"users" example:"[{\"id\":100, \"name\":\"Parvez\"}]"`
}

type Error struct {
  Code string `json:"code"`
  Msg  string `json:"msg" skip:"true"`
  // use skip:"true" if you want to skip the field in the documentation spec
}

type ErrorResponse struct {
  ErrorInfo Error `json:"error"`
}

// RequestHeaders represents the model for header params
// @HeaderParameters RequestHeaders
type RequestHeaders struct {
    Authorization  string  `json:"Authorization"`
}

// @Title Get user list of a group.
// @Description Get users related to a specific group.
// @Header model.RequestHeaders
// @Param  groupID  path  int  true  "Id of a specific group." "120"
// @Success  200  object  UsersResponse  "UsersResponse JSON"
// @Failure  400  object  ErrorResponse  "ErrorResponse JSON"
// @Resource users
// @Route /api/group/{groupID}/users [get]
func GetGroupUsers() {
  // ...
}

// @Title Get user list of a group.
// @Description Create a new user.
// @Param  user  body  User  true  "Info of a user."
// @Success  200  object  User           "UsersResponse JSON"
// @Failure  400  object  ErrorResponse  "ErrorResponse JSON"
// @Resource users
// @Route /api/user [post]
func PostUser() {
  // ...
}

Title And Description

@Title {title}
@Title Get user list of a group.

@Description {description}.
@Description Get users related to a specific group.
  • {title}: The title of the route.
  • {description}: The description of the route.

Parameter

@Param  {name}    {in}  {goType}  {required}  {description}             {example}
@Param  groupID   path  int       true        "Id of a specific group." "120"
  • {name}: The parameter name.
  • {in}: The parameter is in path, query, form, header, cookie, body or file.
  • {goType}: The type in go code. This will be ignored when {in} is file.
  • {required}: true, false, required or optional.
  • {description}: The description of the parameter. Must be quoted.
  • {example}: Optional example of this parameter. Must be quoted.

One can also override example for an object with override-example key in struct eg -

type Request struct {
    version  model.Version `"json:"Version" override-example:"11.0.0"`
}

Header

@Header          {goType}
@HeaderParameters   model.RequestHeaders
  • Header query param for endpoints, parses the query param from the model

Header Parameters

@Param              {goType}
@HeaderParameters   RequestHeaders
  • {goType}: The type in go code. This will be ignored when {in} is file.
  • Parses parameters from the type and keep it up component section for reference

Response

@Success  {status}  {jsonType}  {goType}       {description}
@Success  200       object      UsersResponse  "UsersResponse JSON"

@Failure  {status}  {jsonType}  {goType}       {description}
@Failure  400       object      ErrorResponse  "ErrorResponse JSON"
  • {status}: The HTTP status code.
  • {jsonType}: The value can be object or array.
  • {goType}: The type in go code.
  • {description}: The description of the response. Must be quoted.

Resource & Tag

@Resource {resource}
@Resource users

@Tag {tag}
@tag xxx
  • {resource}, {tag}: Tag of the route.

Route

@Route {path}    {method}
@Route /api/user [post]
  • {path}: The URL path.
  • {method}: The HTTP Method. Must be put in brackets.

Enums

  • To generate enums create type structs for enum field with comma-separated values as follows:
  • Create struct type fields with @Enum Tag
  • Example as follows-
// @Enum CountriesEnum
type CountriesEnum struct {
    // Create the field name with same as struct name
    CountriesEnum string `enum:"india,china,mexico,japan" example:"india"`
}
How to add reference of Enum on types
type Request struct {
  Name string `json:"name" example:"Parvez"` 
  Country string `json:"country" $ref:"CountriesEnum"`
}

Response body

You need to provide swagger fields as reflect tags in your structure. In example:

type Filter struct {
	Rating       int    `json:"rating"`
	Type         string `json:"type"`
	Distance     int64  `json:"distance", minimum:"1", maximum:"100"`
	DistrictCode string `json:"district_code", pattern:"[a-z]{2}\\d[a-z]\\s\\d[a-z]{2}"`
}

Available fields:

  • type
  • format
  • required
  • properties
  • description
  • items
  • example
  • deprecated (bool)
  • ref
  • enum
  • title
  • maximum (float64)
  • exclusiveMaximum (bool)
  • minimum (float64)
  • exclusiveMinimum (bool)
  • maxLength (uint)
  • minLength (uint)
  • pattern
  • maxItems (uint)
  • minItems (uint)
  • uniqueItems (bool)
  • maxProperties (uint)
  • minProperties (uint)
  • additionalProperties (bool)
  • nullable (bool)
  • readOnly (bool)
  • writeOnly (bool)

4. Security

If authorization is required, you must define security schemes and then apply those to the API. A scheme is defined using @SecurityScheme [name] [type] [parameters] and applied by adding @Security [scheme-name] [scope1] [scope2] [...].

All examples in this section use MyApiAuth as the name. This name can be anything you chose; multiple named schemes are supported. Each scheme must have its own name, except for OAuth2 schemes - OAuth2 supports multiple schemes by the same name.

A number of different types is supported, they all have different parameters:

Type Description Parameters Example
HTTP A HTTP Authentication scheme using the Authorization header scheme: any HTTP Authentication scheme @SecurityScheme MyApiAuth basic
APIKey Authorization by passing an API Key along with the request in: Location of the API Key, options are header, query and cookie. name: The name of the field where the API Key must be set @SecurityScheme MyApiAuth apiKey header X-MyCustomHeader
OpenIdConnect Delegating security to a known OpenId server url: The URL of the OpenId server @SecurityScheme MyApiAuth openIdConnect https://example.com/.well-known/openid-configuration
OAuth2AuthCode Using the "Authentication Code" flow of OAuth2 authorizationUrl, tokenUrl @SecurityScheme MyApiAuth oauth2AuthCode /oauth/authorize /oauth/token
OAuth2Implicit Using the "Implicit" flow of OAuth2 authorizationUrl `@SecurityScheme MyApiAuth oauth2Implicit /oauth/authorize
OAuth2ResourceOwnerCredentials Using the "Resource Owner Credentials" flow of OAuth2 authorizationUrl `@SecurityScheme MyApiAuth oauth2ResourceOwnerCredentials /oauth/token
OAuth2ClientCredentials Using the "Client Credentials" flow of OAuth2 authorizationUrl `@SecurityScheme MyApiAuth oauth2ClientCredentials /oauth/token

Any text that is present after the last parameter wil be used as the description. For instance @SecurityScheme MyApiAuth basic Login with your admin credentials.

Once all security schemes have been defined, they must be configured. This is done with the @Security comment. Depending on the type of the scheme, scopes (see below) may be supported. At the moment, it is only possible to configure security for the entire service.

// @Security MyApiAuth read_user write_user

Scopes

For OAuth2 security schemes, it is possible to define scopes using the @SecurityScope [schema-name] [scope-code] [scope-description] comment.

// @SecurityScope MyApiAuth read_user Read a user from the system
// @SecurityScope MyApiAuth write_user Write a user to the system

5. Limitations

  • Only support go module.
  • Anonymous struct field is not supported.

6. References

go-swagger3's People

Contributors

a0v0 avatar itmosha avatar parvez3019 avatar parvezhassan1 avatar qequ avatar samantatarun 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  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

go-swagger3's Issues

Ref for maps object does not get created

If you have a struct that has map with struct values, the swagger generated does not reference the AccessDefinition.

type Policys struct {	
AccessRights                  map[string]AccessDefinitions      `bson:"access_rights" json:"access_rights"`
}

type AccessDefinitions struct {
	Name string `json:"name"`
}

This is what is produced instead of using ref to reference the already created AccessDefinitions :

  schemas:
    AccessDefinitions:
      properties:
        name:
          type: string
      type: object
    Policys:
      properties:
        access_rights:
          properties:
            key:
              properties:
                name:
                  type: string
              type: object
          type: object
      type: object ```

Generated yaml file is not ordered as normally open-api swagger yaml file.

What I mean is that when generating the swagger yaml file normally it follows the next structure provided by Swagger Editor, you can follow the Load PetStore OAS 3.0 example:

  • openapi: 3.0.0
  • info
  • externalDocs
  • servers
  • tags
  • path
  • components

The structure that I obtained when generating the yaml file follows:

  • components
  • info
  • openapi: 3.0.0
  • path
  • servers

It will be helpful to update it as the Swagger Editor suggests.

Can not generate Request Param swagger config

In Param config, if we pass {in} as query, path, it won't generate Request Param Config in oas.yml.
It also doesn't have {required} information in the oas.yml.
Does someone know how to generate it or it's a bug?

Model composition in response

This is what swaggo can do:

// JSONResult's data field will be overridden by the specific type proto.Order
@success 200 {object} ReturnValue {data=proto.Order} "desc"

then custom struce can as a common response type like :

type ReturnValue struct {
	Data   interface{} `json:"data"`
	Status uint        `json:"status" example:"0"`
	Msg    string      `json:"msg" example:"成功"`
}

when I use struct ReturnValue as success response , I can put the truely model in data field.
Does this lib support this? I didn`t found it in docs.

type's required tag is can't extend

//main.go

// @Title test
// @Version 0.0.0
package main

type A struct {
	A string `json:"a" required:""`
}
type B struct {
	A
	B string `json:"bb" required:""`
}

// @Title test
// @Param  in body  B  true  "x"
// @Route  / [GET]
func main() {

}

//swagger.json

{
  "openapi": "3.0.0",
  "info": {
    "title": "test",
    "version": "0.0.0"
  },
  "servers": [
    {
      "url": "/",
      "description": "Default Server URL"
    }
  ],
  "paths": {
    "/": {
      "get": {
        "responses": {},
        "summary": "test",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/B"
              }
            }
          },
          "required": true
        }
      }
    }
  },
  "components": {
    "schemas": {
      "A": {
        "type": "object",
        "required": [
          "a"
        ],
        "properties": {
          "a": {
            "type": "string"
          }
        }
      },
      "B": {
        "type": "object",
        "required": [
          "bb"
        ],
        "properties": {
          "bb": {
            "type": "string"
          },
          "a": {
            "type": "string"
          }
        }
      }
    }
  }
}

how to write let type B required is ["a","bb"]

Fails on parsing builtin error

Hi, I can't find an example of error response in documentation, so I'm wondering does it also support errors, because it fails on the bellow example.

Example:

package pog

// @title Get Planograms.
// @description Returns planogram based on query params.
// @param id query string true "Use as filter.id! Planogram dbKey [comma separated list]"
// @param locationId query string true "Use as filter.locationId! Location ID"
// @param include query string false "Includes. Can be: position, fixture, liveFlrFixture"
// @param commodity query string false "Use as filter.commodity! Commodity"
// @param commodityGroup query string false "Use as filter.commodityGroup! Commodity Group"
// @param isDigitalScreen query string false "Use as filter.isDigitalScreen! IsDigitalScreen. Can be: true, false"
// @success 200 {object} GetPogsResponse
// @failure 400 {object} types.ValidationError
// @failure 404 {object} types.ErrResponse
// @failure 500 {object} types.ErrResponse
// @route assortment/planogram [get]
func (h *Handler) GetPogs(ctx *krogo.Context) (interface{}, error) { ....

package types

type ValidationError struct {
StatusCode int json:"statusCode" xml:"statusCode"
Errors []error json:"errors" xml:"errors"
}

Error:
FATA[0014] Can not find definition of error ast.TypeSpec. Current package types

Update:
It works with such trick, if instead of []error just use new typetype errors []error. But of course this is not the greatest solution, I guess there should be simple way to use []error

type errors []error

// swagger:model ValidationErrorResponse
type ValidationErrorResponse struct {
StatusCode int json:"statusCode" xml:"statusCode"
Errors errors json:"errors" xml:"errors"
}

Problems encountered in use

  1. How should I comment the file and text in form?
  2. If file is used instead of body, the parameter must not contain underscores, such as file_name.

Failing to add header to model

I get the following when trying to add basic security onto my endpoints. Are you able to see why? Looking at the readme and examples i've done the same thing.

PS G:\gok8> go-swagger3 --module-path . --output .\swaggerui\swagger.yml --schema-without-pkg --generate-yaml true
time="2022-06-05T15:01:31+01:00" level=info msg="Parsing Initialized"
time="2022-06-05T15:01:31+01:00" level=info msg="Parsing Info ..."
time="2022-06-05T15:01:31+01:00" level=info msg="Parsing Modules ..."
time="2022-06-05T15:01:31+01:00" level=info msg="Parsing GoMod Info ..."
time="2022-06-05T15:01:32+01:00" level=info msg="Parsing APIs ..."
2022/06/05 15:01:35 Error: NilSchemaProperties : parseHeaders can not parse Header schema model.Headers

Model file:

package model

// Headers represents the model for header params
// @HeaderParameters Headers
type Headers struct {
	Authorization string `parse:"Authorization" json:"Authorization" example:"Bearer thisisatest" skip:"true"`
}

Handler file:

package handler

// @Tag namespace
// @Title List namespaces
// @Description Get a list of namespaces.
// @Header model.Headers
// @Param request body model.namespaceQuery true "The query to filter namespaces"
// @Success 200 {object} model.namespaceResponse "The response from the kubernetes cluster"
// @Router /namespace [get]
func listNamespaces() {
	return
}

Parsing go.mod that contains a replace directive for external module forks

Hi,

I am trying to learn go-swagger3 and so far have managed to get a working demo setup. I am now trying it on a larger codebase which contains a fork to an external repository. Subsequently, the go.mod file uses the replace directive, e.g. something similar to:

g.mod file

// last line of go.mod file uses replace directive for fork of external module
replace example.io/goexample => github.com/example.org/goexample v1.20.7

When I issue the command from the project root folder:

go-swagger3 --debug --module-path . --output oas.yml --schema-without-pkg --generate-yaml true

Parsing of the go.mod fails with error:

INFO[0000] Parsing Initialized
INFO[0000] Parsing Info ...
INFO[0000] Parsing Modules ...
INFO[0000] Parsing GoMod Info ...
2023/04/28 15:51:48 Error: expect package version, got "=>"

If I remove the replace directive in the go.mod file the oas.yml file is generated successfully by go-swagger3.

Will there be future support for parsing the replace directive for projects that use forks of external modules?

Custom type objects are generated twice in Components

@parvez3019 when custom type objects are generated in Components two exact equal objects are generated,one with the name of the custom type alone and another with the name plus the package.

e.g. in the integration_test's expected.json there is a CreateUserRequest (among other custom types) which appears twice in Components; CreateUserRequest and github.com.parvez3019.go-swagger3.model.CreateUserRequest. The $Ref points to github.com.parvez3019.go-swagger3.model.CreateUserRequest and the other is never used.

Why is this? Shouldn't there be only one of the the objects?

How to add restrictions for fields in response/parameter

I want to add some restrictions to my fields in responses and parameters such as min length, max length and type. How can I do this or it doesn't implemented now? I don't find anything about it in readme.

Example of JSON of OpenAPI specification for response.

{
  "type": "array",
  "items": {
    "type": "object",
    "properties": {
      "id": {
        "type": "integer"
      },
    "title": {
      "type": "string",
      "maxLength": 50
    }
  }
}

Example of JSON of OpenAPI specification for parameter.

{
   "name": "username",
   "in": "path",
   "description": "username to fetch",
   "required": true,
   "schema": {
     "type": "string",
     "maxLength": 100
   }
}

OperationID

Please add an option to add operationId as well.

How to add oneOf to the schema

type Response struct {
field1 *string json:"field1,omitempty"
field2 *string json:"field2,omitempty"
}

I want to indicate that the response will either contain field1 or field2

Sample spec:

    Response:
      oneOf:
        - $ref: '#/components/schemas/Response1'
        - $ref: '#/components/schemas/Response2'

Expand test suit

Currently there are only integration tests. To ensure a more robust and reliable codebase, it's needed to expand our test suite to include unit tests.

Can this project use generic types in Swagger?

Hello,

This is my first time using this project. Previously, I used go-swagger, but now I prefer to use OpenAPI 3.0.

After studying the README, I'm not sure if generic classes are supported. Could you please confirm whether this project can handle generic types in Swagger?

Thank you for your assistance.

Add CI/CD pipeline

Currently there are no pipelines (GitHub actions) when a pull request is open. It would be great to add a pipeline of linting and another that runs the tests

Please update regex to support dot within params name

We have query params formatted like this:

// @param filter.id
// @param filter.locationId

and it cuts prefix part and only accepts everything after dot:

Swagger:
Screenshot 2023-09-18 at 10 44 15 AM

Openapi.json:
...

paths:
  /assortment/planogram:
    get:
      description: ' Returns planogram based on query params.'
      parameters:
      - description: Use as filter.id! Planogram dbKey [comma separated list]
        in: query
        name: id
        required: true
        schema:
          description: Use as filter.id! Planogram dbKey [comma separated list]
          format: string
          type: string
      - description: Use as filter.locationId! Location ID
        in: query
        name: locationId
        required: true
        schema:
          description: Use as filter.locationId! Location ID
          format: string
          type: string

Is there any way to use params with dot?

Thanks.

Potential fix that works:
Within parser/operations/param.go, update regular expression to this one to support dot as well:

re := regexp.MustCompile(`([-.\w]+)[\s]+([\w]+)[\s]+([\w./\[\]]+)[\s]+([\w]+)[\s]+"([^"]+)"`)

`skip` flag not working field custom types mapping

Hi, I realized that go-swagger3 still continues with the type mapping for those fields marked with skip: "true".
For example:

type Foo struct {
  field1 string `json:"field1"`
  field2 string `json:"field2"`
  field3 Bar `json:"field3" skip:"true"`
}

type Bar struct {
  ...
}

And, if I don't want to map the Bar type, it also processes it.

go-swagger error

go-swagger3: command not found
After installation via go get and execution of go-swagger3 --module-path . --main-file-path ./cmd/main/main.go --output oas.json

How to mark field as nullable?

I would like to mark Name as nullable field. How can I achieve that?

type Task struct {
	ID        int            `json:"task_id" gorm:"index:idx_name,unique" required:"true"`
	Name      string         `json:"task_name"  required:"true"`
}

I've tried nullable: true, x-nullable: true without much success. Returned json doesn't return anything that would resemble nullability.

How to provide a different example Response for a type for different endpoint paths?

Hi,

I am working with a codebase that has has the following type to record the status of operations on key resources.

type apiModifyKeySuccess struct {
	Key     string `json:"key" example:"12345678987654321"`
	Status  string `json:"status"` example:"ok"`
	Action  string `json:"action"` example:"added"`
	KeyHash string `json:"key_hash,omitempty"` example:"bc123456"
}

The Action field can accept values added, deleted or modified

I have used the example tag to give example values for the response in the OAS generated documentation. However, this example is generated globally across all endpoints.

For example, endpoint paths for adding and deleting a key render the same example response with Action example value being displayed as "added".

Is it possible to use the @success tag to override the example for the type?

// @Title Create a key.
// @Description Create a new key and return associated details in response.
// @Param   key  body  user.SessionState  true  "Info for key relating to access rights, policies etc."
// @Success  201  object  apiModifyKeySuccess  "JSON response containing the new key and hash
// @Resource keys
// @Route /api/keys [post]
func AddKey() {
  // ...
}

// @Title Delete a key.
// @Description Delete a given key.
// @Param  keyID  path  string  true  "Id of a specific key."
// @Success  200  object  apiModifyKeySuccess   "Returns details of the key and confirmation of deletion action"
// @Resource keys
// @Route /api/keys [delete]
func DeleteKey() {
  // ...
}

Why GPL 3.0?

I like this library but why is GPL 3.0 necessary? Isn’t it virtually useless for serious usage this way?

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.