Composable OpenAPI Specification (aka Swagger)

CI codecov Go Reference

compoas

Library for building, composing and serving OpenAPI Specification (aka Swagger).

Features

This lib provides:

  • golang structs which reflect OpenAPI Specification (check "Limitations" below),
  • embedded Swagger UI (through go:embed) and http.Handler for serving it,
  • functions for merging OpenAPI Specifications and dumping them into a file

Limitations

  • included golang structs not cover entire OpenAPI Specification
  • Swagger UI cannot be customized (only setting specification URL is possible)

Installation

go get github.com/graaphscom/compoas

Example code

Usage

Let's assume we're building a simple e-commerce app (same as in dbmigrat). This app is split into three modules. For now, each module exposes one REST API endpoint:

  • auth (provides an endpoint for signing up)
  • billing (provides an endpoint for fetching orders list - only for authenticated users)
  • inventory (provides an endpoint for fetching a single product)

At the end of this mini-tutorial we will have documentation for each separate module and one merged doc:

That's how our project's directory layout looks like:

|-- ecommerceapp
|   |-- auth
|   |   `-- openapi.go
|   |-- billing
|   |   `-- openapi.go
|   |-- cmd
|   |   |-- dump_openapi
|   |   |   `-- main.go
|   |   `-- start_http_server
|   |       |-- main.go
|   |       `-- openapi // this dir contains dumped specs
|   |           |-- auth.json
|   |           |-- billing.json
|   |           |-- inventory.json
|   |           `-- merged.json
|   `-- inventory
|       `-- openapi.go

At first, let's define OpenAPI Specification for each module. To save space in this README, I'm pasting spec only for the billing module.

billing/openapi.go:

package billing

import (
	"github.com/graaphscom/compoas"
	"github.com/graaphscom/compoas/internal/docs/ecommerceapp/auth"
	"github.com/graaphscom/compoas/internal/docs/ecommerceapp/inventory"
)

var Openapi = compoas.OAS{
	Openapi: "3.0.0",
	Info: compoas.Info{
		Title:   "Billing API",
		Version: "1.0.0",
	},
	Components: &compoas.Components{
		Schemas: map[string]compoas.Schema{
			"Order": {Type: "object", Properties: map[string]compoas.Schema{
				"id":    {Type: "integer"},
				"buyer": {Ref: "#/components/schemas/User-Read"},
				"items": {Type: "array", Items: &compoas.Schema{Ref: "#/components/schemas/Product"}},
			}},
			"User-Read": auth.Openapi.Components.Schemas["User-Read"],
			"Product":   inventory.Openapi.Components.Schemas["Product"],
		},
		SecuritySchemes: auth.Openapi.Components.SecuritySchemes,
	},
	Paths: map[string]compoas.PathItem{
		"/billing/orders": {
			Get: &compoas.Operation{
				Tags: []string{"Billing"},
				Responses: map[string]compoas.Response{
					"200": {Content: map[string]compoas.MediaType{
						"application/json": {Schema: &compoas.Schema{
							Type:  "array",
							Items: &compoas.Schema{Ref: "#/components/schemas/Order"},
						}},
					}},
				},
				Security: []compoas.SecurityRequirement{{"bearerAuth": {}}},
			},
		},
	},
}

inventory/openapi.go: check here

auth/openapi.go: check here

Now it's time to build a command for starting an HTTP server which will be exposing:

  • OpenAPI Specifications as JSON files
  • Swagger UI

Let's begin creating cmd/start_http_server/main.go file:

package main

import (
	"embed"
	"github.com/graaphscom/compoas"
	"log"
	"net/http"
)

//go:embed openapi
var dumpedSpecs embed.FS

func main() {
	oasHandler, err := compoas.UIHandler(
		compoas.SwaggerUIBundleConfig{Urls: []compoas.SwaggerUIBundleUrl{
			{Url: "/openapi/merged.json", Name: "All"},
			{Url: "/openapi/auth.json", Name: "Auth"},
			{Url: "/openapi/billing.json", Name: "Billing"},
			{Url: "/openapi/inventory.json", Name: "Inventory"},
		}},
		"/swagger-ui",
		log.Fatalln,
	)
	if err != nil {
		log.Fatalln(err)
	}

Above code configures handler for serving Swagger UI.

The first argument to the compoas.UIHandler defines URLs where specifications are available.

We want to have Swagger UI under route http://localhost:8080/swagger-ui. For that reason, the second argument to the compoas.UIHandler is /swagger-ui. If Swagger UI should be directly under http://localhost:8080 we would provide / as the second argument.

Now create a handler for static JSON specifications, configure routes and start listening:

package main

import (
	"embed"
	"github.com/graaphscom/compoas"
	"log"
	"net/http"
)

//go:embed openapi
var dumpedSpecs embed.FS

func main() {
	oasHandler, err := compoas.UIHandler(
		compoas.SwaggerUIBundleConfig{Urls: []compoas.SwaggerUIBundleUrl{
			{Url: "/openapi/merged.json", Name: "All"},
			{Url: "/openapi/auth.json", Name: "Auth"},
			{Url: "/openapi/billing.json", Name: "Billing"},
			{Url: "/openapi/inventory.json", Name: "Inventory"},
		}},
		"/swagger-ui",
		log.Fatalln,
	)
	if err != nil {
		log.Fatalln(err)
	}

+ 	mux := http.NewServeMux()
+ 	mux.Handle("/swagger-ui/", oasHandler)
+ 	mux.Handle("/openapi/", http.FileServer(http.FS(dumpedSpecs)))
+ 
+ 	log.Fatalln(http.ListenAndServe(":8080", mux))
+ }

As a final step, we need to prepare command for dumping specifications into JSON files. Let's start creating cmd/dump_openapi/main.go file:

package main

import (
	"github.com/graaphscom/compoas"
	"github.com/graaphscom/compoas/internal/docs/ecommerceapp/auth"
	"github.com/graaphscom/compoas/internal/docs/ecommerceapp/billing"
	"github.com/graaphscom/compoas/internal/docs/ecommerceapp/inventory"
	"log"
	"path"
)

func main() {
	const dir = "cmd/start_http_server/openapi"

	err := auth.Openapi.Dump(true, path.Join(dir, "auth.json"))
	err = billing.Openapi.Dump(true, path.Join(dir, "billing.json"))
	err = inventory.Openapi.Dump(true, path.Join(dir, "inventory.json"))

In the code above we're dumping each module's pretty-printed specification. To dump merged specifications we need to create a new empty specification, the remaining specifications will be merged into it:

package main

import (
	"github.com/graaphscom/compoas"
	"github.com/graaphscom/compoas/internal/docs/ecommerceapp/auth"
	"github.com/graaphscom/compoas/internal/docs/ecommerceapp/billing"
	"github.com/graaphscom/compoas/internal/docs/ecommerceapp/inventory"
	"log"
	"path"
)

func main() {
	const dir = "cmd/start_http_server/openapi"

	err := auth.Openapi.Dump(true, path.Join(dir, "auth.json"))
	err = billing.Openapi.Dump(true, path.Join(dir, "billing.json"))
	err = inventory.Openapi.Dump(true, path.Join(dir, "inventory.json"))

+ 	rootOpenapi := compoas.OAS{
+ 		Openapi: "3.0.0",
+ 		Info: compoas.Info{
+ 			Title:   "e-commerce app",
+ 			Version: "1.0.0",
+ 		},
+ 		Components: &compoas.Components{
+ 			Schemas:         map[string]compoas.Schema{},
+ 			SecuritySchemes: map[string]compoas.SecurityScheme{},
+ 		},
+ 		Paths: map[string]compoas.PathItem{},
+ 	}
+ 	err = rootOpenapi.Merge(auth.Openapi).
+ 		Merge(billing.Openapi).
+ 		Merge(inventory.Openapi).
+ 		Dump(true, path.Join(dir, "merged.json"))
+ 
+ 	if err != nil {
+ 		log.Fatalln(err)
+ 	}
+ }

It's time to start our HTTP server:

  1. make sure that directory cmd/start_http_server/openapi exists
  2. dump specifications - run go run cmd/dump_openapi/main.go
  3. start server - run go run cmd/start_http_server/main.go
  4. visit http://localhost:8080/swagger-ui in your web browser
Similar Resources

Openapi - OpenAPI 3.x parser. Written in Go

OpenAPI OpenAPI specification object model Features Easy to integrate. Installat

Nov 23, 2022

A diff tool for OpenAPI Specification 3

OpenAPI Diff This is a diff tool for OpenAPI Spec 3. It can be used in two ways: Generate a diff report in YAML, Text/Markdown or HTML from the cmd-li

Jan 5, 2023

OpenAPI specification and related artifacts for HashiCorp Nomad

Overview This repository contains the HashiCorp Nomad OpenAPI specification and related artifacts. The OpenAPI specification defines a machine-readabl

Dec 14, 2022

Go types and validation for OpenAPI Specification 3.1

openapi Package openapi is a set of Go types for OpenAPI Specification 3.1. The primary purpose of the package is to assist in generation of OpenAPI d

Nov 10, 2022

OpenAPI Terraform Provider that configures itself at runtime with the resources exposed by the service provider (defined in a swagger file)

OpenAPI Terraform Provider that configures itself at runtime with the resources exposed by the service provider (defined in a swagger file)

Terraform Provider OpenAPI This terraform provider aims to minimise as much as possible the efforts needed from service providers to create and mainta

Dec 26, 2022

Swagger + Gin = SwaGin, a web framework based on Gin and Swagger

Swagger + Gin = SwaGin, a web framework based on Gin and Swagger

Swagger + Gin = SwaGin Introduction SwaGin is a web framework based on Gin and Swagger, which wraps Gin and provides built-in swagger api docs and req

Dec 30, 2022

Swagger + Gin = SwaGin, a web framework based on Gin and Swagger

Swagger + Gin = SwaGin, a web framework based on Gin and Swagger

Swagger + Gin = SwaGin Introduction SwaGin is a web framework based on Gin and Swagger, which wraps Gin and provides built-in swagger api docs and req

Dec 30, 2022

Swagger-go-chi - Generate a go-chi server from swagger

swagger-go-chi Install go install github.com/cugu/swagger-go-chi@main Run swagge

Nov 5, 2022

Package for controlling the Windows firewall (aka Windows Filtering Platform, WFP)

wf What This is a package for controlling the Windows Filtering Platform (WFP), also known as the Windows firewall. See its docs: https://godoc.org/in

Dec 6, 2022

Lightweight HTTP mocking in Go (aka golang)

httpmock This library builds on Go's built-in httptest library, adding a more mockable interface that can be used easily with other mocking tools like

Dec 16, 2022

Simple attempt at making a program to Brute Force Gift codes for Roberts Space Industries AKA Star Citizen.

Simple attempt at making a program to Brute Force Gift codes for Roberts Space Industries AKA Star Citizen.

Roberts Space Industries: Gift Generator Simple attempt at making a program to Brute Force Gift codes for Roberts Space Industries AKA Star Citizen. I

Nov 2, 2021

The project aims to provide the utility for Kunlun-Cluster aka KTS

Kunlun Tool Set Description This project aims to provide the utility for Kunlun-Cluster aka 'KTS' Including but not limited to backup/restore tools...

Jul 1, 2022

gup aka Get All Urls parameters to create wordlists for brute forcing parameters.

gup aka Get All Urls parameters to create wordlists for brute forcing parameters.

Description GUP is a tool to create wrodlists from the urls. Purpose The purpose of this tool is to create wordlists for brute forcing parameters. Ins

Feb 25, 2022

Just a playground with some interesting concepts like pipelines aka middleware, handleFuncs, request validations etc. Check it out.

Pipeline a.k.a middleware in Go Just a playground with some interesting concepts like pipelines aka middleware, handleFuncs, request validations etc.

Dec 9, 2021

Statefulset-scheduler (aka sfs-scheduler)

statefulset-scheduler (aka sfs-scheduler) Installation I already upload docker i

Dec 19, 2021

This is a golang C2 + Implant that communicates via Protocol Buffers (aka. protobufs).

Br4vo6ix DISCLAIMER: This tool is for educational, competition, and training purposes only. I am in no way responsible for any abuse of this tool This

Nov 9, 2022

Golang - Learning go aka Flow with the go

golang learning go aka Flow with the go! helpful links tour of go: https://go.de

Feb 3, 2022

Composable, observable and performant config handling for Go for the distributed processing era

Konfig Composable, observable and performant config handling for Go. Written for larger distributed systems where you may have plenty of configuration

Dec 11, 2022

Structured, composable logging for Go

Structured, composable logging for Go

log15 Package log15 provides an opinionated, simple toolkit for best-practice logging in Go (golang) that is both human and machine readable. It is mo

Dec 18, 2022
Go types and validation for OpenAPI Specification 3.1

openapi Package openapi is a set of Go types for OpenAPI Specification 3.1. The primary purpose of the package is to assist in generation of OpenAPI d

Nov 10, 2022
Swagger-go-chi - Generate a go-chi server from swagger

swagger-go-chi Install go install github.com/cugu/swagger-go-chi@main Run swagge

Nov 5, 2022
UPBit Auto Trading with OpenAPI Golang Module

Go-Bit! UPBit Auto Trading System with OpenAPI 이 레포지토리는 upbit를 위한 자동매매 프로그램을 개발하기 위해 제공하는 go module입니다. Features 구현 작업 진행상황 Sample Code Template shiel

Jun 27, 2022
OpenAPI Client and Server Code Generator

This package contains a set of utilities for generating Go boilerplate code for services based on OpenAPI 3.0 API definitions

Dec 2, 2022
Entgo openapi example for go

entgo-openapi-example Example app created with ent entgen swagger-editor See https://entgo.io/blog/2021/09/10/openapi-generator/ License MIT Author Ya

Nov 27, 2021
This project extends the go-chi router to support OpenAPI 3, bringing to you a simple interface to build a router conforming your API contract.

Go OpenAPI This project extends the go-chi router to support OpenAPI 3, bringing to you a simple interface to build a router conforming your API contr

Mar 27, 2022
Conversion from OpenAPI definitions to krakend configuration.

Description Basic conversion from OpenAPI specification to Krakend config. This is extendable with custom OpenAPI attributes and more support for both

Dec 13, 2022
Generates Golang client and server based on OpenAPI2 (swagger) definitions
Generates Golang client and server based on OpenAPI2 (swagger) definitions

ExperienceOne Golang APIKit ExperienceOne Golang APIKit Overview Requirements Installation Usage Generate standard project structure Define the API wi

Aug 9, 2022
CRUD API server of Clean Architecture with Go(Echo), Gorm, MySQL, Docker and Swagger
CRUD API server of Clean Architecture with Go(Echo), Gorm, MySQL, Docker and Swagger

CRUD API Server of Clean Architecture Go(echo) gorm mysql docker swagger build docker-compose up -d --build API Postman and Fiddler is recommended to

May 30, 2021
sso, aka S.S.Octopus, aka octoboi, is a single sign-on solution for securing internal services
sso, aka S.S.Octopus, aka octoboi, is a single sign-on solution for securing internal services

sso See our launch blog post for more information! Please take the SSO Community Survey to let us know how we're doing, and to help us plan our roadma

Jan 5, 2023