Smithy RPC v2 CBOR protocol

This specification defines the smithy.protocols#rpcv2Cbor protocol. This protocol is used to expose services that serialize RPC payloads as CBOR.

smithy.protocols#rpcv2Cbor trait

Summary

Adds support for an RPC-based protocol over HTTP that sends requests and responses with CBOR payloads.

Trait selector

service

Value type

Structure

See

Protocol tests

smithy.protocols#rpcv2Cbor is a structure that supports the following members:

Property

Type

Description

http

[string]

The priority ordered list of supported HTTP protocol versions.

eventStreamHttp

[string]

The priority ordered list of supported HTTP protocol versions that are required when using event streams with the service. If not set, this value defaults to the value of the http member. Any entry in eventStreamHttp MUST also appear in http.

Each entry in http and eventStreamHttp SHOULD be a valid Application-Layer Protocol Negotiation (ALPN) Protocol ID (for example, http/1.1, h2, etc). Clients SHOULD pick the first protocol in the list they understand when connecting to a service. A client SHOULD assume that a service supports http/1.1 when no http or eventStreamHttp values are provided.

Event streaming uses the Amazon Event Stream Specification format.

The following example defines a service that uses smithy.protocols#rpcv2Cbor.

$version: "2"

namespace smithy.example

use smithy.protocols#rpcv2Cbor

@rpcv2Cbor
service MyService {
    version: "2020-07-02"
}

The following example defines a service that requires the use of h2 when using event streams.

$version: "2"

namespace smithy.example

use smithy.protocols#rpcv2Cbor

@rpcv2Cbor(
    http: ["h2", "http/1.1"],
    eventStreamHttp: ["h2"]
)
service MyService {
    version: "2020-02-05"
}

The following example defines a service that requires the use of h2 or http/1.1 when using event streams, where h2 is preferred over http/1.1.

$version: "2"

namespace smithy.example

use smithy.protocols#rpcv2Cbor

@rpcv2Cbor(
    http: ["h2", "http/1.1"],
    eventStreamHttp: ["h2", "http/1.1"]
)
service MyService {
    version: "2020-02-05"
}

The following example defines a service that requires the use of h2 for all requests, including event streams.

$version: "2"

namespace smithy.example

use smithy.protocols#rpcv2Cbor

@rpcv2Cbor(http: ["h2"])
service MyService {
    version: "2020-02-05"
}

Supported traits

The smithy.protocols#rpcv2Cbor protocol supports the following traits that affect serialization:

Trait

Description

cors

Indicates that the service supports CORS.

endpoint

Configures a custom operation endpoint.

hostLabel

Binds a top-level operation input structure member to a label in the hostPrefix of an endpoint trait.

httpError

A client error has a default status code of 400, and a server error has a default status code of 500. The httpError trait is used to define a custom status code.

requestCompression

Indicates that an operation supports compressing requests from clients to services.

Protocol behaviors

Implementations of the smithy.protocols#rpcv2Cbor protocol comply with the following rules:

Requests

Every request for the rpcv2Cbor protocol MUST contain a Smithy-Protocol header with the value of rpc-v2-cbor.

Every request for the rpcv2Cbor protocol MUST be sent using the HTTP POST method. HTTP binding traits MUST be ignored when building rpcv2Cbor requests if they are present.

Every request for the rpcv2Cbor protocol MUST be sent to a URL with the following form: {prefix?}/service/{serviceName}/operation/{operationName}

  • The Smithy RPCv2 CBOR protocol will only use the last four segments of the

    URL when routing requests. For example, a service could use a v1 prefix in the URL path, which would not affect the operation a request is routed to: v1/service/FooService/operation/BarOperation

  • The serviceName segment MUST be replaced by the shape name

    of the service's Shape ID in the Smithy model. The serviceName produced by client implementations MUST NOT contain the namespace of the service shape. Service implementations SHOULD accept an absolute shape ID as the content of this segment with the # character replaced with a . character, routing it the same as if only the name was specified. For example, if the service's absolute shape ID is com.example#TheService, a service should accept both TheService and com.example.TheService as values for the serviceName segment.

  • The operationName segment MUST be replaced by the name of the operation

    shape in the Smithy. The operationName produced by client implementations MUST NOT contain the namespace of the operation shape. Service implementations MUST NOT accept an absolute shape ID as the content of this segment.

Requests for the rpcv2Cbor protocol MUST use the following behavior for setting a Content-Type header:

  • Buffered RPC requests: the value of the Content-Type header MUST be

    application/cbor.

  • Event streaming requests: the value of the Content-Type header MUST be

    application/vnd.amazon.eventstream.

  • Requests for operations with no defined input type (as in, they target the

    Unit shape) MUST NOT contain bodies in their HTTP requests. The Content-Type for the serialization format MUST NOT be set.

Requests for the rpcv2Cbor protocol MUST NOT contain an X-Amz-Target or X-Amzn-Target header. An rpcv2Cbor request is malformed if it contains either of these headers. Server-side implementations MUST reject such requests for security reasons.

Buffered RPC requests for the rpcv2Cbor protocol SHOULD include a Content-Length header. Event streaming requests MUST NOT specify a content length (instead using Transfer-Encoding: chunked on HTTP/1.1).

Requests for the rpcv2Cbor protocol MUST use the following behavior for setting an Accept header:

  • For requests with event streaming responses: the value of the Accept

    header MUST be application/vnd.amazon.eventstream.

  • For requests with all other response types: the value of the Accept

    header MUST be application/cbor.

Other forms of content streaming MAY be added in the future, utilizing different values for Accept.

In summary, the rpcv2Cbor protocol defines behavior for the following headers for requests:

Header

Status

Description

Smithy-Protocol

Required

The value of rpc-v2-cbor.

Content-Type

Required with request bodies

The value of application/cbor. For event streaming requests, this is application/vnd.amazon.eventstream.

Content-Length

Conditional

The standard Content-Length header defined by RFC 9110 Section 8.6. For event streaming requests, this MUST NOT be set.

Accept

Required

The value of application/cbor. For requests with event streaming responses, this is application/vnd.amazon.eventstream.

Responses

The status code for successful rpcv2Cbor responses MUST be 200.

The status code for error rpcv2Cbor MUST be determined by the following steps:

  1. If the httpError trait is set on the error shape, its value is used.

  2. If the error trait is set to server, the value MUST be 500.

  3. Otherwise, the value MUST be 400.

Every response for the rpcv2Cbor protocol MUST contain a Smithy-Protocol header with the value of rpc-v2-cbor. The response MUST match the value of the Smithy-Protocol header from the request.

Responses for the rpcv2Cbor protocol MUST use the following behavior for setting a Content-Type header:

  • Buffered RPC responses: the value of the Content-Type header MUST be application/cbor.

  • Event streaming responses: the value of the Content-Type header MUST be application/vnd.amazon.eventstream.

  • Responses for operations with no defined output type (as in, they target the Unit shape) MUST NOT contain bodies in their HTTP responses. The Content-Type for the serialization format MUST NOT be set.

Buffered RPC responses for the rpcv2Cbor protocol SHOULD include a Content-Length header. Event streaming responses SHOULD NOT specify a content length (instead using Transfer-Encoding: chunked on HTTP/1.1).

Responses for the rpcv2Cbor protocol SHOULD NOT contain the X-Amzn-ErrorType header. Type information is always serialized in the payload. Clients MUST ignore this header. See Operation error serialization for information on the serialization of error responses.

In summary, the rpcv2Cbor protocol defines behavior for the following headers for responses:

Header

Status

Description

Smithy-Protocol

Required

The value of rpc-v2-cbor.

Content-Type

Required with response bodies

The value of application/cbor. For event streaming responses, this is application/vnd.amazon.eventstream.

Content-Length

Conditional

The standard Content-Length header defined by RFC 9110 Section 8.6. For event streaming requests, this SHOULD NOT be set.

Shape serialization

The smithy.protocols#rpcv2Cbor protocol serializes all shapes into a CBOR document body with no HTTP bindings supported. The following table shows how to convert each shape type:

Smithy type

CBOR representation

blob

Major type 2 (byte string)

boolean

Major type 7 (simple)

byte

Major type 0 (unsigned integer) or major type 1 (negative integer)

short

Major type 0 (unsigned integer) or major type 1 (negative integer)

integer

Major type 0 (unsigned integer) or major type 1 (negative integer)

long

Major type 0 (unsigned integer) or major type 1 (negative integer)

float

Major type 7 (float)

double

Major type 7 (float)

bigInteger

Major type 6, value tags 2 (unsigned bignum) or 3 (negative bignum)

bigDecimal

Major type 6, value tag 4 (decimal fraction)

string

Major type 3 (text string)

timestamp

See Timestamp type serialization.

document

Document types are not currently supported in this protocol.

list

Major type 4 (array of data items)

map

Major type 5 (map of pairs of data items), each key/value pair is a pair in the type

structure

Major type 5 (map of pairs of data items), each member is the key to a pair in the type

union

Major type 5 (map of pairs of data items), each member is the key to a pair in the type.

A union is serialized identically as a structure shape, but only a single member can be set to a non-null value. Deserializers MUST ignore an unrecognized __type member if present.

Values that are null MUST be omitted from wire contents where not subject to default value serialization rules.

If an implementation does not support arbitrary precision (bigInteger and bigDecimal Smithy types), it MUST fail when attempting to deserialize a value of that type.

Note

The undefined CBOR value, CBOR major type 7 value 23, is not supported. Clients SHOULD NOT serialize to this CBOR value and SHOULD deserialize this CBOR value to null. Servers MUST NOT serialize to this CBOR value and MUST deserialize this CBOR value to null.

Numeric type serialization

Numeric types (byte, short, integer, long, float, and double) SHOULD be serialized into the smallest possible CBOR type representation that can contain its value. For example, a field modeled as a long with a value of 1 should be sent in a single byte.

Floating-point numeric types (float and double) MAY be serialized into non-floating-point numeric types (byte, short, integer, and long) if and only if the conversion would not cause a loss of precision. For example, a field modeled as a float with a value of 256 may be sent as an integer.

As support for half-precision floating-point values is inconsistent across implementations, floating-point numeric types SHOULD NOT serialize into a half-precision (16 bit) numeric CBOR values. Implementations MUST be capable of deserializing half-precision numeric CBOR values (including -Infinity, Infinity, and NAN) into their Smithy type representation.

Numeric types MUST be deserialized into their Smithy type representation. For example, a field modeled as a long with a single byte value of 1 must be deserialized into a long.

Timestamp type serialization

Timestamps are serialized as major type 6, value tag 1 (epoch-based date/time) to indicate the tagged value is an epoch timestamp. Values are either major type 0 (unsigned integer) or major type 1 (negative integer) for integer values or major type 7, value 25 (half-precision float), 26 (single-precision float), or 27 (double-precision float) for floating-point values.

As support for half-precision floating-point values is inconsistent across implementations, timestamp types SHOULD NOT serialize into a half-precision (16 bit) numeric CBOR value for the tagged value.

This protocol uses epoch-seconds, also known as Unix timestamps, with millisecond (1/1000th of a second) resolution. The timestampFormat MUST NOT be respected to customize timestamp serialization.

Default value serialization

To avoid information disclosure, service serializers SHOULD omit the default value of structure members that are marked with the internal trait.

Client deserializers SHOULD attempt to error correct structures that omit a required member by filling in a default zero value for the member. Error correction allows clients to continue to function while the server is in error.

Operation response deserialization

Clients MUST use the following rules to interpret responses and determine how to deserialize them:

  1. If the response does not have the same Smithy-Protocol header as the

    request, it MUST be considered malformed. Clients who receive a malformed response MUST handle it (i.e. throw a reasonable exception) based solely on the HTTP response code. No attempt should be made to interpret the response body or headers.

  2. If the response code is 200, the request is successful and the response

    payload SHALL be deserialized as the output shape defined on the operation.

  3. Finally, if the response code is not 200, the response payload is an

    exception and SHALL be deserialized according to Operation error serialization

Operation error serialization

Error responses in the rpcv2Cbor protocol MUST be serialized identically to standard responses with one additional component to distinguish which error is contained: a body field named __type. This value of this component MUST contain the error’s absolute Shape ID.

By default, all error shapes have a message field containing an error-specific message meant for human consumers of API errors. Services MUST support generating this field and serializing it when responding. Clients MUST support generating this field and deserializing it from responses.

The Code response body field and code response body field MUST NOT be used to distinguish which error is contained in a response.

Clients who receive a malformed error response MUST handle it based solely on the HTTP response code (i.e. throw a reasonable exception). No attempt should be made to interpret the response body or headers.

Error shape renaming

By default, Smithy permits renaming shapes to disambiguate shape ID conflicts in the service closure via the rename property. However, services using this protocol are not allowed to rename error shapes (shapes with error trait applied).