Skip to content

Draft: Add openapi v3 #5627

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

Draft
wants to merge 11 commits into
base: main
Choose a base branch
from

Conversation

amirsalarsafaei
Copy link

References to other Issues or PRs

This feature was request in #441.

Have you read the Contributing Guidelines?

Brief description of what is fixed or changed

This is a minimal implementation (as I'm writing this description a draft) for openapiv3 protoc plugin.

Other comments

I plan to add tests and complete other features. I just want to get this look at before I go all in.
Right now it generates OpenAPI spec version 3, using kin-openapi library.

@amirsalarsafaei amirsalarsafaei marked this pull request as draft June 4, 2025 18:30
Copy link
Collaborator

@johanbrandhorst johanbrandhorst left a comment

Choose a reason for hiding this comment

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

Hi, thanks for taking the time to look into this. It's going to be hard for me to review this the way it's currently written. It seems to be based a lot on the existing generator. Could you talk to me about the process you used to build this? I explicitly said that I want us to start from scratch with this generator and not rely on existing code, if we can avoid it. I would remove basically all the flags too and add them piece by piece. Did you use AI to build this?

@amirsalarsafaei
Copy link
Author

Hi,
Thanks for taking a look at it.
I understood that you didn't want the core functionality to be like the existing generator. But I wanted something to get off the ground. So I copied some base stuff. I thought that you didn't want to use the open api generation method from proto. And using the registry was ok. I dont want a full review I exactly wanted to get some pointers before I fully complete the PR. So I will start by keeping the flags I need. And removing dependencies from other parts as much as possible. I used AI in the process but not for code extensively.

@amirsalarsafaei
Copy link
Author

I'm also a little bit unfamiliar with bazel. I will fix the bazel config to not generate the swagger files

@amirsalarsafaei
Copy link
Author

@johanbrandhorst could you please take another look at it? I deleted the borrowed parts and rewrote them.
The generator is missing nested param generation and support for /{param=foo/*}/ path templates.

@amirsalarsafaei
Copy link
Author

I only implemented the flags that we use in our company for V2.

Copy link
Collaborator

@johanbrandhorst johanbrandhorst left a comment

Choose a reason for hiding this comment

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

I haven't looked at the code, but I ran a simple test:

  1. go install ./protoc-gen-openapiv3
  2. Add a new stanza to buf.gen.yaml for the protoc-gen-openapiv3 plugin
  3. Run buf generate

It crashed with a stack overflow, I think you have a broken recursion somewhere. The stack trace is:

runtime: goroutine stack exceeds 1000000000-byte limit
runtime: sp=0x4020c00380 stack=[0x4020c00000, 0x4040c00000]
fatal error: stack overflow

runtime stack:
runtime.throw({0x55bc01?, 0x3b1b8?})
        /usr/local/go/src/runtime/panic.go:1096 +0x38 fp=0x40000ade70 sp=0x40000ade40 pc=0x7ecc8
runtime.newstack()
        /usr/local/go/src/runtime/stack.go:1107 +0x45c fp=0x40000adfb0 sp=0x40000ade70 pc=0x65cbc
runtime.morestack()
        /usr/local/go/src/runtime/asm_arm64.s:342 +0x70 fp=0x40000adfb0 sp=0x40000adfb0 pc=0x83a00

goroutine 1 gp=0x40000021c0 m=4 mp=0x4000098008 [running]:
runtime.mallocgcSmallScanNoHeader(0x20?, 0x474f40?, 0x1?)
        /usr/local/go/src/runtime/malloc.go:1340 +0x344 fp=0x4020c00380 sp=0x4020c00380 pc=0x23a64
runtime.mallocgc(0x20, 0x474f40, 0x1)
        /usr/local/go/src/runtime/malloc.go:1058 +0x88 fp=0x4020c003b0 sp=0x4020c00380 pc=0x7c8b8
runtime.growslice(0x4020c004a8, 0x0?, 0x0?, 0x0?, 0x474f40)
        /usr/local/go/src/runtime/slice.go:272 +0x464 fp=0x4020c00410 sp=0x4020c003b0 pc=0x81314
github.com/grpc-ecosystem/grpc-gateway/v2/internal/descriptor.(*Message).FQMN(0x4000423ef0)
        /home/johan/src/grpc-ecosystem/grpc-gateway/internal/descriptor/types.go:101 +0x70 fp=0x4020c004c0 sp=0x4020c00410 pc=0x2ca150
github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv3/internal/genopenapiv3.(*fileGenerator).generateMessageSchema(0x4040bffd40, 0x4000423ef0, {0x0, 0x0, 0x1?})
        /home/johan/src/grpc-ecosystem/grpc-gateway/protoc-gen-openapiv3/internal/genopenapiv3/file_generator.go:72 +0x38 fp=0x4020c00750 sp=0x4020c004c0 pc=0x3e7928
github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv3/internal/genopenapiv3.(*fileGenerator).generateMessageSchemaRef(0x4040bffd40, 0x4000423ef0)
        /home/johan/src/grpc-ecosystem/grpc-gateway/protoc-gen-openapiv3/internal/genopenapiv3/file_generator.go:66 +0xf4 fp=0x4020c007d0 sp=0x4020c00750 pc=0x3e7824
github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv3/internal/genopenapiv3.(*fileGenerator).generateFieldTypeSchema(0x4040bffd40, 0x400042f200, {0x4010912140, 0x28})
        /home/johan/src/grpc-ecosystem/grpc-gateway/protoc-gen-openapiv3/internal/genopenapiv3/file_generator.go:229 +0x1b4 fp=0x4020c00840 sp=0x4020c007d0 pc=0x3e8944
github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv3/internal/genopenapiv3.(*fileGenerator).generateFieldDoc(0x4040bffd40, 0x40004f0d60)
        /home/johan/src/grpc-ecosystem/grpc-gateway/protoc-gen-openapiv3/internal/genopenapiv3/file_generator.go:203 +0x304 fp=0x4020c008b0 sp=0x4020c00840 pc=0x3e8754
github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv3/internal/genopenapiv3.(*fileGenerator).generateMessageSchema(0x4040bffd40, 0x4000423ef0, {0x0, 0x0, 0x1?})
        /home/johan/src/grpc-ecosystem/grpc-gateway/protoc-gen-openapiv3/internal/genopenapiv3/file_generator.go:88 +0x1d0 fp=0x4020c00b40 sp=0x4020c008b0 pc=0x3e7ac0
github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv3/internal/genopenapiv3.(*fileGenerator).generateMessageSchemaRef(0x4040bffd40, 0x4000423ef0)
        /home/johan/src/grpc-ecosystem/grpc-gateway/protoc-gen-openapiv3/internal/genopenapiv3/file_generator.go:66 +0xf4 fp=0x4020c00bc0 sp=0x4020c00b40 pc=0x3e7824
github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv3/internal/genopenapiv3.(*fileGenerator).generateFieldTypeSchema(0x4040bffd40, 0x400042f200, {0x4010907fc0, 0x28})
        /home/johan/src/grpc-ecosystem/grpc-gateway/protoc-gen-openapiv3/internal/genopenapiv3/file_generator.go:229 +0x1b4 fp=0x4020c00c30 sp=0x4020c00bc0 pc=0x3e8944
github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv3/internal/genopenapiv3.(*fileGenerator).generateFieldDoc(0x4040bffd40, 0x40004f0d60)
        /home/johan/src/grpc-ecosystem/grpc-gateway/protoc-gen-openapiv3/internal/genopenapiv3/file_generator.go:203 +0x304 fp=0x4020c00ca0 sp=0x4020c00c30 pc=0x3e8754
github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv3/internal/genopenapiv3.(*fileGenerator).generateMessageSchema(0x4040bffd40, 0x4000423ef0, {0x0, 0x0, 0x1?})
        /home/johan/src/grpc-ecosystem/grpc-gateway/protoc-gen-openapiv3/internal/genopenapiv3/file_generator.go:88 +0x1d0 fp=0x4020c00f30 sp=0x4020c00ca0 pc=0x3e7ac0
github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv3/internal/genopenapiv3.(*fileGenerator).generateMessageSchemaRef(0x4040bffd40, 0x4000423ef0)
        /home/johan/src/grpc-ecosystem/grpc-gateway/protoc-gen-openapiv3/internal/genopenapiv3/file_generator.go:66 +0xf4 fp=0x4020c00fb0 sp=0x4020c00f30 pc=0x3e7824
github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv3/internal/genopenapiv3.(*fileGenerator).generateFieldTypeSchema(0x4040bffd40, 0x400042f200, {0x4010907e00, 0x28})
...
       /home/johan/src/grpc-ecosystem/grpc-gateway/protoc-gen-openapiv3/internal/genopenapiv3/file_generator.go:66 +0xf4 fp=0x4040bffbe0 sp=0x4040bffb60 pc=0x3e7824
github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv3/internal/genopenapiv3.(*fileGenerator).generateFileSpec(0x4040bffd40, 0x40004ee240)
        /home/johan/src/grpc-ecosystem/grpc-gateway/protoc-gen-openapiv3/internal/genopenapiv3/file_generator.go:44 +0x288 fp=0x4040bffc70 sp=0x4040bffbe0 pc=0x3e76a8
github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv3/internal/genopenapiv3.(*generator).Generate(0x400000c2b8, {0x40004f1e00, 0x4, 0x400024d800?})
        /home/johan/src/grpc-ecosystem/grpc-gateway/protoc-gen-openapiv3/internal/genopenapiv3/generator.go:44 +0x150 fp=0x4040bffdb0 sp=0x4040bffc70 pc=0x3ea8e0
main.main()
        /home/johan/src/grpc-ecosystem/grpc-gateway/protoc-gen-openapiv3/main.go:89 +0x72c fp=0x4040bfff40 sp=0x4040bffdb0 pc=0x3ee05c
runtime.main()
        /usr/local/go/src/runtime/proc.go:283 +0x284 fp=0x4040bfffd0 sp=0x4040bfff40 pc=0x4c064
runtime.goexit({})
        /usr/local/go/src/runtime/asm_arm64.s:1223 +0x4 fp=0x4040bfffd0 sp=0x4040bfffd0 pc=0x85c44

@amirsalarsafaei
Copy link
Author

hank you for testing and reviewing this. To help me investigate, could you please provide the .proto file you used?

My own testing was done with the standard protoc command, which I expected to behave similarly to buf.gen. It seems I've missed an edge case. My leading theory is that the issue is related to a "resurrection check" from v2, which my current implementation doesn't include.

@johanbrandhorst
Copy link
Collaborator

I'm not sure exactly which proto file it is, as I said, I just ran it on the proto files in this repo (using buf generate). You can just re-run the steps I detailed. I've no idea what a "resurrection check" is.

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

Successfully merging this pull request may close these issues.

None yet

2 participants