Skip to content

Instantly share code, notes, and snippets.

@billiegoose
Last active August 22, 2017 03:28
Show Gist options
  • Save billiegoose/4bd29e36346f7a4b5f54 to your computer and use it in GitHub Desktop.
Save billiegoose/4bd29e36346f7a4b5f54 to your computer and use it in GitHub Desktop.
Embedding data in HTTP messages - an exhaustive analysis

Embedding data in HTTP messages - an exhaustive analysis

Hypertext Transport Protocol (HTTP) is the de facto protocol for sending data over the Internet. Today in addition to transporting hypertext documents, it is used to transport images, stylesheets, JavaScript, fonts - nearly everything in a web page. Rarely do developers pause to question why this is. Lately, I've been thinking a lot about HTTP and its relation to APIs and web apps. This document contains my thoughts on the usefulness of HTTP requests as envelopes for sending data.

HTTP requests consist of at least 7 pieces: the path, the query string, the method, the status, the headers, the body, and cookies. (Technically cookies are a subcategory of headers but they have additional behaviors that make them worth examining separately.) This article examines each of them from the perspective of their utility for carrying arbitrary data. Note: This article only looks at HTTP/1.

Least general

REST APIs often make use of HTTP methods and response status codes to convey information. I would classify these as ways of encoding enumerated types. Often this is supplemented by data in the HTTP response body, which is because these mechanisms are insufficient to communicate anything substantial.

Availability Pros Cons
HTTP method client Shown prominently in DevTools. Need special tools like curl or Postman to send data.
HTTP status codes server Well organized (200, 404, 500, etc). Shown prominently in DevTools. No way to include extra data including error details. Unidirectional (set by server).

Flexible, yet structured

HTTP provides a number of ways to encode key / value pairs in requests and responses. Key/value stores (Redis, IndexDB, LevelDB, etc) have had a resurgence of popularity of late as a NoSQL alternative to relational databases. These encodings might be an elegant match for some use cases.

Availability Pros Cons
HTTP X-Custom-Headers server & client None? Need special tools to render and parse. No theoretical size limit, but a practical limit of ~10,000 characters.
Cookies server & client Flexible. Can be read/writeable in JS, or hidden from JS, and can force an encrypted HTTPS-only transport. Poor separation of concerns. Variously acts as an arbitrary client-local storage, as a client identification system (and hence security mechanism), in addition to its ability to encode data.
URL query parameters client Highly accessible. Can be typed directly into the address bar. More complex data (whitespace) requires awkward variant of percent-encoding. No theoretical size limit, but a practical limit in most software of ~1,000 characters.

Most general

Lastly, HTTP provides a few ways that work well for encoding arbitrary data. Technically, any of the above methods can encode arbitrary data. (For example, you could return any number in the HTTP status code, and thus treat the status code as a bit-string.) However, doing so eliminates the advantage of using HTTP in the first place - the availability of parsing, rendering, and debugging tooling already present in the software ecosystem (or even just in the browser DevTools).

Availability Pros Cons
URL path client Highly accessible. Can be typed directly into the address bar. Works well for some hierarchical data. Poor separation of concerns. The domain is always a fixed address specifier due to DNS. The fragment identifier can represent client state such as scrollbar position. Only the path part of the URL can encode arbitrary data, and even then it must be percent-encoded.
HTTP body server & client Extremely flexible. Practically no size limit. Allows true arbitrary data. (Encoding is specified in HTTP header.) Only available with PUT and POST. No well-established semantic convention for structuring responses. The variety of encodings (application/x-www-form-urlencoded, multipart/form-data, application/json) can be overwhelming.

In Summary

There are at least 7 distinct ways to encode information:

Name Examples
1. URL path (/users, /user/1, /user/1/msgs, /user/1/msg/1, ...)
2. URL query (?id=1, ?q=search&order=desc, ?page=2, ?array=foo&array=bar, ...)
3. HTTP method (GET, PUT, POST, DELETE, ...)
4. HTTP status (200 OK, 404 Not Found, 201 Created, ...)
5. HTTP headers (Authorization: Bearer $TOKEN, X-RateLimit-Remaining: 56, ...)
6. HTTP body (multipart/form-data, XML, JSON, ...)
7. HTTP cookies (connect.sid, PHPSESSID, ...)

Most REST APIs actually utilize most of these features, perhaps skipping over query parameters and cookies. This wouldn't be a big deal if using each of the ways was easy and consistent. However in practice, each way has its own API and set of quirks that have to be remembered. Consider jQuery.ajax:

Name How to use
URL path specified as 1st argument
URL query use data setting with GET requests
HTTP method use method setting OR more frequently use a helper function ($.post, $.get, etc)
HTTP status use separate callbacks for "errors" and "successes"
HTTP headers use headers setting
HTTP body use data setting with appropriate dataType setting
HTTP cookies use xhrFields.withCredentials: true setting to include existing cookies in requests.*

* However, there is no way to edit the cookie (or read it) using just jQuery.

Parting Thoughts

I put forward the hypothesis that the HTTP request protocol is probably more complicated than it needs to be. This added complexity means there are more things that can go wrong, which means there are more things developers need to know about to debug their code. This, in turn, steepens the learning curve and slows down development.

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