Examples of CNP requests and responses

Examples

Request

cnp/0.4 contnet.org/spec/cnp0.4/

Interpretation:

{
	"version": [0, 4],
	"intent": "contnet.org/spec/cnp0.4/",
	"parameters": {},
	"body": "",
	"request": {
		"host": "contnet.org",
		"path": "/spec/cnp0.4/"
	}
}

HTTP equivalent:

GET /spec/cnp0.4/ HTTP/1.0
Host: contnet.org

Explanation:

By default, all CNP requests are equivalent to HTTP GET requests. The request header contains the CNP version string and the intent, which consists of the target hostname (including port if non-default) and the path. No parameters are necessary.

Due to legacy reasons, HTTP does not include the hostname in the method line of the header. Because of that, HTTP/1.1 requires the Host header. In order to allow requests without parameters, the hostname is a part of the core header.

Request with data

cnp/0.4 example.net/upload/ type=text/plain length=10 name=qweasd.txt
qweasd
zxc

Interpretation:

{
	"version": [0, 4],
	"intent": "example.net/upload/",
	"parameters": {
		"length": "10",
		"name": "qweasd.txt",
		"type": "text/plain"
	},
	"body": "qweasd\nzxc",
	"request": {
		"host": "example.net",
		"path": "/upload/"
	}
}

HTTP equivalent (though this would likely be a multipart/form-data request instead):

POST /upload/ HTTP/1.0
Content-Disposition: attachment; name="qweasd.txt"
Content-Length: 10
Content-Type: text/plain
Host: example.net

qweasd
zxc

Explanation:

Any CNP request with nonempty body is equivalent to a HTTP POST request. The distinction between GET and POST on the verb level is not very useful, as the only real protocol difference is that one can contain body data and the other can't. Currently, any CNP request that contains a body must have the length parameter set to a non-zero value, so that is sufficient to distinguish between a data-less fetch and a non-idempotent data submission request.

If-modified request

cnp/0.4 contnet.org/spec/cnp0.4/ if_modified=2015-03-04T08:38:01Z

Interpretation:

{
	"version": [0, 4],
	"intent": "contnet.org/spec/cnp0.4/",
	"parameters": {
		"if_modified": "2015-03-04T08:38:01Z"
	},
	"body": "",
	"request": {
		"host": "contnet.org",
		"path": "/spec/cnp0.4/"
	}
}

HTTP equivalent:

GET /spec/cnp0.4/ HTTP/1.0
Host: contnet.org
If-Modified-Since: Wed, 04 Mar 2015 08:38:01 GMT

Explanation:

CNP's modified/if_modified/not_modified are equivalent to HTTP Last-Modified/If-Modified-Since/304 Not Modified. The main difference is that CNP uses cleaner RFC 3339 timestamps instead of the RFC 2616 date format.

Response

cnp/0.4 ok modified=2015-03-04T08:38:01Z time=2015-03-06T09:58:44Z name=0.4.cnm type=text/cnm
TODO

Interpretation:

{
	"version": [0, 4],
	"intent": "ok",
	"parameters": {
		"modified": "2015-03-04T08:38:01Z",
		"name": "0.4.cnm",
		"time": "2015-03-06T09:58:44Z",
		"type": "text/cnm"
	},
	"body": "TODO"
}

HTTP equivalent:

HTTP/1.0 200 OK
Content-Type: text/cnm
Content-Disposition: inline; filename="0.4.cnm"
Date: Fri, 06 Mar 2015 09:58:44 GMT
Last-Modified: Wed, 04 Mar 2015 08:38:01 GMT

TODO

Explanation:

Instead of HTTP status codes, CNP responses use simple verbs. CNP aims to avoid having too many different response types, which only leads to more complicated implementations; instead, the CNP response intent defines how the message is handled (response containing requested content, a redirect, an error, ...) and the meaning of that specific response type can be more specifically defined by parameters.

CNP also supports providing the filename of the delivered content in a well-defined manner even when the file is displayed inline. Different HTTP implementations expect different encodings, such as RFC 5987, percent-encoded UTF-8 or even raw UTF-8, in the filename (or even filename*) parameter of the Content-Disposition header, which makes sending non-ASCII filenames in a portable way nontrivial.

Redirect response

cnp/0.4 redirect location=example.net/foo/bar/

Interpretation:

{
	"version": [0, 4],
	"intent": "redirect",
	"parameters": {
		"location": "example.net/foo/bar"
	},
	"body": "",
	"response": {
		"redirect_host": "example.net",
		"redirect_path": "/foo/bar/"
	}
}

HTTP equivalent:

HTTP/1.0 302 Found
Location: cnp://example.net/foo/bar/

Explanation:

HTTP has at least five different response codes for redirects, which differ in how long the redirect should be cached and whether the data should be resent to the new address.

In CNP, each redirect is assumed to be temporary and should not be cached unless another header (such a potential future equivalent to HTTP Max-Age) allows that. The new request should always be a blank request (without body data), equivalent to a completely new request issued to the provided host and path. Submitting data to a chain of redirects is wasteful and risks leaking data to unintended recipients.

The location parameter uses the same syntax as the CNP request intent, so a valid location can be reused for the new request without modification. The host part of the intent must be resolved again and the request sent to the new host.

Not modified response

cnp/0.4 not_modified modified=2015-03-04T08:38:01Z time=2015-03-06T09:59:22Z

Interpretation:

{
	"version": [0, 4],
	"intent": "not_modified",
	"parameters": {
		"modified": "2015-03-04T08:38:01Z",
		"time": "2015-03-06T09:59:22Z"
	},
	"body": ""
}

HTTP equivalent:

HTTP/1.0 304 Not Modified
Date: Fri, 06 Mar 2015 09:59:22 GMT
Last-Modified: Wed, 04 Mar 2015 08:38:01 GMT

Explanation:

not_modified is equivalent to a HTTP 304 Not Modified response. No parameters are necessary, but may be provided regardless. The time parameter is informative and may be used with modified to display the page age to the user.

Error response

cnp/0.4 error reason=not_found type=text/plain length=57
The requested path /foo/bar was not found on this server.

Interpretation:

{
	"version": [0, 4],
	"intent": "error",
	"parameters": {
		"length": "57",
		"reason": "not_found",
		"type": "text/plain"
	},
	"body": "The requested path /foo/bar was not found on this server."
}

HTTP equivalent:

HTTP/1.0 404 Not Found
Content-Length: 57
Content-Type: text/plain

The requested path /foo/bar was not found on this server.

Explanation:

A CNP error response represents any response which is not a direct reply to the request. All HTTP 4XX and 5XX status codes would fit in it, distinguished by the response parameter.