Git Product home page Git Product logo

goas's Introduction

goas

The project is based on

Generate OpenAPI Specification json file with comments in Go.

Limit

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

Install

go get -u github.com/mikunalpha/goas

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 Abcd
// @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

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

Handler funcs

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:"Mikun"` 
}

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

type Error struct {
  Code string `json:"code"`
  Msg  string `json:"msg"`
}

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

// @Title Get user list of a group.
// @Description Get users related to a specific group.
// @Param  groupID  path  int  true  "Id of a specific group."
// @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 & 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}
@Param  user    body  User      true        "Info of a user."
  • {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.

Response

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

@Failure  {stauts}  {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.

Documentation Generation

Go to the folder where is main.go in

// go.mod and main file are in the same directory
goas --module-path . --output oas.json

// go.mod and main file are in the different directory
goas --module-path . --main-file-path ./cmd/xxx/main.go --output oas.json

goas's People

Contributors

appleboy avatar jorygeerts avatar mikunalpha 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

goas's Issues

Update to urfave/cli introduces breaking changes

This also broke swaggo/swag#556, but you can no longer build this tool with the latest CLI since it recently introduced a breaking change:

..\mikunalpha\goas\main.go:13:16: cannot use cli.StringFlag literal (type cli.StringFlag) as type cli.Flag in array or slice literal:
        cli.StringFlag does not implement cli.Flag (Apply method has pointer receiver)
..\mikunalpha\goas\main.go:18:16: cannot use cli.StringFlag literal (type cli.StringFlag) as type cli.Flag in array or slice literal:
        cli.StringFlag does not implement cli.Flag (Apply method has pointer receiver)
..\mikunalpha\goas\main.go:23:16: cannot use cli.StringFlag literal (type cli.StringFlag) as type cli.Flag in array or slice literal:
        cli.StringFlag does not implement cli.Flag (Apply method has pointer receiver)
..\mikunalpha\goas\main.go:28:16: cannot use cli.StringFlag literal (type cli.StringFlag) as type cli.Flag in array or slice literal:
        cli.StringFlag does not implement cli.Flag (Apply method has pointer receiver)
..\mikunalpha\goas\main.go:33:14: cannot use cli.BoolFlag literal (type cli.BoolFlag) as type cli.Flag in array or slice literal:
        cli.BoolFlag does not implement cli.Flag (Apply method has pointer receiver)
..\mikunalpha\goas\main.go:40:23: c.GlobalString undefined (type *cli.Context has no field or method GlobalString)
..\mikunalpha\goas\main.go:40:120: c.GlobalBool undefined (type *cli.Context has no field or method GlobalBool)
..\mikunalpha\goas\main.go:45:26: c.GlobalString undefined (type *cli.Context has no field or method GlobalString)

Feature: Strip repository path from component name

Right now, the full repository path to each component is visible in the generated Swagger JSON.

For instance:

{
  "components": {
    "schemas": {
      "gitlab.mycompany.local.mygroup.myproject.internal.web.SomeInput": {
        "type": "object"
      }
    }
  }
}

I'd like to be able to strip (or modify) this, so the component name is simply web.SomeInput (or internal.web.SomeInput, or something like that).

I see three basic option for this, each with its own pro's and cons.

Always strip the domainname and group (and project?)
Pro's: easy to implement, doesn't make anything harder to use.
Cons: Collisions are possible. Any users who are (for whatever reason) relying on component names won't be happy.

Make stripping parts of the component path a runtime option
Possibly by adding CLI options, eg --strip-component gitlab.mycompany.local/mygroup
Pro's: flexible, opt-in
Cons: Makes the tool a bit harder to use (for users who would want to use this). Collisions are also possible, but now the user would have a way to control this.

Support defining an alias somewhere
If it where possible to define a component alias (either on the struct or the package, or perhaps even during import (but not to be confused by import aliasses) this would grant the ultimate flexibility.
Pro's: Opt in, maximal flexibility
Cons: Even more comments throughout the source code that only serve the Swagger documentation. Depending on the "scope" of the alias, moving a struct to another file may unintentionally change the way the name of the component ends up on the Swagger JSON.

mikunalpha is this an idea you could get behind? If so, I'd be happy to implement it. If not, I'll just add some kind of string replace in our CI scripts.

License

Hey, great work on this! Any chance you could add a license file to the project?

Is it possible to use structs in different module(/repository) for input/output?

I have a repository (say github.com/foo/bar) that contains types that I want to use as output for my handlers. I've tried the following:

  1. @Failure 400 object bar.MyError
  2. @Failure 400 object github.com/foo/bar/MyError
  3. @Failure 400 object github.com/foo/bar/bar.MyError

The resulting swagger JSON for all of these is this:

"components": {
    "schemas": {
      "": {}
    }
  }

So goas sees there is something, it just can't do anything useful with it.

The type is imported and used in the file where its referenced by the godoc.

Am I doing something wrong? Or is this not supported?

Question about Security settings

Hi - cool utility!
Looks like you hard-coded the security schema; I'd like to add/change it, but haven't figured out the comment syntax... If you wouldn't mind suggesting a way to do this, I'd appreciate it.

Error: parseImportStatements

Hello, I am generating the documentation for one of my projects, but I have this error

2020/08/20 10:48:18 gopkg.in/yaml.v2 -> /Users/joborettoble/go/pkg/mod/gopkg.in/[email protected]
2020/08/20 10:48:19 Error: parseImportStatements: parse of /Users/joborettoble/go/pkg/mod/golang.org/x/[email protected]/cmd/fiximports/testdata/src/old.com/bad package cause error: /Users/joborettoble/go/pkg/mod/golang.org/x/[email protected]/cmd/fiximports/testdata/src/old.com/bad/bad.go:2:43: expected 'package', found 'EOF'

One of my modules has this dependency
https://github.com/golang/tools/blob/master/cmd/fiximports/testdata/src/old.com/bad/bad.go

How can we handle this error?

Thanks!

Error: imported nested objects

When I use object from another package, that have inside another object, then those nested one are not correctly registered as separate component and thus reference is invalid.

I've created a simple example:
https://gitlab.com/IceExplosive/goas-test

PackageA has two objects... one nested into another.
PackageB has two route definitions, both using object from PackageA

Inner object (TestB) from PackageA is not registered as separate schema so routes from PackageB have invalid reference.
Weird thing is, if I remove one of those two routes, it's working fine.. once I created second route using the same TestA object, it breaks OpenApi schema.

Type Alias + Type Embedding causes panic:

Hi @mikunalpha - thanks for this project

I'm hitting an issue when combining type aliasing with type embedding (both of these on their own are fine)

my minimal reproduction main.go

package main

import "fmt"

// @Version 1.0.0
// @Title Backend API

func main() {
	fmt.Println("hi")
}

type C struct {
	ID int
}

type B C

type A struct {
	B
}

// @Title Get comment list of a match.
// @Success  200  array  A  "A JSON"
// @Route /match/get_comments [post]
func something() {
}

with this spec, calling goas fails with the below error

$ goas
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x8 pc=0x666451]

goroutine 1 [running]:
github.com/iancoleman/orderedmap.(*OrderedMap).Keys(...)
        /home/mark/go/pkg/mod/github.com/iancoleman/[email protected]/orderedmap.go:80
main.(*parser).parseSchemaPropertiesFromStructFields(0xc00014c6e0, 0xc0000c2620, 0x8, 0xc0000c2828, 0x3, 0xc00017e000, 0xc0000c6120, 0x1, 0x1)
        /home/mark/go/pkg/mod/github.com/mikunalpha/[email protected]/parser.go:1215 +0x1d71
main.(*parser).parseSchemaObject(0xc00014c6e0, 0xc0000c2620, 0x8, 0xc0000c2828, 0x3, 0xc0000be199, 0x1, 0x548e00, 0xc0000cd360, 0x6e1c1a)
        /home/mark/go/pkg/mod/github.com/mikunalpha/[email protected]/parser.go:947 +0x1010
main.(*parser).registerType(0xc00014c6e0, 0xc0000c2620, 0x8, 0xc0000c2828, 0x3, 0xc0000be199, 0x1, 0x68ce60, 0x7fcd431ee501, 0xc0000c29b8, ...)
        /home/mark/go/pkg/mod/github.com/mikunalpha/[email protected]/parser.go:829 +0x16c
main.(*parser).parseResponseComment(0xc00014c6e0, 0xc0000c2620, 0x8, 0xc0000c2828, 0x3, 0xc0000c8a80, 0xc0000be18d, 0x17, 0x8, 0x3)
        /home/mark/go/pkg/mod/github.com/mikunalpha/[email protected]/parser.go:761 +0x4f5
main.(*parser).parseOperation(0xc00014c6e0, 0xc0000c2620, 0x8, 0xc0000c2828, 0x3, 0xc0000da980, 0x3, 0x4, 0xc0000daab0, 0xc0000c2620)
        /home/mark/go/pkg/mod/github.com/mikunalpha/[email protected]/parser.go:587 +0x6ab
main.(*parser).parsePaths(0xc00014c6e0, 0x0, 0x0)
        /home/mark/go/pkg/mod/github.com/mikunalpha/[email protected]/parser.go:547 +0x129
main.(*parser).parseAPIs(0xc00014c6e0, 0x0, 0x0)
        /home/mark/go/pkg/mod/github.com/mikunalpha/[email protected]/parser.go:422 +0x85
main.(*parser).CreateOASFile(0xc00014c6e0, 0x6e7e45, 0x8, 0x0, 0x0)
        /home/mark/go/pkg/mod/github.com/mikunalpha/[email protected]/parser.go:205 +0xd7
main.action(0xc00014c580, 0xc00014c580, 0xc0000cd090)
        /home/mark/go/pkg/mod/github.com/mikunalpha/[email protected]/main.go:45 +0x1d6
github.com/urfave/cli.HandleAction(0x690860, 0x701410, 0xc00014c580, 0xc00014c580, 0x0)
        /home/mark/go/pkg/mod/github.com/urfave/[email protected]/app.go:524 +0x105
github.com/urfave/cli.(*App).Run(0xc00015c000, 0xc0000a01f0, 0x1, 0x1, 0x0, 0x0)
        /home/mark/go/pkg/mod/github.com/urfave/[email protected]/app.go:286 +0x675
main.main()
        /home/mark/go/pkg/mod/github.com/mikunalpha/[email protected]/main.go:63 +0x165

if I change the definition of type A to

type A struct {
	C
}

it works like a charm

but unfortunately I'm working on a big existing project and changing all these cases is probably not feasible.

I'd be happy to make a PR myself with a fix if you prefer, but may need some direction on how to go about that ๐Ÿ™‚

Handle ( go.mod's ) replace gracefully

My go.mod has a specific replace
replace github.com/AdRoll/goamz => github.com/arvados/goamz v0.0.0-20190905141525-1bba09f407ef

and goas fails saying:
2020/08/05 18:13:32 Error: expect package version, got "=>"

When I comment out that line in go.mod, everything works as expected

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.