jsontp - version 1.0-rc2
-
jsonis the ubiquitous data interchange format for the web -
HTTPis the ubiquitous protocol for the web -
but
HTTPis not easy to parse -
jsontpis an protocol that usesjsonas its data interchange format -
the
HTTPspecification is often changed, whilst thejsonspecification is stable -
the
jsontpprotocol is designed to be easy to parse and easy to generate -
the
jsontpprotocol is sent overTCP
the jsontp protocol
- there are two types of
jsontpmessages:requestandresponse - a
requestmessage is sent from client to server, and aresponsemessage is sent from server to client
graph TD
A[Client] -->|request| B[Server]
B -->|response| A
the jsontp request message
- the
jsontprequest message is sent from the client to the server - it must always include:
- the
jsontpkey-value pair - the
typekey-value pair - the
resourcekey-value pair - the
methodkey-value pair - the
headersobject (no mandatory headers in the request, but must always be present even if empty, in which case it should be{}) - the
bodyobject - the
bodyobject must always include:- the
contentkey-value pair - the
encodingkey-value pair
- the
- the
{
"jsontp": "1.0", // required and in the format `major.minor`
"type": "request",
"resource": "/path/to/resource",
"method": "GET",
"headers": { // no required headers in the request
"key1": "value1",
},
"body": {
"key1": "value1", // optional
"content": "raw text to be sent", // must always be present, even if empty
"encoding": "gzip" // required, but can be `identity` if no encoding is used
}
}
the jsontp response message
- the
jsontpresponse message is sent from the server to the client - it must always include:
- the
jsontpkey-value pair - the
statusobject - the
resourcekey-value pair - the
headersobject - the
bodyobject - the
statusobject must always include:- the
codekey-value pair - the
formal-messagekey-value pair - the
human-messagekey-value pair
- the
- the
headersobject must always include:- the
datekey-value pair - the
languagekey-value pair
- the
- the
bodyobject must always include:- the
contentkey-value pair - the
encodingkey-value pair
- the
- the
{
"jsontp": "1.0", // required and in the format `major.minor(-rcx)` (explained more in the `jsontp` versioning section)
"type": "response",
"status": {
"code": 200, // a valid `HTTP` status code (not 1xx)
"formal-message": "OK", // a valid `HTTP` status message
"human-message": "The request was successful." // a human-readable message, the contents of which is up to the discretion of the server, but should be helpful to the client. It is required, but can be a copy of the `formal-message` if the server wishes.
},
"resource": "/path/to/resource",
"headers": {
"date": "2024-01-01T00:00:00Z+00:00", // required and always in this format. Should always be in UTC, but a compliant client should accept any timezone
"language": "en-US", // required and always in this format (explained more in the `response` headers section)
},
"body": {
"key1": "value1", // optional
"content": "raw text to be sent", // must always be present, even if empty
"encoding": "gzip" // required, but can be `identity` if no encoding is used
}
}
the jsontp 100 Continue request message
{
"jsontp": "1.0", // required and in the format `major.minor`
"type": "request",
"resource": "/path/to/resource",
"method": "GET",
"headers": {
"expect": "100-continue" // required
},
"body": {} // if not empty, it will be ignored
}
the jsontp 100 Continue response message
{
"jsontp": "1.0", // required and in the format `major.minor(-rcx)` (explained more in the `jsontp` versioning section)
"type": "response",
"status": {
"code": 100, // either 100, or a 4xx or 5xx error code
"formal-message": "CONTINUE", // corresponding status code
"human-message": "Ackknowledgement on the 100 Continue message"
},
"resource": "/path/to/resource",
"headers": {
"date": "2024-01-01T00:00:00Z+00:00", // required and always in this format. Should always be in UTC, but a compliant client should accept any timezone
"language": "en-US", // required and always in this format (explained more in the `response` headers section
},
"body": {} // should be empty, ignored if not
}
content requirements of certain key-value pairs
jsontp
- the
jsontpkey-value pair is always in the formatmajor.minor(-rcx) - this is explained more in the
jsontpversioning section - if the
jsontpversion is not supported, the server should respond with a505 HTTP Version Not Supportedstatus code - if the
jsontpversion is not provided, the server should respond with a400 Bad Requeststatus code
type
- must be either
requestorresponse - if the
typeis not supported, the server should respond with a400 Bad Requeststatus code
method
- the
methodkey-value pair is theHTTPmethod that the client is using to request the resource - the
methodkey-value pair can be any of the following:GET- standard request for the resource, which follows the
requestspecification exactly
- standard request for the resource, which follows the
POST- same as get, but the server must attempt to parse the body as a
&-separated list of key-value pairs. If not, that is no problem, and the server can proceed as usual
- same as get, but the server must attempt to parse the body as a
PUT- the
resourceis to be created or replaced with thecontentof thebody - if successful, the server should respond with a
201 Createdstatus code
- the
DELETE- the
resourceis to be deleted - the
bodyshould be ignored. - if successful, the server should respond with a
204 No Contentstatus code
- the
OPTIONS- the server should respond with a
200 OKstatus code, and thebodyshould contain akeyentitledallowed-methods, and thevalueshould be an array of the allowed methods. - It should ignore the
bodyof therequestmessage.
- the server should respond with a
- if the
methodis not supported, the server should respond with a405 Method Not Allowedstatus cod - a compliant server must implement at least the
GETandOPTIONSmethods
status
- the
statuskey-value pair is always anobject
code
- the
codekey-value pair is always a validHTTPstatus code (not 1xx).
formal-message
- the
formal-messagekey-value pair is always a validHTTPstatus message corresponding to thecode, for example,OKfor200,Not Foundfor404, etc. It is case-insensitive.
human-message
- the
human-messagekey-value pair is always a human-readable message, the contents of which is up to the discretion of the server, but should be helpful to the client. It is required, but can be a copy of theformal-messageif the server wishes.
resource
- the
resourcekey-value pair is the path to the resource that the client is requesting - the
resourcekey-value pair can be in any of the following formats:/path/to/resource/path/to/resource/path/to/resourcepath/to/resource/site.com/path/to/resourcejsontp://site.com/path/to/resource
- if the
resourceformat is not supported, the server should respond with a400 Bad Requeststatus code - if the
resourceis not found, the server should respond with a404 Not Foundstatus code
valid headers
- headers are always in the format
{ "key": "value" } - the
keyis always astring, and thevaluecan be any type barundefinedandnull - the
keyis always case-insensitive - the
valueis always case-sensitive - if an invalid header is provided, the server should respond with a
400 Bad Requeststatus code, however, this shouldn"t happen if the headerignore-invalid-headersis set totrue
headers in request and response messages
content-type - string
- the
MIMEtype of thebodyorcontentof the message - if the
MIMEtype is not supported, the server should respond with a415 Unsupported Media Typestatus code
accept - array or string
- the
MIMEtype of thebodyorcontentthat the client is willing to accept. - If the server cannot provide the
MIMEtype, it should respond with a415 Unsupported Media Typestatus code. - If there are multiple allowed
MIMEtypes, they should ideally be ajsonarray, but astringis also acceptable. - For example:
["text/html", "application/json", "application/xml"]or"text/html, application/json, application/xml"
request headers
accept-encoding - array or string
- the encoding that the client is willing to accept.
- If the server cannot provide the encoding, it should respond with a
412 Precondition Failedstatus code. - If there are multiple allowed encodings, they should ideally be a
jsonarray, but astringis also acceptable. - For example:
["gzip", "deflate", "br", "identity"]or"gzip, deflate, br, identity" - Allowed encodings are:
gzip,deflate,br,identity
accept-language - array or string
- the language that the client is willing to accept.
- If the server cannot provide the language, it should respond with a
406 Not Acceptablestatus code. - If there are multiple allowed languages, they should ideally be a
jsonarray, but astringis also acceptable. - For example:
["en-US", "en-GB", "en-CA"]or"en-US, en-GB, en-CA" - Each must first be a valid
ISO 639-1language code, followed by a hyphen, and then a validISO 3166 Alpha 2country code.
authorization - string
- the
authorizationheader is used to authenticate the client with the server. - the
authorizationheader should be in the format<token>, where<token>is the token that the server has provided to the client. - if the server cannot authenticate the client, it should respond with a
401 Unauthorizedstatus code.
cookies - object or string
- the
cookiesheader is used to send cookies to the server. - the
cookiesheader should be a smalljsonobject, with the keys being the cookie names, and the values being the cookie values. - if the server cannot accept the cookies, it should respond with a
400 Bad Requeststatus code. - example:
"cookies": {"cookie1": "value1", "cookie2": "value2"} - however, a compliant server will also accept cookies in the format
"cookie1=value1; cookie2=value2", as this is the format that theHTTPspecification uses, andjsontpis designed to be maximally compatible with existing standards.
if-modified-since - string in the strftime format (that found given in man 3 strftime) %Y-%m-%dT%H:%M:%SZ%z
- the
if-modified-sinceheader is used to tell the server that the client only wants the resource if it has been modified since the date provided. - the date should be in the format
%Y-%m-%dT%H:%M:%SZ%z, and should always be inUTC, but a compliant server should accept any timezone (although it should convert it toUTCbefore comparing it to the last modified date of the resource, which should always be inUTC). - if the server cannot provide the resource, it should respond with a
412 Precondition Failedstatus code. - if the server could provide the resource, but it has not been modified since the date provided, it should respond with a
304 Not Modifiedstatus code. - example value:
2024-01-01T00:00:00Z+0000(no colon is permitted in the timezone offset)
if-unmodified-since - string in the strftime format (that found given in man 3 strftime) %Y-%m-%dT%H:%M:%SZ%z
- the
if-unmodified-sinceheader is used to tell the server that the client only wants the resource if it has not been modified since the date provided. - the date should be in the format
%Y-%m-%dT%H:%M:%SZ%z, and should always be inUTC, but a compliant server should accept any timezone (although it should convert it toUTCbefore comparing it to the last modified date of the resource, which should always be inUTC). - if the server cannot provide the resource, it should respond with a
412 Precondition Failedstatus code. - if the server could provide the resource, but it has been modified since the date provided, it should respond with a
412 Precondition Failedstatus code. Unfortunately, theHTTPspecification does not provide a status code for this (3xx Modified), sojsontphas to use412 Precondition Failedinstead, as does theHTTPspecification. - example value:
2024-01-01T00:00:00Z+0000(no colon is permitted in the timezone offset)
expect - string (namely 100-continue)
- used to tell the server that the body will be sent in the next request, and not to time out quickly
- first, the client sends a message in the format specified above, then the server responds, again set out above. If the server does not support
100-continue, it must respond with a501 Not Implementedstatus code, at which point the connection will terminate. - if the server responds with
100 Continue, the client then sends its request in the usual fashion, containing all required fields, including headers. The client can modify the headers for this second request if they need to for some reason. -
ignore-invalid-headers-boolean - if the
ignore-invalid-headersheader is set totrue, the server should ignore any invalid headers, and not respond with a400 Bad Requeststatus code. - if the
ignore-invalid-headersheader is set tofalse, the server should respond with a400 Bad Requeststatus code if any invalid headers are provided.
response headers
date - string in the strftime format (that found given in man 3 strftime) %Y-%m-%dT%H:%M:%SZ%z
- the
dateheader is used to tell the client the date and time that the response was generated. - the date should be in the format
%Y-%m-%dT%H:%M:%SZ%z, and should always be inUTC, but a compliant client should accept any timezone. - if the server cannot provide the date, it should respond with a
500 Internal Server Errorstatus code. - this header is always present in a
responsemessage. - example value:
2024-01-01T00:00:00Z+0000(no colon is permitted in the timezone offset)
language - string
- the
languageheader is used to tell the client the language of the response. - the language must be in the format
ISO 639-1language code, followed by a hyphen, and then a validISO 3166 Alpha 2country code. - if the language does not match this format, the server should respond with a
400 Bad Requeststatus code. - if the server cannot provide the language, it should respond with a
500 Internal Server Errorstatus code.
set-cookies - object
- the
set-cookiesheader is used to tell the client to set cookies. - the
set-cookiesheader should be a smalljsonobject, with the keys being the cookie names, and the values being the cookie values. - example:
"set-cookies": {"cookie1": "value1", "cookie2": "value2"} - the server must respond with an
object, not astring, as theHTTPspecification does not allow for multipleset-cookieheaders to be sent in a single response, and sojsontpmust use ajsonobject to represent multiple cookies.
Other important requirements
jsontp versioning
- the
jsontpversion is in the formatmajor.minor(-rcx) - the
majorversion is incremented when there are breaking changes - the
minorversion is incremented when there are non-breaking changes (though this may never happen) - the
rcxis the release candidate number, and will only be present in a release candidate version, for example,1.0-rc1. It will not be present in a stable release. If it is present, it should be incremented with each release candidate, and omitted in the stable release. - the
jsontpversion is always in thejsontpkey-value pair, which is mandatory in alljsontpmessages. - if the
jsontpversion is not supported, the server should respond with a505 HTTP Version Not Supportedstatus code. - if the
jsontpversion is not provided, the server should respond with a400 Bad Requeststatus code.
errors on the server's side
- if the server encounters an error, it should respond with a
5xx Server Errorstatus code. - the
messagekey-value pair in thestatusobject should be a human-readable error message.
where to submit feature requests
- feature requests can be submitted to the
jsontp/paperGitHub repository, or can be emailed directly to thejsontpmaintainers, the email address of which is provided in thejsontpGitHub organization.
comments
- comments should not be included in any message, but a compliant implementation should allow them.
The "expect": "100-continue" header
- This is explained in the section on the valid client headers, but below is a nice mermaid diagram
sequenceDiagram
Client ->> Server: body-less request
Server ->> Client: 100 continue response (or 501, if so the connection ends)
Client ->> Server: full request
Server ->> Client: full response