swagno

package module
v0.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 29, 2023 License: MIT Imports: 13 Imported by: 0

README

Swagno: Simplified Swagger Documentation Creation

Swagno Logo

Swagno offers a streamlined approach to create Swagger Documentation 2.0. With Swagno, you can declare documentation details directly in code, eliminating the need for annotations, exported files, or commands. This approach simplifies the process of generating a JSON string to serve with a handler.

About the Project

This project inspired by Swaggo. Swaggo, uses annotations, exports files and needs to run by command. If you don't like this way, Swagno appears as a good alternative.

This project was then forked from go-swagno/swagno with the goal of being more idiomatic and user friendly. While trying to achieve these goals a lot of breaking changes were made and hence why this repo is separate as opposed to being merged into the original.

Compared to the original Swagno, this version includes:

  • An API that's more idiomatic and easier to read.
  • Enhanced type safety.
  • Functional option parameters for flexible and robust endpoint creation.
  • Support for multiple response and error model types for endpoints.
  • Core structural and semantic bug fixes in rendering Swagger/OpenAPI pages.
Before and After Comparison

Before: The constructor function was less flexible and lacked type safety.
After: The new constructor is more idiomatic and supports multiple responses and errors.

Before Example
endpoints := []Endpoint{
  // constructor function doesn't allow for options, only allows for one error response with not configuring of things like response code and description, and no type safety
  EndPoint(GET, "/product", "product", Params(), nil, []models.Product{}, models.ErrorResponse{}, "Get all products", nil), 
  EndPoint(GET, "/product/{id}", "product", Params(IntParam("id", true, "")), nil, models.Product{}, models.ErrorResponse{}, "", nil),
  EndPoint(POST, "/product", "product", Params(), models.ProductPost{}, models.Product{}, models.ErrorResponse{}, "", nil),
  // no return
  EndPoint(POST, "/product-no-return", "product", Params(), nil, nil, models.ErrorResponse{}, "", nil),
  // no error
  EndPoint(POST, "/product-no-error", "product", Params(), nil, nil, nil, "", nil),
}

After:

// New constructor is idiomatic, allows for the client to use as many or as little options as they like, and allows for multiple responses and errors to be modelled for endpoints instead of restricting to just one.
endpoints := []*endpoint.EndPoint{
  endpoint.New(
   endpoint.WithMethod(endpoint.GET),
   endpoint.WithPath("/product/page"),
   endpoint.WithTags("product"),
   endpoint.WithSuccessfulReturns([]response.Info{models.UnsuccessfulResponse{}}),
   endpoint.WithErrors([]response.Info{models.EmptySuccessfulResponse{}}),
   endpoint.WithDescription(desc),
   endpoint.WithProduce([]mime.MIME{mime.JSON, mime.XML}),
   endpoint.WithConsume([]mime.MIME{mime.JSON}),
  ),
  endpoint.New(
   endpoint.WithMethod(endpoint.GET),
   endpoint.WithPath("/product"),
   endpoint.WithTags("product"),
   endpoint.WithParams(parameter.IntParam("id", parameter.WithRequired())),
   endpoint.WithSuccessfulReturns([]response.Info{models.SuccessfulResponse{}}),
   endpoint.WithErrors([]response.Info{models.UnsuccessfulResponse{}}),
  ),
  endpoint.New(
   endpoint.WithMethod(endpoint.GET),
   endpoint.WithPath("/product/{id}/detail"),
   endpoint.WithTags("product"),
   endpoint.WithParams(parameter.IntParam("id", parameter.WithRequired())),
   endpoint.WithSuccessfulReturns([]response.Info{models.SuccessfulResponse{}}),
   endpoint.WithErrors([]response.Info{models.UnsuccessfulResponse{}}),
  )
}

Contents

Getting started

  1. Server Example here

  2. Get swagno package in your project

go get github.com/domhoward14/swagno
  1. Import swagno
import "github.com/domhoward14/swagno"
import "github.com/go-swagno/swagno-http/swagger" // recommended if you want to use their http handler for serving swagger docs
  1. Create your endpoints (check Endpoints) with it's corresponding parameters. Example:
 endpoints := []*endpoint.EndPoint{
  endpoint.New(
   endpoint.WithMethod(endpoint.GET),
   endpoint.WithPath("/product/page"),
   endpoint.WithTags("product"),
   endpoint.WithSuccessfulReturns([]response.Info{models.UnsuccessfulResponse{}}),
   endpoint.WithErrors([]response.Info{models.EmptySuccessfulResponse{}}),
   endpoint.WithDescription(desc),
   endpoint.WithProduce([]mime.MIME{mime.JSON, mime.XML}),
   endpoint.WithConsume([]mime.MIME{mime.JSON}),
  ),
  endpoint.New(
   endpoint.WithMethod(endpoint.GET),
   endpoint.WithPath("/product"),
   endpoint.WithTags("product"),
   endpoint.WithParams(parameter.IntParam("id", parameter.WithRequired())),
   endpoint.WithSuccessfulReturns([]response.Info{models.SuccessfulResponse{}}),
   endpoint.WithErrors([]response.Info{models.UnsuccessfulResponse{}}),
  ),
  endpoint.New(
   endpoint.WithMethod(endpoint.GET),
   endpoint.WithPath("/product/{id}/detail"),
   endpoint.WithTags("product"),
   endpoint.WithParams(parameter.IntParam("id", parameter.WithRequired())),
   endpoint.WithSuccessfulReturns([]response.Info{models.SuccessfulResponse{}}),
   endpoint.WithErrors([]response.Info{models.UnsuccessfulResponse{}}),
  ),
  endpoint.New(
    endpoint.WithMethod(endpoint.POST),
    endpoint.WithPath("/product"),
    endpoint.WithTags("product"),
    endpoint.WithBody(models.ProductPost{}),
    endpoint.WithSuccessfulReturns([]response.Info{models.SuccessfulResponse{}}),
    endpoint.WithErrors([]response.Info{models.UnsuccessfulResponse{}}),
    endpoint.WithProduce([]mime.MIME{mime.JSON, mime.XML}),
  ),
}
  1. Create Swagger(swagno) instance
sw := swagno.New(swagno.Config{Title: "Testing API", Version: "v1.0.0"})
  1. Use sw.AddEndpoints function to add endpoints arrays to Swagno
sw.AddEndpoints(endpoints)

// you can also add more arrays
sw.AddEndpoints(productEndpoints)
sw.AddEndpoints(merchantEndpoints)
  1. Generate json as string and give it to your handler to serve. You can create your own handler or use the swagno http handler
 http.HandleFunc("/swagger/", swagger.SwaggerHandler(sw.GenerateDocs()))
 fmt.Println("Server is running on http://localhost:8080")
 http.ListenAndServe(":8080", nil)

Implementation Status

As purpose of this section, you can compare swagno status with swaggo

Swagger 2.0 document

See how Swagno compares to Swaggo in terms of Swagger 2.0 features:

  • Basic Structure: ✅
  • API Host and Base Path: ✅
  • Paths and Operations: ✅
  • Describing Parameters: ✅
  • Describing Request Body: ✅
  • Describing Responses: ✅
  • MIME Types: 🔄 (Improvement needed)
  • Authentication: ✅
  • File Upload: 🔄 (Improvement needed)
  • Enums: ✅
  • Grouping Operations With Tags: ✅
  • Swagger Extensions: 🔜 (Coming soon)

Create Your Swagger

General Swagger Info

Swagger v2.0 specifications can be found here

You can use the swagger config when creating new swagger object

type Config struct {
 Title   string   // title of the Swagger documentation
 Version string   // version of the Swagger documentation
 Host    string   // host URL for the API
 Path    string   // path to the Swagger JSON file
 License *License // license information for the Swagger documentation
 Contact *Contact // contact information for the Swagger documentation
}
sw := swagno.New(swagno.Config{Title: "Testing API", Version: "v1.0.0"}) // optionally you can also use the License and Info properties as well

Endpoints (API)

Definition:

type EndPoint struct {
 method            string
 path              string
 params            []*parameter.Parameter
 tags              []string
 Body              interface{}
 successfulReturns []response.Info
 errors            []response.Info
 description       string
 summary           string
 consume           []mime.MIME
 produce           []mime.MIME
 security          []map[string][]string
}

You need to create an Endpoint array []Endpoint and add your endpoints in this array. Example:

import "github.com/domhoward14/swagno/components/endpoint"

endpoints := []endpoint.Endpoint{
  endpoint.New(
    endpoint.WithMethod(endpoint.POST),
    endpoint.WithPath("/product"),
    endpoint.WithTags("product"),
    endpoint.WithBody(models.ProductPost{}),
    endpoint.WithSuccessfulReturns([]response.Info{models.SuccessfulResponse{}}),
    endpoint.WithErrors([]response.Info{models.UnsuccessfulResponse{}}),
    endpoint.WithProduce([]mime.MIME{mime.JSON, mime.XML}),
    ),
}
// add endpoints array to Swagno
sw.AddEndpoints(endpoints)

Note: You can simply add only one endpoint by using AddEndpoint(endpoint)

Endpoint Options

Arguments: The Endpoint object is configured via the With<property> functional options provided in the github.com/domhoward14/swagno/components/endpoint package

Function Description
WithMethod(method string) Sets the HTTP method of the EndPoint.
WithPath(path string) Sets the path for the EndPoint.
WithParams(params []*parameter.Parameter) Adds parameters to the EndPoint.
WithTags(tags ...string) Assigns tags to the EndPoint for grouping and categorization.
WithBody(body interface{}) Sets the request body structure expected by the EndPoint.
WithSuccessfulReturns(successfulReturns ...response.Info) Sets the successful responses from the EndPoint. Needs to implement the response.Info interface
WithErrors(errors ...response.Info) Sets the error responses the EndPoint could return. Needs to implement the response.Info interface
WithDescription(description string) Provides a detailed description of what the EndPoint does.
WithSummary(summary string) Gives a brief summary of the EndPoint purpose.
WithConsume(consume ...mime.MIME) Sets the MIME types the EndPoint can consume (input formats).
WithProduce(produce ...mime.MIME) Sets the MIME types the EndPoint can produce (output formats).
WithSecurity(security ...map[string][]string) Sets security requirements for the EndPoint, such as required scopes or auth methods.

Don't forget to add your endpoints array to Swagno prior to serving requests

sw.AddEndpoints(endpoints)
Parameters

You can use endpoint.WithParams() function to generate params array for an Endpoint object:

// path should be -> /product/{merchant}/{id}
endpoint.WithParams(
    parameter.StrParam("id", parameter.WithIn(parameter.Path), parameter.WithRequired()), 
    parameter.StrParam("merchant", parameter.WithIn(parameter.Path), parameter.WithRequired()),
    ),
Parameter Location

Each parameter value can be assigned to a different location for the api request (i.e. [query, header, path, form]) using WithIn

parameter.WithIn(parameter.Query)
Location Type Description
Query Used for parameters in the URL query string.
Header Used for parameters in the HTTP header.
Path Used for parameters within the path of the URL.
Form Used for parameters submitted through form data in POST requests.
Parameter Types

Below are all the parameter types that the EndPoint object can take as input

Function Description
IntParam(name string, ...) Creates an integer parameter.
StrParam(name string, ...) Creates a string parameter.
BoolParam(name string, ...) Creates a boolean parameter.
FileParam(name string, ...) Creates a file upload parameter.
IntQuery(name string, ...) Creates an integer query parameter.
StrQuery(name string, ...) Creates a string query parameter.
BoolQuery(name string, ...) Creates a boolean query parameter.
IntHeader(name string, ...) Creates an integer header parameter.
StrHeader(name string, ...) Creates a string header parameter.
BoolHeader(name string, ...) Creates a boolean header parameter.
IntEnumParam(name string, arr []int64, ...) Creates an integer enum parameter.
StrEnumParam(name string, arr []string, ...) Creates a string enum parameter.
IntEnumQuery(name string, arr []int64, ...) Creates an integer enum query parameter.
StrEnumQuery(name string, arr []string, ...) Creates a string enum query parameter.
IntEnumHeader(name string, arr []int64, ...) Creates an integer enum header parameter.
StrEnumHeader(name string, arr []string, ...) Creates a string enum header parameter.
IntArrParam(name string, arr []int64, ...) Creates an integer array parameter.
StrArrParam(name string, arr []string, ...) Creates a string array parameter.
IntArrQuery(name string, arr []int64, ...) Creates an integer array query parameter.
StrArrQuery(name string, arr []string, ...) Creates a string array query parameter.
IntArrHeader(name string, arr []int64, ...) Creates an integer array header parameter.
StrArrHeader(name string, arr []string, ...) Creates a string array header parameter.
Parameter Options

Just like the endpoint package, the parameter package also comes with a set of functional With<Option> options to configure a parameter.

Modifier Function Description
WithType(t ParamType) Sets the type of a parameter (integer, string, boolean, and etc.).
WithIn(in Location) Defines where the parameter is expected (query, header).
WithRequired() Makes the parameter required.
WithDescription(description string) Provides a description for the parameter.
WithDefault(defaultValue interface{}) Sets a default value for the parameter.
WithFormat(format string) Sets the format field for the parameter.
WithMin(min int) sets the Min field of a Parameter.
WithMax(max int) sets the Max field of a Parameter.
WithMinLen(minLen int) sets the MinLen field of a Parameter.
WithMaxLen(maxLen int) sets the MaxLen field of a Parameter.
WithPattern(pattern string) sets the Pattern field of a Parameter.
WithMaxItems(maxItems int) sets the WithMaxItems field of a Parameter.
WithMinItems(minItems int) sets the WithMinItems field of a Parameter.
WithUniqueItems(uniqueItems bool) Sets the WithUniqueItems filed of a Parameter
WithMultipleOf(multipleOf int64) Sets the WithMultipleOf filed of a Parameter
WithCollectionFormat(c CollectionFormat) Sets the WithCollectionFormat filed of a Parameter

Defining Models

You can define models for the following type of objects below. Look here for specific model examples.

❗ When modeling error/successful responses they need to implement the interface below to properly generate their Swagger/OpenAPI output.❗

package response

// Info is an interface for response information.
type Info interface {
 GetDescription() string
 GetReturnCode() string
}
Successful Response/Return

use a struct model instance like models.EmptySuccessfulResponse{} or nil

Error Response

use a struct model instance like models.UnsuccessfulResponse{} or nil

Request Body

use a struct model instance like models.PostBody{} or nil

Security (optional)

Also provides functions to set different security configurations for swagger doc

sw.SetBasicAuth()
sw.SetApiKeyAuth("api_key", "query")
sw.SetOAuth2Auth("oauth2_name", "password", "http://localhost:8080/oauth2/token", "http://localhost:8080/oauth2/authorize", security.Scopes(security.Scope("read:pets", "read your pets"), security.Scope("write:pets", "modify pets in your account")))

Contribution

We are welcome to any contribution. Swagno still has some missing features. Also we want to enrich handler implementations for other web frameworks.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Config

type Config struct {
	Title   string   // title of the Swagger documentation
	Version string   // version of the Swagger documentation
	Host    string   // host URL for the API
	Path    string   // path to the Swagger JSON file
	License *License // license information for the Swagger documentation
	Contact *Contact // contact information for the Swagger documentation
}

Config struct represents the configuration for Swagger documentation.

type Contact

type Contact struct {
	Name string `json:"name"` // name of the contact person
}

Contact struct represents the contact information for Swagger documentation.

type Info

type Info struct {
	Title          string   `json:"title"`
	Version        string   `json:"version"`
	TermsOfService string   `json:"termsOfService,omitempty"`
	Contact        *Contact `json:"contact,omitempty"`
	License        *License `json:"license,omitempty"`
}

Info represents the information about the API. https://swagger.io/specification/v2/#info-object

type License

type License struct {
	Name string `json:"name"` // name of the license
	URL  string `json:"url"`  // URL for the license
}

License struct represents the license information for Swagger documentation.

type Swagger

type Swagger struct {
	Swagger             string                                      `json:"swagger" default:"2.0"`
	Info                Info                                        `json:"info"`
	Paths               map[string]map[string]endpoint.JsonEndPoint `json:"paths"`
	BasePath            string                                      `json:"basePath" default:"/"`
	Host                string                                      `json:"host" default:""`
	Definitions         map[string]definition.Definition            `json:"definitions"`
	Schemes             []string                                    `json:"schemes,omitempty"`
	Tags                []tag.Tag                                   `json:"tags,omitempty"`
	SecurityDefinitions map[string]securityDefinition               `json:"securityDefinitions,omitempty"`
	// contains filtered or unexported fields
}

The full JSON model for swagger v2 documentation https://swagger.io/docs/specification/2-0/basic-structure/

func New

func New(c Config) *Swagger

New creates a new swagger instance with the provided config

func (*Swagger) AddEndpoint

func (s *Swagger) AddEndpoint(e *endpoint.EndPoint)

func (*Swagger) AddEndpoints

func (s *Swagger) AddEndpoints(e []*endpoint.EndPoint)

Add EndPoint models to Swagger endpoints

func (*Swagger) AddTags

func (swagger *Swagger) AddTags(tags ...tag.Tag)

func (*Swagger) ExportSwaggerDocs

func (swagger *Swagger) ExportSwaggerDocs(out_file string) string

ExportSwaggerDocs exports the Swagger documentation as a JSON file.

func (Swagger) GenerateDocs

func (s Swagger) GenerateDocs() (jsonDocs []byte)

Generate swagger v2 documentation as json string

func (Swagger) SetApiKeyAuth

func (s Swagger) SetApiKeyAuth(name string, in string, description ...string)

SetApiKeyAuth sets the API key authentication security definition in the Swagger object. For more information, refer to: https://swagger.io/specification/v2/#api-key-sample

func (Swagger) SetBasicAuth

func (s Swagger) SetBasicAuth(description ...string)

SetBasicAuth sets the basic authentication security definition in the Swagger object. For more information, refer to: https://swagger.io/specification/v2/#basic-authentication-sample

func (Swagger) SetOAuth2Auth

func (s Swagger) SetOAuth2Auth(name string, flow string, authorizationUrl string, tokenUrl string, scopes map[string]string, description ...string)

SetOAuth2Auth sets the OAuth2 authentication security definition in the Swagger object. For more information, refer to: https://swagger.io/specification/v2/#implicit-oauth2-sample

Directories

Path Synopsis
components
tag
http

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL