Skip to content

Support an RPC structure of API #664

Closed

Description

@SvyatoslavVasiliev

Hi there!
I am realy sad that OpenAPI specification does not support RPC style of API, because of path centric structure. There is so many tools to describe REST API, but there is no such to describe RPC API. And recently your initiative have appeared with Open API ideology, but without supporting of RPC API style. Why? Could you add it to nearest release?

Activity

  1. webron commented on Apr 19, 2016

    @webron
    Member

    RPC style APIs could be a side effect of #574. An unfortunate side effect, IMHO.

  2. SvyatoslavVasiliev commented on Apr 20, 2016

    @SvyatoslavVasiliev
    Author

    @webron it seems like that implementation of operations really solves issue of describing RPC API. There is can be some details related to JSON RPC 2.0, for example, but I hope you cover most cases.
    Thank you, and if it possible to take part in testing of your new realease, I would glad to join.

  3. changed the title [-]RPC structure of API supporting[/-] [+]Support an RPC structure of API[/+] on Apr 20, 2016
  4. webron commented on Apr 20, 2016

    @webron
    Member

    Parent: #586.

  5. webron commented on Apr 20, 2016

    @webron
    Member

    Following a different thread, it's unlikely #574 will resolve it as it's controlled by the content of the request, not the structure of it. Moving it under #586.

  6. vearutop commented on May 22, 2016

    @vearutop
    Contributor

    I use swagger spec to describe JSON-RPC in a hacky way, storing method names in paths keys and ignoring non-post operations. Hack is enabled by x-service-type vendored flag.

  7. earth2marsh commented on May 23, 2016

    @earth2marsh
    Member

    @vearutop that sounds interesting—do you have an example you could share?

  8. vearutop commented on May 24, 2016

    @vearutop
    Contributor

    basePath is used for endpoint value.
    x-service-type specifies how to treat swagger.json file.
    For this vendor extension we have a patched swagger-ui which envelopes original request to something like {"jsonrpc": "2.0", "method": "getSimpleV1", "params": {"id":3}, "id": 1}.
    That simple we benefit from swagger spec and tools not only for our REST, but also for JSON-RPC services.

    {
      "swagger": "2.0",
      "x-service-type": "json-rpc",
      "info": {
        "title": "DummyAPI",
        "version": "master~dirty"
      },
      "host": "",
      "basePath": "/rpc",
      "schemes": [
        "http",
        "https"
      ],
      "paths": {
        "getSimpleV1": {
          "post": {
            "tags": [
              "V1"
            ],
            "summary": "Simple Get",
            "description": "Get simple by ID",
            "parameters": [
              {
                "name": "body",
                "in": "body",
                "schema": {
                  "$ref": "#/definitions/SimpleGetParameters"
                },
                "required": true
              }
            ],
            "responses": {
              "200": {
                "description": "request success",
                "schema": {
                  "$ref": "#/definitions/Simple"
                }
              }
            }
          }
        }
      },
      "definitions": {
        "Simple": {
          "type": "object",
          "properties": {
            "id_simple": {
              "type": "integer"
            },
            "name": {
              "type": "string"
            }
          }
        },
        "SimpleGetParameters": {
          "type": "object",
          "properties": {
            "id": {
              "type": "integer"
            }
          }
        }
      }
    }
    
  9. wparad commented on May 24, 2016

    @wparad

    That's a little disappointing, I was really hoping to see something interesting, like folding of the parameters into the existing document, with clever uses of the flags. Having to use a different library to pull meaningful data is unfortunate.

  10. vearutop commented on May 24, 2016

    @vearutop
    Contributor

    Sorry, @wparad, I did not mean to make you sad (mind hacky way disclaimer).
    Not sure I got you right, by "folding of the parameters into the existing document" do you mean having JSON-RPC envelope structures built in schema definition? What is "different library"?

  11. SvyatoslavVasiliev commented on May 24, 2016

    @SvyatoslavVasiliev
    Author

    @vearutop, could you clarify, your API has structure according to JSON RPC 2.0 or you are just using RPC style for URL resources?

  12. vearutop commented on May 24, 2016

    @vearutop
    Contributor

    @SvyatoslavVasiliev, API is serving valid JSON RPC 2.0 structures.
    JSON RPC enveloping (including batch requests) is done by client and server according to spec.
    method, params and result is defined and validated by swagger.json path, post-parameters and post-responses-200 accordingly.
    Endpoint URI is defined in swagger.json as basePath.
    Service host is dynamic and loadbalanced, so it is not present in swagger.json.

    Actually this swagger.json is not valid, since it does not have / at the beginning of paths keys.
    But this approach made possible to achieve "compatibility" with least effort.

  13. SvyatoslavVasiliev commented on May 24, 2016

    @SvyatoslavVasiliev
    Author

    @vearutop, thank you, as I am looking for some tool to specify my JSON RPC API, I will try your approach in swagger. But unfortunately, as @wparad already said, standard swagger library won't be able to work with it fully. For example if I try to upload your specification in on-line swagger editor I won't able to make API requests, because of wrong auto generated URL.

  14. AlJohri commented on Dec 29, 2016

    @AlJohri

    hi @webron, I was wondering if there's any update on this issue? thanks!

  15. radek-smseagle commented on Jan 26, 2017

    @radek-smseagle

    Hi, same here. I would really be glad to hear that OpenAPI (Swagger) can handle JSON RPC style APIs.

  16. dasheck0 commented on Mar 21, 2017

    @dasheck0

    +1 for this. Swagger is de facto standard. It should feel the urge to influence the standard of RPC documentation as well.

  17. o314 commented on May 6, 2017

    @o314

    +1000
    REST = SQL Web API != Computer Science + Information Technology + Computational Science
    Trying to implement google maps in sql may help to understand the most stubborn soul.

    Data manipulation and, side by side, function call is a must.

    By the way json-rpc 2 is pretty simple, good and stable.

  18. darrelmiller commented on May 6, 2017

    @darrelmiller
    Member

    OpenAPI provides JSON Schema to describe a wide range of payloads. If an API provider decides to create a single path item object with many different payloads in order to tunnel procedure calls, then OpenAPI can do that. The support for JSON Schema oneOf in OpenAPI V3 will make that even easier.

    If people want to build tooling that map those payloads into UI as if they were different path item objects, then they are free to do so. I don't believe that the OpenAPI spec should try and standardize a mapping between those payloads and native HTTP constructs. If there is sufficient community support to standardize that mapping then I would encourage that community to create it and encourage tool builders to support it.

  19. o314 commented on May 6, 2017

    @o314

    @darrelmiller

    I have to admit it's a bit harsh to understand all the terms you cite for an outsider for now o:
    (But i have a second screen diffusing the linux foundation mooc at this same amazing time, and sure, that will help to catch in the long run).

    I will follow your tips and wait/contribute example from/to the community.

    By the way, thanks for the quick answer, and what a good teasing for the v3!

  20. ltfschoen commented on Nov 9, 2018

    @ltfschoen

    I ended up using @vearutop 's approach to create a demo. We have a single endpoint for JSON-RPC calls that each have a different method. But I've explained how we resolved it in the main "info" > "description" section of the following OAS3 that I've pushed here:
    https://github.com/ltfschoen/swagger/blob/master/scon_substrate_0.4.0_swagger.json
    It can be viewed with Swagger UI here: https://app.swaggerhub.com/apis-docs/scon/substrate/0.4.0
    And I also imported into Readme.io here: https://substrate.readme.io/v1.0.0/reference

  21. thephez commented on Dec 4, 2018

    @thephez

    I ran into this issue recently too and ended up here from swagger-api/swagger-codegen#4274. I finally have something that is working relatively well for what I am doing so I created a JSON-RPC 2.0 OAS sample gist for anyone else that may benefit from it. You can copy/paste it into http://editor.swagger.io/ to experiment with it.

    There is a simple POST that includes a JSON-RPC param. I also showed how to use a ref (in conjunction with allOf) to avoid duplicating the method, id and jsonrpc properties.

    Copy of gist:

    {
      "x-send-defaults": true,
      "openapi": "3.0.0",
      "x-api-id": "json-rpc-example",
      "info": {
        "title": "JSON-RPC OpenAPI",
        "version": "1.0.0",
        "description": "Example of how to describe a JSON-RPC 2 API in OpenAPI"
      },
      "servers": [
        {
          "url": "http://127.0.0.1:3000"
        }
      ],
      "paths": {
        "/examplePost": {
          "post": {
            "operationId": "examplePost",
            "deprecated": false,
            "summary": "Example of JSON-RPC2 Post",
            "description": "Example post using JSON-RPC params.",
            "tags": [
              "JSONRPC"
            ],
            "parameters": [],
            "responses": {
              "200": {
                "description": "Successful response"
              }
            },
            "requestBody": {
              "content": {
                "application/json": {
                  "schema": {
                    "type": "object",
                    "required": [
                      "method",
                      "id",
                      "jsonrpc",
                      "params"
                    ],
                    "properties": {
                      "method": {
                        "type": "string",
                        "default": "examplePost",
                        "description": "Method name"
                      },
                      "id": {
                        "type": "integer",
                        "default": 1,
                        "format": "int32",
                        "description": "Request ID"
                      },
                      "jsonrpc": {
                        "type": "string",
                        "default": "2.0",
                        "description": "JSON-RPC Version (2.0)"
                      },
                      "params": {
                        "title": "Parameters",
                        "type": "object",
                        "required": [
                          "jsonParam"
                        ],
                        "properties": {
                          "jsonParam": {
                            "type": "integer",
                            "default": 1,
                            "description": "A param to include"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "/examplePost2": {
          "post": {
            "operationId": "examplePost2",
            "deprecated": false,
            "summary": "Example of JSON-RPC2 Post",
            "description": "Example post using JSON-RPC params. Also uses a ref to avoid duplicating properties.",
            "tags": [
              "JSONRPC"
            ],
            "parameters": [],
            "responses": {
              "200": {
                "description": "Successful response"
              }
            },
            "requestBody": {
              "content": {
                "application/json": {
                  "schema": {
                    "$ref": "#/components/schemas/examplePost"
                  }
                }
              }
            }
          }
        }
      },
      "x-headers": [],
      "x-explorer-enabled": true,
      "x-proxy-enabled": true,
      "x-samples-enabled": true,
      "x-samples-languages": [
        "curl",
        "node",
        "ruby",
        "javascript",
        "python"
      ],
      "components": {
        "schemas": {
          "JsonRpcRequired": {
            "type": "object",
            "required": [
              "method",
              "id",
              "jsonrpc"
            ],
            "properties": {
              "method": {
                "type": "string",
                "default": "examplePost",
                "description": "Method name"
              },
              "id": {
                "type": "integer",
                "default": 1,
                "format": "int32",
                "description": "Request ID"
              },
              "jsonrpc": {
                "type": "string",
                "default": "2.0",
                "description": "JSON-RPC Version (2.0)"
              }
            },
            "discriminator": {
              "propertyName": "method_name"
            }
          },
          "examplePost": {
            "allOf": [
              {
                "$ref": "#/components/schemas/JsonRpcRequired"
              },
              {
                "type": "object",
                "properties": {
                  "params": {
                    "title": "Parameters",
                    "type": "object",
                    "required": [
                      "jsonParam"
                    ],
                    "properties": {
                      "jsonParam": {
                        "type": "integer",
                        "default": 1,
                        "description": "A param to include"
                      }
                    }
                  }
                }
              }
            ]
          }
        }
      },
      "tags": []
    }
    
  22. CharlieBreval commented on Oct 19, 2021

    @CharlieBreval

    @thephez Thanks a lot for your gist, very interesting and helpfull 🥇 .
    One point that I don't understand is that using json-rpc, we use to always call the same url, kind of "/json-rpc", because the url doesn't matter as we are using the method name as discriminant.

    Meanwhile on your example, the 2 calls you described are hitting 2 different urls

  23. thephez commented on Oct 19, 2021

    @thephez

    @CharlieBreval Glad it was helpful to you. It's been a while, but as I recall I my reason for the 2 different URLs had something to do with the specific tool that I was importing this into.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions