cloudstate icon indicating copy to clipboard operation
cloudstate copied to clipboard

Tooling - Produce openapi and swagger ui in proxy dev mode

Open sleipnir opened this issue 5 years ago • 5 comments
trafficstars

I think it would be possible when using the proxy in development mode that it could take advantage of the HTTP transcoding mappings to generate a simple OpenAPI output. This would be excellent for testing and development. It also allows users to automatically generate HTTP clients

sleipnir avatar Jun 13 '20 00:06 sleipnir

This is an excellent complement to the gRPC Server Reflection support!

Cheers, √

viktorklang avatar Jun 14 '20 21:06 viktorklang

@viktorklang I found this repository https://github.com/grpc-swagger/grpc-swagger

I think that proves that it is totally possible and feasible. Take a look at the source code, I think it can help

sleipnir avatar Jun 25 '20 04:06 sleipnir

@sleipnir @marcellanz Running Gnostic's protoc-gen-openapi on shoppingcart.proto yields the following result.

# Generated with protoc-gen-openapi
# https://github.com/googleapis/gnostic/tree/master/apps/protoc-gen-openapi
openapi: 3.0.3
info:
    title: ShoppingCart
    version: 0.0.1
paths:
    /cart/{user_id}/items/add:
        post:
            operationId: ShoppingCart_AddItem
            requestBody:
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/AddLineItem'
                required: true
            responses:
                "200":
                    description: OK
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/Empty'
    /cart/{user_id}/items/{product_id}/remove:
        post:
            operationId: ShoppingCart_RemoveItem
            parameters:
                - name: user_id
                  in: query
                  schema:
                    type: string
                - name: product_id
                  in: query
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/Empty'
    /carts/{user_id}:
        get:
            operationId: ShoppingCart_GetCart
            parameters:
                - name: user_id
                  in: query
                  schema:
                    type: string
            responses:
                "200":
                    description: OK
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/Cart'
components:
    schemas:
        AddLineItem:
            properties:
                user_id:
                    type: string
                product_id:
                    type: string
                name:
                    type: string
                quantity:
                    type: integer
                    format: int32
        Cart:
            properties:
                items:
                    type: array
                    items:
                        $ref: '#/components/schemas/LineItem'
        Empty:
            properties: {}
            description: 'A generic empty message that you can re-use to avoid defining duplicated empty messages in your APIs. A typical example is to use it as the request or the response type of an API method. For instance:     service Foo {       rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty);     } The JSON representation for `Empty` is empty JSON object `{}`.'
        LineItem:
            properties:
                product_id:
                    type: string
                name:
                    type: string
                quantity:
                    type: integer
                    format: int32

There seems to be a bit of issues with {user_id} URL segment for /cart/{user_id}/items/add but I think it should be definitely feasible to "handcraft" an OpenAPIv3 YAML and expose that in the proxy under a /openapi.yaml endpoint, and use the returned FileDescriptorSet from the user-function.

viktorklang avatar Nov 16 '20 00:11 viktorklang

Awesome @viktorklang

sleipnir avatar Nov 16 '20 03:11 sleipnir

Pushed this very much work in progress branch for futher exploration: https://github.com/cloudstateio/cloudstate/tree/wip-openapiv3-%E2%88%9A

viktorklang avatar Nov 17 '20 14:11 viktorklang