GithubHelp home page GithubHelp logo

elliots / protoc-gen-twirp_swagger Goto Github PK

View Code? Open in Web Editor NEW
62.0 7.0 15.0 722 KB

Swagger generator for twirp

License: Other

Batchfile 0.18% Shell 3.08% C# 15.29% Scala 0.17% Java 18.02% JavaScript 8.27% Lua 0.77% Python 12.58% Ruby 11.03% Go 25.48% Rust 5.13%
swagger twirp grpc protobuf

protoc-gen-twirp_swagger's Introduction

Twirp Swagger Generator

NOTE: This is new and barely tested. If you find problems, please open an issue :)

Also Note: None of the clients or servers generated from swagger support protobuf. Only json.

Table of Contents

What is this?

A plugin for the awesome twirp - https://github.com/twitchtv/twirp

It is a protobuf generator that creates a swagger file for your twirp services.

This swagger file can then be used to generate documentation and clients for many many languages.

Usage

go get github.com/elliots/protoc-gen-twirp_swagger

then run as part of your usual protoc generation phase

protoc --go_out=. \
       --twirp_out=. \
       --twirp_swagger_out=. \
       ./test.proto

Other uses

You can import the swagger file into a lot of other tools and services.

If you find any good ones, add an issue so we can list them here.

Full Example

Proto file taken from the twirp example. All scripts/clients/docs are in example

Generating the swagger file

./generate-swagger.sh will create service.swagger.json

Output

{
  "swagger": "2.0",
  "info": {
    "title": "service.proto",
    "version": "version not set"
  },
  "schemes": [
    "http",
    "https"
  ],
  "consumes": [
    "application/json"
  ],
  "produces": [
    "application/json"
  ],
  "paths": {
    "/twirp/twitch.twirp.example.Haberdasher/MakeHat": {
      "post": {
        "summary": "MakeHat produces a hat of mysterious, randomly-selected color!",
        "operationId": "MakeHat",
        "responses": {
          "200": {
            "description": "",
            "schema": {
              "$ref": "#/definitions/exampleHat"
            }
          }
        },
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/exampleSize"
            }
          }
        ],
        "tags": [
          "Haberdasher"
        ]
      }
    }
  },
  "definitions": {
    "exampleHat": {
      "type": "object",
      "properties": {
        "size": {
          "type": "integer",
          "format": "int32",
          "description": "The size of a hat should always be in inches."
        },
        "color": {
          "type": "string",
          "description": "The color of a hat will never be 'invisible', but other than\nthat, anything is fair game."
        },
        "name": {
          "type": "string",
          "description": "The name of a hat is it's type. Like, 'bowler', or something."
        }
      },
      "description": "A Hat is a piece of headwear made by a Haberdasher."
    },
    "exampleSize": {
      "type": "object",
      "properties": {
        "inches": {
          "type": "integer",
          "format": "int32"
        }
      },
      "description": "Size is passed when requesting a new hat to be made. It's always\nmeasured in inches."
    }
  }
}

Generating Clients

./generate-clients.sh will create clients for C#, go, java, javascript, lua, python, and ruby (many more are available)

Using the Clients

JavaScript

var Serviceproto = require('./javascript');

var devClient = new Serviceproto.ApiClient();
devClient.basePath = 'http://localhost:8080';

var api = new Serviceproto.HaberdasherApi(devClient);

var body = new Serviceproto.ExampleSize(); // {ExampleSize} 
body.inches = 20;

var callback = function(error, data, response) {
  if (error) {
    console.error(error);
  } else {
    console.log('API called successfully. Returned data: ', data);
  }
};
api.makeHat(body, callback);

Python

from __future__ import print_function
import time
import swagger_client
from swagger_client.rest import ApiException
from pprint import pprint
# create an instance of the API class
cfg = swagger_client.Configuration()
cfg.host="http://localhost:8080"
client = swagger_client.ApiClient(cfg)
api_instance = swagger_client.HaberdasherApi(client)
body = swagger_client.ExampleSize() # ExampleSize | 
body.inches = 20

try:
    # MakeHat produces a hat of mysterious, randomly-selected color!
    api_response = api_instance.make_hat(body)
    pprint(api_response)
except ApiException as e:
    print("Exception when calling HaberdasherApi->make_hat: %s\n" % e)

Go

Note: You almost certainly want to use the twirp client, not the swagger one. No protobuf here.

package main

import (
	"context"
	"fmt"

	"github.com/elliots/protoc-gen-twirp_swagger/example/clients/go"
)

func main() {
	cfg := swagger.NewConfiguration()
	cfg.BasePath = "http://localhost:8080"
	client := swagger.NewAPIClient(cfg)

	hat, resp, err := client.HaberdasherApi.MakeHat(context.Background(), swagger.ExampleSize{
		Inches: 20,
	})
	if err != nil {
		panic(err)
	}

	fmt.Printf("Got response code: %d hat: %v", resp.StatusCode, hat)
}

Generating documentation

./generate-documentation.sh

Spectacle

swagger-codegen (html2 language)

Generating servers

./generate-documentation.sh

Generates servers for rust and node.js.

See example/servers

Thanks

Based on: https://github.com/grpc-ecosystem/grpc-gateway/tree/master/protoc-gen-swagger (Like, 99.5% based on.)

Table of contents created by gh-md-toc

protoc-gen-twirp_swagger's People

Contributors

alexplevako avatar elliots avatar marwan-at-work avatar ryogak avatar tiramiseb 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

protoc-gen-twirp_swagger's Issues

Upstream breaking change:

	gen "github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/generator"

The package doesn't exist anymore.

ERROR_UNKNOWN

When running the generate clients, I notice the following in the javascript log output.

[main] ERROR io.swagger.codegen.DefaultCodegen - String to be sanitized is null. Default to ERROR_UNKNOWN

There is no useful information before or after in the docker logs.

[main] INFO io.swagger.parser.Swagger20Parser - reading from /work/service.swagger.json
[main] INFO io.swagger.codegen.languages.JavascriptClientCodegen - Using JS ES5 templates
[main] ERROR io.swagger.codegen.DefaultCodegen - String to be sanitized is null. Default to ERROR_UNKNOWN
[main] WARN io.swagger.codegen.DefaultGenerator - 'host' not defined in the spec. Default to 'localhost'.
[main] INFO io.swagger.codegen.AbstractGenerator - writing file /work/clients/javascript/src/model/ExampleHat.js

Can you confirm this is not a problem?

Thanks.

Swift4's Alamofire Implementation is not thread safe

// Create a new manager for each request to customize its request header
managerStore[managerId] = manager

We use our own manager to add some authentication headers and the managerStore will just cause random crashes when using a concurrent background queue.

sigsegv when there is no package

AFAIK, package is not mandatory in the protobuf file.

I want to create a service without a package name, I would end up with URLs like:

/twirp/Service/Method

No problem with twirp, generated Go code is okay... But there is a sigsegv error when I want to generate a swagger file:

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

goroutine 1 [running]:
github.com/elliots/protoc-gen-twirp_swagger/genswagger.applyTemplate(0xc4200ea800, 0xc420103570, 0xd, 0xc42007fc48, 0x1, 0x1)
	/home/sebastien/Code/go/src/github.com/elliots/protoc-gen-twirp_swagger/genswagger/template.go:631 +0x294
github.com/elliots/protoc-gen-twirp_swagger/genswagger.(*generator).Generate(0xc42000e0c8, 0xc42000e0d0, 0x1, 0x1, 0x1, 0xc42000e0d0, 0x0, 0x1, 0x0)
	/home/sebastien/Code/go/src/github.com/elliots/protoc-gen-twirp_swagger/genswagger/generator.go:35 +0x184
main.main()
	/home/sebastien/Code/go/src/github.com/elliots/protoc-gen-twirp_swagger/main.go:84 +0x61a
--twirp_swagger_out: protoc-gen-twirp_swagger: Plugin failed with status code 2.

Line genswagger/template.go:631 is:

if err := renderServices(*p.Package, p.Services, s.Paths, p.reg, refs); err != nil {

Looks like *p.Package is a nil pointer when there is no package...

Chinese notes parsed incorrect

when parsing a .proto file to a swagger.json file, chinese annotations/notes in .proto were parsed incorrect, like this: " //中文注释" were parsed to "\ufffd\ufffd\ufffd\ufffd". how can I resolve this problem.

Is this project still active?

@elliots I'm wondering if this project is still active, as I plan to use it for production purposes. I opened a PR and I also know that Twirp v6 might require this project to be updated as URL paths might be changed, so I plan on also making sure this project is updated. Thank you

How to set description for the generated swagger file

Hi. I can set description for the method by adding gap in its comment like this:

// Foo is foo.
//
// This is description
rpc Foo (FooRequest) returns (FooResponse);

But how I can set description for the whole generated document? Or at least title?

About basepath

Is there a way to specify basepath so that it is set to something else than localhost in the generated swagger file?

google.protobuf.Timestamp incorrectly interpreted as date

Using the swift4 codegen

google.protobuf.Timestamp updated_time = 4;

will incorrectly be interpreted as a date field.

returnedError(Swift.DecodingError.dataCorrupted(Swift.DecodingError.Context(codingPath: ["profiles", _JSONKey(stringValue: "Index 0", intValue: 0), "updated_time"], debugDescription: "Date string does not match format expected by formatter.", underlyingError: nil)))

Swift4's generated use the main queue to process response

It would be nice if it was using the background queue or a configurable queue.

We use AsyncDisplayKit and we do nearly everything in the background.

I had to patch the generated code to specify my queue as an argument to all the validatedRequest's method.

How do you specify optional attributes?

Not sure this is a limitation of Twirp or .proto(3), but how do you convey to consumers that an attribute is optional?

For example what if I wanted to make the inches attribute optional on twitch.twirp.example.Haberdasher/MakeHat? I know I could manually modify the generated swagger.json file, however that diminishes the value of auto-generation.

Incorrect type gen for []int64 (repeated int64), single int64 fields

I get the following output for a type generated in a swagger file:

"userGetMultiRequest": {
  "type": "object",
  "properties": {
    "userIDs": {
      "type": "array",
      "items": {
        "type": "string",
        "format": "int64"
      }
    }
  },
  "title": "GetMulti() rpc request and response"
},

From the proto definition for:

message GetMultiRequest {
        repeated int64 userIDs = 1;
}

It seems single fields (non-repeating) for int64 also get encoded as "string".

Multiple swagger.json files generated

if you split out your protobuf definition into multiple files, so something like:

  • messages.proto
  • services.proto

then a json file will be generated per proto file.

I don't really know swagger at all (yet), but I think it expects a single json file

build failed via `go get`

~ $ go get github.com/elliots/protoc-gen-twirp_swagger
# github.com/elliots/protoc-gen-twirp_swagger/genswagger
go/src/github.com/elliots/protoc-gen-twirp_swagger/genswagger/template.go:534:105: reg.GetUseFQNForSwaggerName undefined (type *"github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/descriptor".Registry has no field or method GetUseFQNForSwaggerName)

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.