Skip to content

Gopenapi use javascript to extend and simplify openapi sepc.

License

Notifications You must be signed in to change notification settings

gopenapi/gopenapi

Repository files navigation

Gopenapi

Gopenapi use javascript to extend and simplify openapi sepc.

Goals

Unlike the regular openapi spec generator, Gopenapi has the following features:

  • Highly flexible
    • Base on openapi.yaml file, you can choose which part of the content is generated by Gopenapi according to your preferences
    • Use JavaScript to write additional logic
  • Understanding low-cost
    • Syntax as simple as yaml
  • Less intrusion
    • Just need a few comments in the go source code

Why not

  • go-swagger has the following disadvantages:
    • Syntax is complicated, I now need to learn two kinds of syntax: openapi and goswagger
    • Non-scalability, only the syntax supported by go-swgger can be used
    • All information is written in Go code, which makes the source code unclean

Get start

Precondition

  • Make sure your project is written in Golang and 'go module' is enabled

Step 0: Install Gopenapi

go get -u github.com/gopenapi/gopenapi

Step 1: Write openapi.src.yaml file

Gopenapi only support yaml format files so far

openapi: 3.0.1
info:
  title: Swagger Petstore
  description: |
    This is a sample server Petstore server.  You can find out more about     Swagger
    at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/).      For
    this sample, you can use the api key "special-key" to test the authorization     filters.

    **All api maybe return 401 code if it need auth.**
  termsOfService: http://swagger.io/terms/
  contact:
    email: apiteam@swagger.io
  license:
    name: Apache 2.0
    url: http://www.apache.org/licenses/LICENSE-2.0.html
  version: 1.0.0
externalDocs:
  description: Find out more about Swagger
  url: http://swagger.io
servers:
  - url: https://petstore.swagger.io/v2
  - url: http://petstore.swagger.io/v2

tags:
  - name: pet
    description: Test all features

paths:
  /pet/findByStatus:
    get:
      x-$path: github.com/gopenapi/gopenapi/internal/delivery/http/handler.PetHandler.FindPetByStatus
      tags:
        - pet
      security:
        - petstore_auth:
            - write:pets
            - read:pets
  /pet/{id}:
    get:
      x-$path: github.com/gopenapi/gopenapi/internal/delivery/http/handler.PetHandler.GetPet
      tags:
        - pet
      operationId: getPetById
      security:
        - api_key: [ ]

    delete:
      x-$path: ./internal/delivery/http/handler.PetHandler.DelPet
      tags:
        - pet
      security:
        - api_key: [ ]

components:
  schemas:
    Category:
      x-$schema: github.com/gopenapi/gopenapi/internal/model.Category
    Tag:
      x-$schema: ./internal/model.Tag
    Pet:
      x-$schema: github.com/gopenapi/gopenapi/internal/model.Pet

As you can see, Gopenapi provide some extended syntax:

  • x-$schema
  • x-$path

For more information about 'extended syntax', please refer to here

Step 2: Write 'meta-comments' in your go source code

// FindPetByStatus Finds Pets by status
//
+ // $:
+ //   params: model.FindPetByStatusParams
+ //   response: schema([model.Pet])
func (h *PetHandler) FindPetByStatus(ctx *gin.Context) {
...
}

Done! Just added 3 lines of comments

'meta-comments' syntax is yaml, but it needs to start with the '$' symbol.

The following syntax is correct:

// $:
//   params: model.FindPetByStatusParams
//   response: schema([model.Pet])

or

// $:
//   params: model.FindPetByStatusParams
//   response: 
//     200: schema([model.Pet])

or

// $params: model.FindPetByStatusParams
// $response: schema([model.Pet])

Remember it just is 'yaml'

Step 3: Run Gopenapi to fill your yaml file

Run the following command in the project root directory.

gopenapi -i example/openapi.src.yaml -o example/openapi.gen.yaml

Tip: Type 'gopenapi -h' for more helps.

gopenapi -h

Usage:
  gopenapi [flags]

Flags:
  -c, --config string   specify the configuration file to be used (default "gopenapi.conf.js")
  -h, --help            help for gopenapi
  -i, --input string    specify the source file in yaml format
  -o, --output string   specify the output file path
  -v, --version         version for gopenapi

Tip: You can review the generated file on http://editor.swagger.io/

Extended Syntax

x-$path

The x-$path instruction generates data that conforms to openapi-path from Go comment.

Its value is the definition path of function or struct.

e.g.

  • github.com/gopenapi/gopenapi/internal/delivery/http/handler.PetHandler.FindPetByStatus
  • ./internal/delivery/http/handler.PetHandler.FindPetByStatus

x-$schema

The x-$schema instruction generates data that conforms to openapi-schema from Go struct.

Its value is the definition path of struct.

e.g.

  • github.com/gopenapi/gopenapi/internal/model.Pet
  • ./internal/model.Pet

x-$tags

Same as tags, except that the group field is added to generate 'x-tagGroups' for redoc.

input

x-$tags:
  - name: Regular
    description: Test all features
    group: GroupA
  - name: Edge
    description: Test things that are prone to bugs
    group: GroupB

output

tags:
  - name: Regular
    description: Test all features
  - name: Edge
    description: Test things that are prone to bugs
x-tagGroups:
  - name: GroupA
    tags:
      - Regular
  - name: GroupB
    tags:
      - Edge

Shortcoming

  • Currently, this project is still being tested, Performance is not stable enough, code is not elegant enough.
  • Since it is based on Golang Ast, it currently only supports Golang, and need to enable 'go module'.

Who needs Gopenapi?

If you meet the following situation, maybe you need it

  • Not using openapi
  • Write openapi.yaml by yourself

Don't recommend you who are using go-swagger to use it, unless you want to write openapi.yaml again.

Advanced

So far you already know how to use Gopenapi, if you want more customization, please read on.

What is gopenapi.conf.js?

Gopenapi will generate gopenapi.conf.js file in the root directory of the project after running if this file does not exist.

You can make more custom syntax in this script (In addition to cross-language syntax, such as the functions provided by x-$path, it is built in Gopenapi. nevertheless, you can still customize the format of 'meta-comment').

For example, the x-$path syntax currently supports multiple formats of 'meta-comment':

in yaml

x-$path: ./internal/delivery/http/handler.PetHandler.FindPetByStatus

in go code

// add 'required' field
// 
// $:
//   params: {schema: model.FindPetByStatusParams, required: [status]}
//   response: model.Pet

or

// add 'description' field
// 
// $:
//   params: {schema: model.FindPetByStatusParams, required: [status]}
//   response: {schema: model.Pet, desc: 'success!'}

or

// add more responses
// 
// $:
//   params: {schema: model.FindPetByStatusParams, required: [status]}
//   response: {200: {schema: model.Pet, desc: 'success!'}, 401: '#401'} 

or

// add 'tag' field
// 
// $:
//   params: {schema: model.FindPetByStatusParams, required: [status]}
//   response: {200: {schema: model.Pet, desc: 'success!'}, 401: '#401'} 
//   tags: [pet]

How to write gopenapi.conf.js?

The code in gopenapi.conf.js is very long, I do not recommend you to modify it, you can create a new issue if you have same requirements.

If you really want to modify it, don’t worry about breaking it, just delete it and run gopenapi again will regenerate it.

For example, if we want to add a operationId field, we can write code like this:

In go comments:

// $:
//   params: model.FindPetByStatusParams
//   response: schema([model.Pet]) 
//   tags: [pet]
+ //   operationId: FindPetByStatus

In gopenapi.conf.js:

export default {
  filter: function (key, value) {
    ...
    let path = {
      summary: value.summary,
      description: value.description,
    }
     // use 'console.log(JSON.stringify(value))' to print data-struct of value
+    if (value.meta.operationId) {
+      path.operationId = value.meta.operationId
+    }
    ...

Now the generated openapi will add the operationId field

paths:
  /pet/findByStatus:
    get:
+      operationId: FindPetByStatus
      summary: FindPetByStatus test for return array schema
      description: ""
      ...

FQA

How to distinguish whether the string in 'meta-comments' is JavaScript or pure string?

// $:
//   params: model.FindPetByStatusParams

In the above example, 'model.FindPetByStatusParams' will be parsed into JavaScript execution instead of pure string, because Gopenapi can guessing whether the string is JavaScript or not.

Strings that meet the following rules will be executed as JavaScript:

  • Wrap with '[]'
  • Wrap with '{}'
  • Wrap with 'schema()'
  • string like "model.X" and can find the definition in go source code.

Next goal

  • Optimize code and performance
  • More documentation if you need it
  • Organize the code in gopenapi.conf.js

Releases

No releases published

Packages

No packages published