Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add swagger support #68

Merged
merged 18 commits into from
Jan 28, 2016
Merged

Add swagger support #68

merged 18 commits into from
Jan 28, 2016

Conversation

achew22
Copy link
Collaborator

@achew22 achew22 commented Dec 2, 2015

Yuki,

I started to create a grpc-gateway swagger client which generates a .swagger.json file for every proto that you load in. This is what I have right now. It is broken into two commits. The first clones protoc-gen-grpc-gateway into protoc-gen-swagger and the 2nd modifies it to emit a really terrible swagger definition.

Right now it has a number of shortcomings.

  1. It doesn't take parameters in requests
  2. It generates both a post and a get (and no other verbs)
  3. It's super hacky
  4. I have no idea what I'm doing
  5. Doesn't load any comment information into the swagger spec which would make it MUCH easier to understand the output

I was wondering if you could provide some general feedback. This is the first thing of any size I've ever done in go so sorry if it isn't idiomatic. I'm seeking comments on places that you think could be improved but please do the delta from the 2nd commit on or it will be very painful to review. "This looks like it's on the right track" or "try again with this strategy" is ultimately what I would like to get from you.

Thanks so much for creating this project! It is making my life so much less painful.

@yugui
Copy link
Member

yugui commented Dec 2, 2015

Amazing!

I'm afraid, but it takes a bit long to take a look at this PR since it is large.
Maybe I have some time to do that this weekend.

@yugui
Copy link
Member

yugui commented Dec 6, 2015

@achew22
Thank you. I really like the overall direction, e.g.

  1. Map proto message to predefined message schema
  2. Construct Swagger definition in process and marshal it in JSON afterward.

There are some comments.

  1. You don't have to copy entire the protoc plugin. Code generator part of protoc-gen-grpc-gateway is pluggable by intention. So you can reuse the existing message/option parser. Feel free to propose some extension of the parser if is functionality is not sufficient for your purpose.
  2. I'm not sure, but sometimes it might be better to define parameters of paths with parameterObject rather than referenceObject because it is allowed to place some fields in request paths.

@achew22
Copy link
Collaborator Author

achew22 commented Dec 14, 2015

I have been on vacation for the past week. I intend to start taking a look at this in my spare time over this week.

@yugui
Copy link
Member

yugui commented Dec 14, 2015

👍

@achew22
Copy link
Collaborator Author

achew22 commented Dec 20, 2015

@yugui, I have done a bit of cleanup on this PR. Just for reference, once you're happy with it I would like to squash it into a single commit, so don't just hit the merge button 😄.

I think your suggestion about using a parameter object is a great one. I looked at the docs and agreed with you when I was writing but I couldn't find a compelling way to do union types in Golang. Do you know what the best way to do a union type is? That seems to me like the only way to do it unfortunately.

I have updated the branch with changes to make it reuse the existing protoc-gen-grpc-gateway instead of my clone. Turns out almost all the stuff I wanted was there.

import (
"errors"
"fmt"
// Don't use the formatter
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you just remove this if you don't need "go/format"?

@yugui
Copy link
Member

yugui commented Dec 24, 2015

https://travis-ci.org/gengo/grpc-gateway/builds/97933023

The test is broken because master branch was broken.
Maybe you just need to rebase onto the current master to fix the test.

@achew22
Copy link
Collaborator Author

achew22 commented Dec 27, 2015

The thing I'm stuck on right now is that you can import arbitrary protos into your api. They don't necessarily have to be included in the file that you're currently compiling. My plan thus far had been to use "#/definitions/{{message.FQMN()}}" for all the definitions. This is great, except when it comes to iterating over all the messages, I get stuck because they may not be in the file.

Right now I'm expecting that I will have to create a registry of messages, like you did, then recurse through all the fields creating a set of messages that have been seen. I was planning on using a hashmap from FQMN to the actual message object then in the stage where I generate the definitions I can just emit each entry as a definition. Looking at the go code it solves this by importing 1 layer deep and then using the protoc-go library's output to solve the problem of transitive dependence, but you might have a cool trick up your sleeve so I thought I would ask.

@achew22
Copy link
Collaborator Author

achew22 commented Dec 28, 2015

Now I remember why this was hard! Field [https://godoc.org/github.com/gengo/grpc-gateway/protoc-gen-grpc-gateway/descriptor#Field] has a message attached, but it isn't the message I would expect. It is the message of it's parent. This is, no doubt, useful but not in the context that I need it. Lemme go dig in to see if I can figure out how to add a FieldMessage field to the Field struct. Meta-programming is hard!

@achew22
Copy link
Collaborator Author

achew22 commented Dec 28, 2015

After a bit of playing, I just plumbed the registry through to the generator and now I'm able to resolve these. Thanks for writing that!

@achew22
Copy link
Collaborator Author

achew22 commented Dec 28, 2015

Sorry, I accidentally closed this by pushing your master to github. It's all fixed now.

I think this is getting a lot closer. I have created a non-streaming example file which is the a bit of everything with the word streaming removed https://raw.githubusercontent.com/achew22/grpc-gateway/master/examples/examplepb/streamless_everything.swagger.json

If you want to see how their API viewer sees it, check out http://petstore.swagger.io/#/ and type that URL in at the top. If you want to see what linter checks it is failing you can go to https://editor.swagger.io and do the same thing.

Things that still need to be done:

  • EmptyProto is still an interesting edge case. Right now it is not being included in output and I haven't figured out why.
  • Even if empty proto is fixed in the swagger codegen to emit an empty dictionary, their editor will still barf on it Using empty schema object does not work anymore OAI/OpenAPI-Specification#452
  • Repeated fields need to be marked as arrays
  • Theoretical support for enums -- I couldn't get enums to be loaded in the params object. What I have should handle them properly.
  • Parameters should not all be typed as "String". They have type information and we should represent that.
  • More tests

@achew22 achew22 reopened this Dec 28, 2015
@yugui
Copy link
Member

yugui commented Dec 28, 2015

I see. I'm looking forward to seeing it.

My intent is to turn protoc-gen-swagger into a swagger JSON generating
protoc plugin.
Previously I had forked the protoc-gen-grpc-gateway folder because I
wasn't sure how many changes I was going to have to make to it. Since
there weren't very many changes required. I have patched it to add the
fields I required and moved gen-swagger to use gen-grpc.
This also adds an error condition that I hadn't previously considered.
If there is a streaming API swagger doesn't currently support it. I
handle that now with an error.
Also does a major refactor. This changes the way that Messages are
discovered and breaks the generation step down from a monoloithic task
into a much easier to test set. Also parses paths and adjusts them so
that they match what swagger expects.
Swagger uses the operationId as the "nickname" for the method generated
for your service.
The tag is used to define the class name in code generation out of
Swagger.
@yugui
Copy link
Member

yugui commented Jan 19, 2016

@achew22
I want to hear your opinion about https://github.com/gengo/grpc-gateway/pull/68/files#r50193073.
Besides the comment and other small coding-level issues, I like the overall direction.

@achew22 achew22 changed the title Add non-functional swagger support Add swagger support Jan 21, 2016
@achew22
Copy link
Collaborator Author

achew22 commented Jan 25, 2016

PTAL

output := fmt.Sprintf("%s.swagger.json", base)
files = append(files, &plugin.CodeGeneratorResponse_File{
Name: proto.String(output),
Content: proto.String(string(formatted.Bytes())),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use bytes.Buffer.String() to avoid unnecessary copy.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you

@yugui
Copy link
Member

yugui commented Jan 26, 2016

The design looks good to me.
I'll add some coding-level comments.


// We now have rendered the entire swagger object. Write the bytes out to a
// string so it can be written to disk.
w := bytes.NewBuffer(nil)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't have to allocate the buffer in heap.

var w bytes.Buffer
enc := json.NewEncoder(&w)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Saving memory 👍

@achew22
Copy link
Collaborator Author

achew22 commented Jan 28, 2016

Thank you so much for the review. This is my first bout with Golang and I'm happy to have someone reviewing it. I think I have addressed all your concerns and would appreciate if you could take another look at the code.

@yugui
Copy link
Member

yugui commented Jan 28, 2016

LGTM.

Thank you for your excellent work!

yugui added a commit that referenced this pull request Jan 28, 2016
@yugui yugui merged commit a7e1d20 into grpc-ecosystem:master Jan 28, 2016
@achew22 achew22 mentioned this pull request Jan 28, 2016
ithinker1991 pushed a commit to tronprotocol/grpc-gateway that referenced this pull request Jun 22, 2018
…ttransactioninfobyid_api

add transactioninfobyid api
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants