# The hRPC Specification This document defines and explains design details for hRPC. ## Version This is hRPC specification version `1`. ## Protobuf Version All hRPC implementations **MUST** support [Protobuf 3](https://developers.google.com/protocol-buffers/docs/reference/proto3-spec). All references to Protobuf in this document are references to Protobuf 3. ## RPCs A unary RPC is where a Protobuf RPC signature is as follows: ```protobuf rpc ExampleMethod(ExampleMessage) returns (ExampleMessage); ``` A streaming RPC is where a Protobuf RPC signature is as follows: ```protobuf rpc ExampleMethod(stream ExampleMessage) returns (stream ExampleMessage); ``` A client streaming RPC is where a Protobuf RPC signature is as follows: ```protobuf rpc ExampleMethod(stream ExampleMessage) returns (ExampleMessage); ``` In client streaming RPCs, the server is only allowed to send **one** message. Messages sent after that **SHOULD** be ignored by the client. A server streaming RPC is where a Protobuf RPC signature is as follows: ```protobuf rpc ExampleMethod(ExampleMessage) returns (stream ExampleMessage); ``` In server streaming RPCs, the client is only allowed to send **one** message. Messages sent after that **SHOULD** be ignored by the server. ### Errors Servers can send errors to clients using the [hRPC error] protocol type. How errors sent are dependent on the transport used. Error identifiers are described in the [hRPC errors document]. ## Transports hRPC is transport agnostic. Here we describe transport specific design details. ### HTTP This transport works over HTTP. #### Request Paths A request path is a string in the following format, where `` is the name of the package, `` is the name of the service and `` is the name of the RPC: ``` /./ ``` If `` is empty, it becomes the following: ``` // ``` This is used as the path of an URI while making a request to a server. ##### Example For the Protobuf definition below: ```protobuf syntax = "proto3"; package example; message ExampleMessage { } service ExampleService { rpc ExampleMethod(ExampleMessage) returns (ExampleMessage); } ``` The `ExampleMethod` RPC will have a request path of: ``` /example.ExampleService/ExampleMethod ``` #### Unary RPCs ##### Unary requests - **MUST** have method set to `POST`. - **MUST** contain the serialized binary data of the Protobuf message in their body. - **MUST** set the [`Content-Type`][http headers] header to `application/hrpc`. - **MUST** set the [`Content-Length`][http headers] header to the length of the serialized binary data. - **SHOULD** add `` to `Hrpc-Version` header, where `` is the [version defined at the start of this document](#Version). ##### Unary responses - **MUST** contain the serialized binary data of the Protobuf message in their body. - **MUST** set the [`Content-Type`][http headers] header to `application/hrpc`. - **MUST** add `` to `Hrpc-Version` header, where `` is the [version defined at the start of this document](#Version). ##### Client behaviour - After getting a successful unary response, a client **SHOULD** look for the `Hrpc-Version` header. A client then **SHOULD** check if it can work with the version of the specification in the header. A client **SHOULD** return an error to the user notifying of the incompatible spec version. #### Streaming RPCs Streaming RPCs use a [`WebSocket`][websocket] to communicate Protobuf messages between server and client. The initial handshake is done through HTTP. ##### Handshake requests - **MUST** have method set to `GET`. - **MUST** contain `hrpc` in the [`Sec-WebSocket-Protocol`][websocket_protocol_header] header, where `` is the [version defined at the start of this document](#Version). ##### Handshake responses - **IF** the request had `hrpc` in the [`Sec-WebSocket-Protocol`][websocket_protocol_header] header, **MUST** set the same header to `hrpc`, where `` is the [version defined at the start of this document](#Version). ##### Client behaviour - After getting a successful handshake response from the server, a client **SHOULD** look for `hrpc` in the [`Sec-WebSocket-Protocol`][websocket_protocol_header] header. The `` will be the version of hRPC implemented by the server. A client then **SHOULD** check if it can work with this version of the specification. If a client can't work with this version, it **SHOULD** close the [`WebSocket`][websocket]. - [`WebSocket` binary messages][websocket_messages] **MUST** be used to send RPCs request message in serialized form to the server. ##### Server behaviour - [`WebSocket` binary messages][websocket_messages] **MUST** be used to send RPCs response message or a [hRPC error] prefixed with an opcode. - If sending RPCs response message, the serialized message **MUST** be prefixed with `0`. - If sending a [hRPC error], the serialized error **MUST** be prefixed with `1`. ### Errors When a request fails for whatever reason, an error response should be sent. This applies to socket handshake requests and unary requests. Below should be implemented for error responses: - **MUST** set the body to a serialized [hRPC error] message. Implementations **MUST** use the [hRPC errors document] to decide what error identifier to use. Implementations **SHOULD** set a descriptive human readable error message. - **MUST** set the status to an **unsuccessful** [HTTP status]. This should be the status code corresponding to the error identifier. Implementations **MUST** use the [hRPC errors document] to decide what status to set. - **MUST** set the [`Content-Type`][http headers] header to `application/hrpc`. - **MUST** add `` to `Hrpc-Version` header, where `` is the [version defined at the start of this document](#Version). [http headers]: https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html [websocket]: https://datatracker.ietf.org/doc/html/rfc6455 [websocket_messages]: https://datatracker.ietf.org/doc/html/rfc6455#section-5.6 [websocket_protocol_header]: https://datatracker.ietf.org/doc/html/rfc6455#section-11.3.4 [websocket_extensions_header]: https://datatracker.ietf.org/doc/html/rfc6455#section-11.3.2 [hrpc error]: ./hrpc.proto#L5-L13 [http status]: https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html [hrpc errors document]: ./ERRORS.md