Generates Golang client and server based on OpenAPI2 (swagger) definitions

Related tags

Microservices apikit
Overview

Experience One

ExperienceOne Golang APIKit

Overview

The APIKit enables the rapid development of Web APIs with Golang by providing the functionality to (re-)generate the communication layer of the API based on an OpenAPIv2 (Swagger) definition, both for the client and server part. It also helps with one-time generation of stubs for the server-side endpoint handlers. The generated API code does fully handle (and thus hide) the HTTP layer of the application, so the developer can focus on business logic implementation. Integration between API core and HTTP layer is handled via generated structs and interfaces. The API HTTP layer can be regenerated from the OpenAPIv2 definition without breaking the integration with the API core code. This enables a "definition first" approach that ensures a 100% match of OpenAPI / Swagger definition and the implemented API.

Specifically the APIKit contains a CLI to generate and update the following API related items:

  • standard project directory structures and common files
  • validation of OpenAPIv2 (Swagger) definition
  • HTTP API client based on an OpenAPIv2 (Swagger) definition
  • HTTP API server based on an OpenAPIv2 (Swagger) definition
  • stubs for server API endpoint handlers

See the compliance list for a detailed list of supported OpenAPIv2 features.

Requirements

  • Golang 1.11 or higher
  • make (if you want to use the Makefile)

Installation

git clone [email protected]:ExperienceOne/apikit.git
cd apikit
make install

Usage

Generate standard project structure

The command apikit project <dest.dir> <path/of/package> generates a standard project directory.

cd go/src
$GOPATH/bin/apikit project myproject myproject

The project command takes the name of the directory to create and the path of the main package as arguments It creates a CLI stub in the cmd subdirectory and a .gitignore file.

Note that it is not necessary to use the standard project structure with the APIKit.

Define the API with OpenAPIv2

The next step is to define your API. It can be useful to use a Swagger editor for this task. By convention the Swagger definition is stored in the doc subdirectory.

For showcasing the following example definition will be used:

---
swagger: "2.0"
info:
  title: "vis-admin"
  version: "1.0.0"
consumes:
- "application/json"
produces:
- "application/json"
paths:
  /api/client/{clientId}:
    put:
      summary: "Create or update client"
      operationId: "CreateOrUpdateClient"
      consumes: []
      parameters:
      - name: "X-Auth"
        in: "header"
        required: true
        type: "string"
        description: "Authentication token"
      - name: "clientId"
        in: "path"
        required: true
        type: "string"
        description: "Client ID"
      - name: "body"
        in: "body"
        required: true
        schema:
          $ref: "#/definitions/Client"
      responses:
        200:
          description: "Updated"
          schema:
            $ref: "#/definitions/Client"
        201:
          description: "Created"
          schema:
            $ref: "#/definitions/Client"
        400:
          description: "Malformed request body"
        403:
          description: "Not authenticated"
        405:
          description: "Not allowed"
definitions:
  Client:
    type: "object"
    required:
    - "id"
    - "name"
    properties:
      id:
        type: "string"
      name:
        type: "string"
      activePresets:
        type: "string"

Validate the OpenAPIv2 definition

The command apikit validate <api.yaml> validates against the given OpenAPIv2 / Swagger definition.

cd myproject
$GOPATH/bin/apikit validate doc/myproject.yaml

Generate API server and client

The apikit generate <api.yaml> <dest.dir> <package> command generates the client and server API based on an OpenAPIv2 definition. Use --only-client if the server component and --only-server if the client component is not needed.

$GOPATH/bin/apikit generate doc/myproject.yaml api api

Note that all endpoints need to have an operation ID to generate successfully. The generated code should not be edited manually. Instead, the OpenAPI definition should be updated and the source regenerated with APIKit generate command.

Using the API client

The client.go file contains an interface defining the programming interface of the API.

type VisAdminClient interface {
  CreateOrUpdateClient(request *CreateOrUpdateClientRequest) (CreateOrUpdateClientResponse, error)
}

The request parameter contains all data that is sent to the server with the API call. Every API call returns a response interface that can be casted to the actual, HTTP return code specific struct, and an error code if the communication with the server went wrong. The content of the response is only valid if the error return value is nil.

The client.go file also contains an implementation of the programming interface using HTTP calls to the actual API. There is a constructor for the client implementation which takes an http.Client and the API base URL as parameters. Via the http.Client network handling and additional http.RoundTripper can be configured and integrated with the API client.

The steps for using the client to make an API call are:

  • create the client implementation via constructor
  • fill request struct with appropriate data
  • call the API via the function for the endpoint
  • check error return value
  • check HTTP status code of the response
  • cast response to correct struct

This is illustrated in the following example:

package myproject_test

import (
  "myproject/api"
  "net/http"
  "testing"
)

const (
  baseUrl      = "http://api.myproject.com/"
  testClientId = "clientId"
  testApiKey   = "apiKey"
  testName     = "name"
)

func TestClient(t *testing.T) {

  // create instance of API client
  client := api.NewVisAdminClient(&http.Client{}, baseUrl, api.Opts{})

  // create request struct
  request := api.CreateOrUpdateClientRequest{
    ClientId: testClientId,
    XAuth:    testApiKey,
    Body: api.Client{
      Id:   testClientId,
      Name: testName,
    },
  }

  // call API with request
  response, err := client.CreateOrUpdateClient(&request)
  if err != nil {
    t.Fatal(err)
  }

  // check HTTP return code
  if response.StatusCode() != http.StatusOK {
    t.Fatalf("API returned error code %d", response.StatusCode())
  }

  // cast response appropriatly and use returned information
  t.Log(response.(*api.CreateOrUpdateClient200Response).Body.Name)
}

Note that for testing the API can be mocked by a local implementation of the API client programming interface.

Using the API server

The file server.go contains an a full HTTP server that serves the specified API. Additional to the defined endpoints it contains the /spec endpoint that delivers the OpenAPIv2 / Swagger definition the server was generated with. The /spec endpoint can be used to visualize the API via UIs like Swagger UI.

The implementation of the API endpoints has to be done in handler functions that take the request data as parameter and return an implementation of the endpoint-specific response interface. The handler functions need to be registered before starting the server. If there is no handler registered for an endpoint, the server will respond with status code 404 as default.

The steps for using the API server are:

  • create the server via constructor
  • register endpoint handlers
  • start listening on network socket

The following example shows how the server is initialized and than called by the generated client (see above).

package myproject_test

import (
  "context"
  "myproject/api"
  "net/http"
  "testing"
  "time"
)

const (
  baseUrl      = "http://localhost:8080"
  testClientId = "clientId"
  testApiKey   = "apiKey"
  testName     = "name"
)

func CreateOrUpdateClient(ctx context.Context, request *api.CreateOrUpdateClientRequest) api.CreateOrUpdateClientResponse {

  return &api.CreateOrUpdateClient200Response{
    Body: request.Body,
  }
}

func TestServer(t *testing.T) {

  // create server instance
  server := api.NewVisAdminServer(nil)

  // register endpoint handler
  server.SetCreateOrUpdateClientHandler(CreateOrUpdateClient)

  // start server to listen for requests
  go func() {
    t.Log(server.Start(8080))
  }()
  time.Sleep(1 * time.Second)

  // create instance of API client
  client := api.NewVisAdminClient(&http.Client{}, baseUrl, api.Opts{})

  // create request struct
  request := api.CreateOrUpdateClientRequest{
    ClientId: testClientId,
    XAuth:    testApiKey,
    Body: api.Client{
      Id:   testClientId,
      Name: testName,
    },
  }

  // call API with request
  response, err := client.CreateOrUpdateClient(&request)
  if err != nil {
    t.Fatal(err)
  }

  // check HTTP return code
  if response.StatusCode() != http.StatusOK {
    t.Fatalf("API returned error code %d", response.StatusCode())
  }

  // cast response appropriate and use returned information
  t.Log(response.(*api.CreateOrUpdateClient200Response).Body.Name)

  // stop server
  server.Stop()
}

Generate handler stubs

For one-time generation of stubs for the endpoint handlers the command apikit handlers <api.yaml> <dest.go> <package> <api/package/path> can be used. Especially for large APIs it saves some typing work by writing out the boilerplate code for the handlers.

$GOPATH/bin/apikit handlers doc/myproject.yaml handlers.go myproject myproject/api

Generate service stubs

For larger projects grouping the endpoint handlers in service classes is convenient. A service stub can be generated with apikit service <api.yaml> <dest.go> <package> <tag> <api/package/path>. The command will generate the endpoints that are tagged with tag only.

$GOPATH/bin/apikit service doc/myproject.yaml client_service.go myproject client myproject/api

Validation of request data

The generated server does validate the request against the constraints defined in the OpenAPIv2 specification. If the validation fails, the server will respond with a 400 Bad Request status code to the client.

Passing information about invalid data to the client

To pass more information about the invalid data to the client, the 400 Bad Request response with the body type ValidationErrors has to be added to the endpoint. The generated server will automatically use it to send details about malformed data to the client.

# ... endpoint definition ...
      responses:
        400:
          description: "Bad request"
          schema:
            $ref: "#/definitions/ValidationErrors"

definitions:
  ValidationErrors:
    type: "object"
    properties:
      Message:
        type: "string"
      Errors:
        type: "array"
        items:
          $ref: "#/definitions/ValidationError"

  ValidationError:
    type: "object"
    properties:
      Message:
        type: "string"
      Field:
        type: "string"
      Code:
        type: "string"

Required and non-required fields

The generated types do reflect if a field is required or not by making not required fields pointers. If a non-required field is not present in the request data or a field is present, but has the JSON value null, the pointer will be set to nil. Otherwise the pointer will point to the actual data. Required fields are not allowed to be not present or to be null. If they are, a 400 Bad Request response is returned to the client.

The proper handling of required and non-required fields allows to correctly distinguish between zero values ("", 0, false) and non-present values. Note that the default status for fields in OpenAPIv2 is non-required. To avoid nil pointer checks mark as many fields required as appropriate.

String validation

The string validation supports the minLength, maxLength and the pattern attributes. pattern allows to specify a regular expression that the string has to match. If the string has the format uuid, url or email, it is automatically matched against the corresponding regular expression.

Integer validation

The integer validation supports the minimum, maximum, exclusiveMinimum and exclusiveMaximum attributes.

Content types

The client needs to send the correct content type header matching the consumes attribute in the OpenAPIv2 definition. If not, the server responds with a 415 Unsupported media type error.

Enum support

The APIKit generator has limited enum support. It is required that every enum definition occurs only once in the whole OpenAPIv2 specification. The best way to achieve this is to reference enum types where they are used and have a global definition of the enum type in the definitions section of the specification.

 Car:
    type: object
    required:
      - driveConcept
    properties:
      driveConcept:
        $ref: '#/definitions/DriveConcept'
DriveConcept:
    type: string
    enum:
      - COMBUSTOR
      - HYBRID
      - ELECTRIC
      - FUELCELL
      - UNDEFINED

This produces the following code in types.go:

type DriveConcept string

const (
  DriveConceptCOMBUSTOR DriveConcept = "COMBUSTOR"
  DriveConceptHYBRID    DriveConcept = "HYBRID"
  DriveConceptELECTRIC  DriveConcept = "ELECTRIC"
  DriveConceptFUELCELL  DriveConcept = "FUELCELL"
  DriveConceptUNDEFINED DriveConcept = "UNDEFINED"
)
type (
  Car struct {
    DriveConcept         DriveConcept         `json:"driveConcept" bson:"driveConcept"`
  }
)

Advanced features

Error logging

An error logger can be passed to the server via the ErrorHandler attribute of the ServerOpts struct. The logger will be called when something unexpected goes wrong inside the HTTP layer.

Additional routes for the server

The ServerOpts struct can be used to pass a function to the generated server that is executed during server startup and has access to the internal router object. It is defined as func(router *routing.Router). With this function routes that are not defined in the OpenAPIv2 specification or are implemented by packages that come with an own HTTP handler can be added to the server.

import(
    ...
    "github.com/go-ozzo/ozzo-routing"
)

func NewServer() {

  onStart := func(router *routing.Router) {
    router.Any("/metrics", func(ctx *routing.Context) error {
      metrics.ServeHTTP(ctx.Response, ctx.Request)
      return nil
    })
  }

  server := api.NewVisAdminServer(&api.ServerOpts{OnStart: onStart})

Middleware components

Functions that shall be executed every time an endpoint is called can be added to the server and to individual handlers via middleware components. A middleware is defined by a struct that holds the handler function (defined in ozzo-routing) and a flag, if the middleware shall be executed before or after the endpoint handler.

Middleware struct {
  Handler routing.Handler
  After   bool
}

Server-wide middleware components can be passed via the ServerOpts struct.

middleware := []api.Middleware{{Handler: middleware.RequestID().Handler}}
server := api.NewVisAdminServer(&api.ServerOpts{Middleware: middleware})

Handler-specific middleware can be added via a var-arg list at handler registration.

sessionMiddleware := xcustomer.Middleware{Handler: middleware.SessionHandler(s.sessions)}
server.SetCreateOrUpdateClientHandler(CreateOrUpdateClient, sessionMiddleware)

Middleware can use c.Request.Context() object to pass data to the handler function. For example the session handler can check for a valid session token and load session data into the context object of the handler if successful.

func SessionHandler(service session.Service) routing.Handler {

  return func(c *routing.Context) error {

    authToken := c.Request.Header.Get(XAuthTokenHeader)
    if len(authToken) == 0 {
      return xcustomer.NewHTTPStatusCodeError(http.StatusBadRequest)
    }

    sess, err := service.GetSession(authToken)
    if err != nil {
      if err.StatusCode == http.StatusInternalServerError {
        return xcustomer.NewHTTPStatusCodeError(http.StatusInternalServerError)
      }
      return xcustomer.NewHTTPStatusCodeError(http.StatusUnauthorized)
    }

    if sess == nil {
      return xcustomer.NewHTTPStatusCodeError(http.StatusUnauthorized)
    }

        // add session data to the context of the endpoint handler
    ctx := context.WithValue(c.Request.Context(), xcontext.SessionKey, sess)
    c.Request = c.Request.WithContext(ctx)
    return c.Next()
  }
}

Server-side request and response logging

The APIKit middleware package provides a component for server-side request and response logging. The middleware records request and response and forwards it to a user-defined log function before sending the data to the client. LogResponseWriter is part of the APIKit middleware package.

rrLogger := func(r *http.Request, w *LogResponseWriter, elapsed time.Duration) {
    // ...  print request and response infos as suitable
}
middleware := []api.Middleware{{Handler: middleware.Log(rrLogger)}}

There is also a convenience wrapper for the log function.

timeFormat := time.RFC3339
pathsToIgnore := []string{...} // endpoints not to log
logger := logFunc func(entity middleware.LogEntry, values ...interface{}) {
    // use entity object to print log
}
rrLogger := middleware.NewLogger(timeFormat, pathsToIgnore, logger)

GDPR compliant request and response logging

In order to comply with the GDPR no data that could identify a person must be stored in log files. Therefore, a middleware logger is provided that can mask specified fields in JSON request and response bodies.

fieldsToMask := []string{...} // list of JSON paths
typesToMask := []reflect.Type{...} // list of types
rrLogger := middleware.NewMaskingLogger(timeFormat, fieldsToMask, typesToMask, pathsToIgnore, logger)

Client-side request and response logging

The APIKit roundtripper package contains components for client-side request and response logging. The simplest roundtripper forwards the HTTP request and response to a log function. The roundtripper.Use() function wraps the transport of an HTTP client with the given RoundTripper.

logFunc := func(req *http.Request, resp *http.Response) {
    // ... log request and response content ...
}
client := roundtripper.Use(&http.Client{}, roundtripper.Logger(logFunc))

Additionally there is a convenience roundtripper that does an httputil.Dump..() on request and response and forwards the result a generic logging function.

logger := func(a ...interface{}) {
  // log a[0]
}

client := roundtripper.Use(&http.Client{}, roundtripper.Dump(logger))

The logging function is defined as an interface var-arg list so that it's possible to use standard functions of logging frameworks like logrus. The roundtripper does always call it with one string parameter.

Up- and downloading files as streams

Up- and downloading binary data in JSON format requires to put whole files in memory while marshalling / unmarshalling the JSON. This can quickly overwhelm the server. A better approach is to handle files as streams. The APIKit supports this via the type: file attribute.

When uploading a file the content type multipart/form-data (consumes attribute) is required.

  /upload:
    post:
      summary: Upload a file with others data
      consumes:
      - multipart/form-data
      operationId: PostUpload
      parameters:
      - in: formData
        name: upfile
        type: file
        description: the file to upload
      - in: formData
        name: note
        type: string
        maxLength: 4000
        pattern: "^[0-9a-zA-Z ]*$"
        description: Description of file
      responses:
        '200':
          description: Status 200
        '500':
          description: Status 500

The request struct that is passed to the endpoint handler now contains a FormData object that includes an io.ReadCloser to access the file content. Note that the io.ReadCloser needs to be closed by the handler to prevent memory leaks.

func PostUpload(ctx context.Context, request *PostUploadRequest) PostUploadResponse {

  defer request.FormData.Upfile.Content.Close()

  data, err := ioutil.ReadAll(request.FormData.Upfile.Content)
  if err != nil {
    log.Println(fmt.Sprintf("error reading uploaded file (%v)", err))
    return new(PostUpload500Response)
  }

    // .. do something with data
  return new(PostUpload200Response)
}

To deliver a file as stream to the client, the response body must have the type: file. In the example below the Content-Type header specified explicitly to overwrite the Content-Type generated by the produces attribute.

  '/download/{image}':
    get:
      produces:
      - image/png
      summary: Retrieve a image
      description: Retrieve a image
      operationId: DownloadImage
      parameters:
      - in: path
        name: image
        description: The image name of the image
        type: string
        required: true
      responses:
        '200':
          description: image to download
          schema:
            type: file
          headers:
            Content-Type:
              type: "string"
        '500':
          description: Internal server error

The handle than has to pass an io.ReadCloser with the response. The open stream is closed in the HTTP layer of the generated server.

func DownloadImage(ctx context.Context, request *DownloadImageRequest) DownloadImageResponse {

    file, err := os.Open(request.Name)
    if err != nil {
        return &DownloadImage500Response{}
    }

  return &DownloadImage200Response{Body: file, ContentType: "image/png"}
}

APIKit development notes

If you have found a bug or would like contributed to the project please check out our Contribution Guidelines.

After making changes to the APIKit source do run the testsuite via the Makefile.

make test

When there were changes to the internal/framework package, update the framework files before committing and building the executable.

make framework

When debugging code generation consider enabling the debug mode of the generate command. When activated the generator will save the generated code regardless of errors into a temporary file and it print its location to the terminal.

Issues
  • Replace custom mock generator with mockery

    Replace custom mock generator with mockery

    The custom-made mock generator is not really satisfying the real requirements of the mock concept therefore I think it will be better to replace the custom mock generator with mockery. I began to deeply integrate the mockery cmd into the Apikit.

    @seseloos let me know what do you think about this early draft. In the case you willing to accept this fundamental change then I will finalize the feature.

    Mockery ref: https://github.com/vektra/mockery autogenerated mock ref: https://github.com/ExperienceOne/apikit/blob/89938c251d6135449e625c5c09f50f05985f3aaf/tests/api/mock_VisAdminClient.go

    opened by donutloop 9
  • Validation of minItems/maxItems array query parameter options

    Validation of minItems/maxItems array query parameter options

    I am using the minItems and maxItems options for an array query parameter. The request validation does not automatically respond with a 400 Bad Request as I would expect when sending a request with less or more values as defined by the options.

    Example request:

    • /pet/findByTags?tags=test1 (less than minItems)
    • /pet/findByTags?tags=test1,test2,test3,test4,test5,test6 (more than maxItems)

    Version Info

    • GitCommit: 24ae678b1ec596a7e3d22909c962a9de295c8665
    • GitBranch: master
    • GitTag: v1.0.0

    OpenAPIv2 definition

    swagger: '2.0'
    info:
      version: 1.0.0
      title: Test
    host:  localhost:8080
    tags:
      - name: pet
    schemes:
      - http
    paths:
      /pet/findByTags:
        get:
          tags:
            - pet
          summary: Finds Pets by tags
          description: 'Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.'
          operationId: findPetsByTags
          produces:
            - application/json
          parameters:
            - name: tags
              in: query
              description: Tags to filter by
              required: true
              type: array
              minItems: 2
              maxItems: 5
              items:
                type: string
              collectionFormat: csv
          responses:
            '200':
              description: successful operation
              schema:
                type: string
            '400':
              description: Invalid tag value
    

    Expected behaviour

    Server request validation automatically rejects the request and responds with 400 Bad Request.

    enhancement 
    opened by oloose 7
  • Proposal: A dedicated section for security bugs in contribution guideline

    Proposal: A dedicated section for security bugs in contribution guideline

    In my point of view! It might be dangerous to expose any security issues on Github in any form. It will be better if you clarify such problems over email.

    Doc example:

    I have found a security bug!

    Please contact Sebastian Loose via email ([email protected])

    Sebastian needs:

    • Description of the security issue
    • Attack vectors
    • Fix

    What do you think?

    documentation 
    opened by donutloop 7
  • Roundtripper request id

    Roundtripper request id

    To inter connect the whole request graph it is nessacary to set a request id for each outgoing request.

    Changes

    • Add request id roundtripper
    • Add test cases for request id roundtripper
    opened by donutloop 4
  • Add generation of min items and max items validator constraints

    Add generation of min items and max items validator constraints

    Changes

    • Add generation of min items and max items validator constraints
    • Add array query parameters validation documentation
    • Add min Items, max Items, and sufficient items integration test cases
    opened by donutloop 4
  • Use defer to close http response body in auto generated client code

    Use defer to close http response body in auto generated client code

    Less Code Less Complexity Less time to worry

    Replaced allresponse.Body.Close calls inside of each Client handler with a deferred response.body.Close. The autogenerated code is less complex and the client generator is better adaptable in case of adding new response cases or adapting the current set of response cases. Reduces the likelihood of introducing a memory leak to an optiminun

    opened by donutloop 4
  • ACG: Decompose client interface

    ACG: Decompose client interface

    • Decompose client interface into smaller interfaces, fewer methods need to be satisfied.
    • Can be used to make code more lean and clean, reader knows exactly which method are needed from the client.
    • Allows fine granular definition of new interface types
    opened by donutloop 3
  • accept uuid V1 - V5

    accept uuid V1 - V5

    Allows validation of UUIDs other than Version4.

    If the restriction to v4 is deliberate please let me know, so we'll use strings with our own validation

    Thanks!

    opened by zgiber 3
  • Change error messages and error types

    Change error messages and error types

    Changes

    • Improves error assertions and error equal checks
    • Add basic golint linter configuration and enable only err113 by default
    • Upgrade to golang 1.13 (Major break)
    • Regenerate example and framework code
    opened by donutloop 3
  • Generate else block only for required parameters

    Generate else block only for required parameters

    The previous server generator implementation is not causing a bug it just generates an unused else block

    Changes

    • Optimized performance of auto-generated code
    • Remove unused else blocks for optional parameters
    opened by donutloop 3
  • AGC: Query default values

    AGC: Query default values

    Iterate over each URL query parameter if the parameter query default value is set to a valid value then generate value default setter inside of a server handler

    Example use case: Do not allow requesting all entries with one call by default when the default value property is set for a URL query parameter in the spec.

    Kind of a major break!!!

    if you regenerate code and it contains those queries default parameters then the behavior might be different for your application.

    opened by donutloop 2
  • Types generator use constants for hardcoded empty strings

    Types generator use constants for hardcoded empty strings

    Replace empty string "" within generator/types_generator.go with constants that have proper names to improve the readability and understanding of the code.

    See the following lines of generator/types_generator.go as an example.

    https://github.com/ExperienceOne/apikit/blob/8d8fa95b59b78dc09066b3bc84e2bce52ca12c9f/generator/types_generator.go#L317-L321

    Also see the suggestion of @donutloop in pull request #5 for further information.

    enhancement 
    opened by seseloos 0
Releases(v1.0.0)
Owner
Experience One
Experience One
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

null 303 May 30, 2021
Public interface definitions of 1C Enterprise

proto Репозиторий содержит файлы для Protobuf (контрактов и описание сервисов) для автоматической генерации классов/структур под языки программировани

null 9 Jul 16, 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

Hamza Oral 9 Jun 14, 2022
generates avatars based on a user's name

Gradient Avatar Service - GAS Gradient Avatar Service is a service that generates avatars based on a user's name. GAS is inspired by Vercel's user ava

Muhammed Nazeem 0 Jan 16, 2022
Composable OpenAPI Specification (aka Swagger)

compoas Library for building, composing and serving OpenAPI Specification (aka Swagger). Features This lib provides: golang structs which reflect Open

Graaphs 12 Jun 1, 2022
This tool generates Go language bindings of services in protobuf definition files for go-kit

protoc-gen-go-kit This tool generates Go language bindings of services in protobuf definition files for go-kit. Installation $ go install github.com/x

X64FUN 1 Nov 9, 2021
Nano - Lightweight, facility, high performance golang based game server framework

Nano Nano is an easy to use, fast, lightweight game server networking library fo

Lonng 2.1k Aug 4, 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

Discord Gophers 45 Jul 28, 2022
A microservice gateway developed based on golang.With a variety of plug-ins which can be expanded by itself, plug and play. what's more,it can quickly help enterprises manage API services and improve the stability and security of API services.

Goku API gateway is a microservice gateway developed based on golang. It can achieve the purposes of high-performance HTTP API forwarding, multi tenant management, API access control, etc. it has a powerful custom plug-in system, which can be expanded by itself, and can quickly help enterprises manage API services and improve the stability and security of API services.

Eolink 233 Aug 4, 2022
Microservice Boilerplate for Golang with gRPC and RESTful API. Multiple database and client supported

Go Microservice Starter A boilerplate for flexible Go microservice. Table of contents Features Installation Todo List Folder Structures Features: Mult

Ahmad Saugi 14 Jul 28, 2022
Golang client for Ethereum and Flashbots JSON-RPC API calls.

Flashbots RPC client Fork of ethrpc with additional Flashbots RPC methods: FlashbotsGetUserStats FlashbotsCallBundle FlashbotsSendBundle FlashbotsSimu

Chris Hager 79 Aug 3, 2022
Rpcx-framework - An RPC microservices framework based on rpcx, simple and easy to use, ultra fast and efficient, powerful, service discovery, service governance, service layering, version control, routing label registration.

RPCX Framework An RPC microservices framework based on rpcx. Features: simple and easy to use, ultra fast and efficient, powerful, service discovery,

ZYallers 1 Jan 5, 2022
Design-based APIs and microservices in Go

Goa is a framework for building micro-services and APIs in Go using a unique design-first approach. Overview Goa takes a different approach to buildin

Goa 4.8k Aug 7, 2022
Concourse is a container-based continuous thing-doer written in Go and Elm.

Concourse: the continuous thing-doer. Concourse is an automation system written in Go. It is most commonly used for CI/CD, and is built to scale to an

Concourse 6.5k Aug 8, 2022
🦄🌈 YoyoGo is a simple, light and fast , dependency injection based micro-service framework written in Go.

???? YoyoGo is a simple, light and fast , dependency injection based micro-service framework written in Go. Support Nacos ,Consoul ,Etcd ,Eureka ,kubernetes.

YoyoFx 549 Aug 6, 2022
Appsearch - AppSearch Client for ElasticAppsearch

AppSearch Client for ElasticAppsearch Require Apikey Host init config func main(

Rohmat mret 0 Feb 17, 2022
This project implements p11-kit RPC server protocol, allowing Go programs to act as a PKCS #11 module without the need for cgo

PKCS #11 modules in Go without cgo This project implements p11-kit RPC server protocol, allowing Go programs to act as a PKCS #11 module without the n

Google 42 Jun 28, 2022
NewSQL distributed storage database based on micro service framework

QLite 是基于微服务的 NewSQL 型数据库系统,与传统的一体化数据库不同,该系统将本该内置的多种数据结构(STL)拆分成多个服务模块,每个模块都是独立的一个节点,每个节点都与其主网关进行连接,从而形成分布式存储结构。

null 36 Jun 19, 2022
Application tracing system for Go, based on Google's Dapper.

appdash (view on Sourcegraph) Appdash is an application tracing system for Go, based on Google's Dapper and Twitter's Zipkin. Appdash allows you to tr

Sourcegraph 1.7k Jul 27, 2022