Protocol Buffers are not very “RESTish”.
There’s been a lot of activity recently around highly optimized, binary serialization formats such as Google Protocol Buffers and Thrift. There have been some attempts to include formats such as Protocol Buffers into their “REST API” because of perceived performance benefits without consideration of the downside of an IDL format with respect to REST.
To illustrate why Protocol Buffers inherently adulterate REST architectural style, I’ve compiled the following points:
Imposes a Tight Coupling
This tight coupling is considered a REST anti-pattern and should be avoided. Protobuf over HTTP is probably a form of RPC-URI tunneling, it is not REST. In order to work with protobufs efficiently, both the client and server must have code generated by the .proto definition.
Strongly Typed Resources
A key point made my Roy T. Fielding in one of his more informative blog posts is that:
A REST API should never have “typed” resources that are significant to the client. Specification authors may use resource types for describing server implementation behind the interface, but those types must be irrelevant and invisible to the client. The only types that are significant to a client are the current representation’s media type and standardized relation names.
I’m not totally sure I’ve got this one 100% correct, but it would appear that the use of protobufs is now also exposing typed resources to the client. Additionally, there is no means to specify which type to ask for. Which leads me to my next point:
Ambiguous Media Type
Subbu Allamaraju has pointed out that the protobuf media type doesn’t doesn’t convey enough information as to indicate what message type is in the protobuf representation in a post about a Protobuf provider for JAX-RS. Protobuf doesn’t have an official media type, but folks generally use one of the following media types:
Protobufs are not generic and the representation contains data for a very specific message. Furthermore, the serialized form contains no information as to what type(s) it represents. So although you may have specified the media type in the request, there is no mechanism to specify which protobuf message we actually want. One suggestion as to how this might be resolved is to specify the .proto package and message name by using a parameter:
The approach seems reasonable enough. But as Subbu also points out, this solution also requires that the .proto be shared between the client and server in order to establish the binding. Clearly there’s a number of options that could be applied share the .proto definition, but all of them involve some type of external configuration in order to resolve the .proto since the protobuf wire format is not self-describing.
Self-Describing formats must be Self-Describing
Protocol Buffers are not self-describing by design. The Google documentation even states that:
“Protocol Buffers do not contain descriptions of their own types. Thus, given only a raw message without the corresponding
.protofile defining its type, it is difficult to extract any useful data.”
This isn’t necessary a bad thing in general, but it does violate a core tenet or RESTful architecture. Section 126.96.36.199 of the Roy T. Fielding’s dissertation states that a proper representation consists of the following:
- The data
- Metadata that describes the data
- Optional metadata about the metadata, usually used to for integrity checking.
Protocol Buffers only handle the data. Google has presented an option for making protobuf messages self-describing. While this works, it still has three fundamental flaws:
- The SelfDescribingMessage itself is not self-describing
- There’s still a tight coupling between client and server for the SelfDescribingMessage as generated code is still required on both client and server.
- It doesn’t address dependency resolution. That is, message you’re sending over might extend or depend on other .proto definitions. How you resolve those dependencies is a challenge.
The dependency resolution is no small challenge and becomes a major headache if you’re extending messages from other parties.
Application State is not Hypermedia driven
Protocol Buffers do not have a means to describe links to external messages. Most applications I’ve encountered that use protobufs either send the entire message tree in a single call or there is some type of ID value that the client will have to dereference somehow. The latter ultimately results in either forcing the client to infer and generate URLs, which is yet another REST anti-pattern.
This isn’t to say that Protocol Buffers are inherently bad. Google has proven that protobufs have value when used as intended. Outside of an RPC system, protocol buffers are really don’t seem appropriate for web applications who claim to be RESTful. Of course, I could be complete wrong here and I’m sure the internets will be certain to let me know.