spec: Revisit spacing and indentation.

Co-authored-by: pancho horrillo <pedrofelipe.horrillo@bbva.com>
This commit is contained in:
Roberto Abdelkader Martínez Pérez
2019-05-23 09:56:35 +02:00
parent 23adf2ea50
commit 1eb0500b92
+131 -189
View File
@@ -1,5 +1,6 @@
# Kapow! # Kapow!
## Why? ## Why?
Because we think that: Because we think that:
@@ -105,14 +106,15 @@ Kapow! server interacts with the outside world only through its HTTP API. Any
program making the correct HTTP request to a Kapow! server, can change its program making the correct HTTP request to a Kapow! server, can change its
behavior. behavior.
## Design Principles ## Design Principles
* All requests and responses will leverage JSON as the data encoding method. * All requests and responses will leverage JSON as the data encoding method.
* The API calls responses will have two distinct parts: * The API calls responses will have two distinct parts:
* The HTTP status code (e.g., 400, Bad Request). The target audience of this * The HTTP status code (e.g., `400`, which is a bad request). The target
information is the client code. The client can thus use this information to audience of this information is the client code. The client can thus use
control the program flow. this information to control the program flow.
* The JSON-encoded message. The target audience in this case is the human * The JSON-encoded message. The target audience in this case is the human
operating the client. The human can use this information to make a operating the client. The human can use this information to make a
decision on how to proceed. decision on how to proceed.
@@ -126,59 +128,42 @@ Let's illustrate these ideas with an example: TODO
FIXME: consider what to do when deleting objects. Isn't it too much to FIXME: consider what to do when deleting objects. Isn't it too much to
return the list of all deleted objects in such a request? return the list of all deleted objects in such a request?
## API elements
## API Elements
### Servers ### Servers
TODO: Define servers' API TODO: Define servers' API
### Routes ### Routes
Routes are the mechanism that allows Kapow! to find the correct program to Routes are the mechanism that allows Kapow! to find the correct program to
respond to an external event (e.g. an incomming HTTP request). respond to an external event (e.g. an incomming HTTP request).
#### List routes #### List routes
Returns JSON data about the current routes. Returns JSON data about the current routes.
* **URL** * **URL**: `/routes`
* **Method**: `GET`
`/routes` * **Success Response**:
* **Method**
`GET`
* **Success Response**
* **Code**: `200 OK`<br /> * **Code**: `200 OK`<br />
**Content**: TODO **Content**: TODO
* **Sample Call**: TODO
* **Notes**: Currently all routes are returned; in the future, a filter may be accepted.
* **Sample Call**
TODO
* **Notes**
Currently all routes are returned; in the future, a filter may be accepted.
#### Append route #### Append route
Accepts JSON data that defines a new route to be appended to the current routes. Accepts JSON data that defines a new route to be appended to the current routes.
* **URL**
`/routes`
* **Method**
`POST`
* **URL**: `/routes`
* **Method**: `POST`
* **Header**: `Content-Type: application/json` * **Header**: `Content-Type: application/json`
* **Data Params**:<br />
* **Data Params**
* **Content**:
``` ```
{ {
"method": "GET", "method": "GET",
@@ -187,58 +172,41 @@ Returns JSON data about the current routes.
"command": "echo Hello World | response /body" "command": "echo Hello World | response /body"
} }
``` ```
* **Success Responses**:
* **Success Response**
* **Code**: `200 OK`<br /> * **Code**: `200 OK`<br />
**Header**: `Content-Type: application/json`<br /> **Header**: `Content-Type: application/json`<br />
**Content**: **Content**:<br />
``` ```
{ {
"method": "GET", "method": "GET",
"url_pattern": "/hello", "url_pattern": "/hello",
"entrypoint": null, "entrypoint": null,
"command": "echo Hello World | response /body", "command": "echo Hello World | response /body",
"index": 0 "index": 0
} }
``` ```
* **Error Responses**:
* **Error Response**
* **Code**: `400 Bad Request`<br /> * **Code**: `400 Bad Request`<br />
**Header**: `Content-Type: application/json`<br /> **Header**: `Content-Type: application/json`<br />
**Content**: `{ "error": "Malformed JSON." }` **Content**: `{ "error": "Malformed JSON." }`
* **Code**: `400 Bad Request`<br /> * **Code**: `400 Bad Request`<br />
**Header**: `Content-Type: application/json`<br /> **Header**: `Content-Type: application/json`<br />
**Content**: `{ "error": "Mandatory field(s) not provided." }` **Content**: `{ "error": "Mandatory field(s) not provided." }`
* **Sample Call**: TODO
* **Sample Call** * **Notes**:
TODO
* **Notes**
* A successful request will yield a response containing all the effective * A successful request will yield a response containing all the effective
parameters that were applied. parameters that were applied.
#### Insert a route #### Insert a route
Accepts JSON data that defines a new route to be inserted at the specified Accepts JSON data that defines a new route to be inserted at the specified
index to the current routes. index to the current routes.
* **URL** * **URL**: `/routes`
* **Method**: `PUT`
`/routes`
* **Method**
`PUT`
* **Header**: `Content-Type: application/json` * **Header**: `Content-Type: application/json`
* **Data Params**:<br />
* **Data Params**
* **Content**:
``` ```
{ {
"method": "GET", "method": "GET",
@@ -247,73 +215,52 @@ TODO
"command": "echo Hello World | response /body", "command": "echo Hello World | response /body",
} }
``` ```
* **Success Responses**:
* **Success Responses**
* **Code**: `200 OK`<br /> * **Code**: `200 OK`<br />
**Header**: `Content-Type: application/json`<br /> **Header**: `Content-Type: application/json`<br />
**Content**: **Content**:<br />
``` ```
{ {
"method": "GET", "method": "GET",
"url_pattern": "/hello", "url_pattern": "/hello",
"entrypoint": null, "entrypoint": null,
"command": "echo Hello World | response /body", "command": "echo Hello World | response /body",
"index": 0 "index": 0
} }
``` ```
* **Error Responses**:
* **Error Responses**
* **Code**: `400 Bad Request`<br /> * **Code**: `400 Bad Request`<br />
**Header**: `Content-Type: application/json`<br /> **Header**: `Content-Type: application/json`<br />
**Content**: `{ "error": "Malformed JSON." }` **Content**: `{ "error": "Malformed JSON." }`
* **Code**: `400 Bad Request`<br /> * **Code**: `400 Bad Request`<br />
**Header**: `Content-Type: application/json`<br /> **Header**: `Content-Type: application/json`<br />
**Content**: `{ "error": "Mandatory field(s) not provided." }` **Content**: `{ "error": "Mandatory field(s) not provided." }`
* **Sample Call**: TODO
* **Sample Call** * **Notes**:
TODO
* **Notes**
* Route numbering starts at zero. * Route numbering starts at zero.
* When `index` is not provided or is less than 0 the route will be inserted * When `index` is not provided or is less than 0 the route will be inserted
first, effectively making it index 0. first, effectively making it index 0.
* Conversely when `index` is greater than the number of entries on the route * Conversely, when `index` is greater than the number of entries on the route
table it will be inserted last. table, it will be inserted last.
* A successful request will yield a response containing all the effective * A successful request will yield a response containing all the effective
parameters that were applied. parameters that were applied.
#### Delete a route #### Delete a route
Removes the route identified by `:id`. Removes the route identified by `:id`.
* **URL** * **URL**: `/routes/:id`
* **Method**: `DELETE`
`/routes/:id` * **Success Response**:
* **Method**
`DELETE`
* **Success Response**
* **Code**: `200 OK`<br /> * **Code**: `200 OK`<br />
**Content**: TODO **Content**: TODO
* **Error Response**:
* **Error Response**
* **Code**: `404 Not Found`<br /> * **Code**: `404 Not Found`<br />
**Header**: `Content-Type: application/json`<br /> **Header**: `Content-Type: application/json`<br />
**Content**: `{ "error": "Unknown route", "route_id": "{{ :id }}" }` **Content**: `{ "error": "Unknown route", "route_id": "{{ :id }}" }`
* **Sample Call**: TODO
* **Notes**:
* **Sample Call**
TODO
* **Notes**
### Handlers ### Handlers
@@ -350,31 +297,29 @@ following keys:
└──── <entry> └──── <entry>
``` ```
#### Example Keys #### Example Keys
1. Read the request URL path. - Read the request URL path.
- Scenario: Request URL is `http://localhost:8080/example?q=foo&r=bar` - Scenario: Request URL is `http://localhost:8080/example?q=foo&r=bar`
- Key: `/request/path` - Key: `/request/path`
- Access: Read-Only - Access: Read-Only
- Returned Value: `/example?q=foo&r=bar` - Returned Value: `/example?q=foo&r=bar`
- Comment: That would provide read-only access to the request URL path. - Comment: That would provide read-only access to the request URL path.
- Read an specific URL parameter.
2. Read an specific URL parameter. - Scenario: Request URL is `http://localhost:8080/example?q=foo&r=bar`
Scenario: Request URL is `http://localhost:8080/example?q=foo&r=bar` - Key: `/request/params/q`
Key: `/request/params/q` - Access: Read-Only
Access: Read-Only - Returned Value: `foo`
Returned Value: `foo` - Comment: That would provide read-only access to the request URL parameter `q`.
Comment: That would provide read-only access to the request URL parameter `q`. - Obtain the `Content-Type` header of the request.
- Scenario: A POST request with a JSON body and the header `Content-Type` set to `application/json`.
3. Obtain the `Content-Type` header of the request. - Key: `/request/headers/Content-Type`
Scenario: A POST request with a JSON body and the header `Content-Type` set to `application/json`. - Access: Read-Only
Key: `/request/headers/Content-Type` - Returned Value: `application/json`
Access: Read-Only - Comment: That would provide read-only access to the value of the request header `Content-Type`.
Returned Value: `application/json` - Read a field from a form.
Comment: That would provide read-only access to the value of the request header `Content-Type`. - Scenario: A request generated by submitting this form:<br />
4. Read a field from a form.
Scenario: A request generated by submitting this form:
``` ```
<form method="post"> <form method="post">
First name:<br> First name:<br>
@@ -384,84 +329,67 @@ following keys:
<input type="submit" value="Submit"> <input type="submit" value="Submit">
</form> </form>
``` ```
Key: `/request/form/firstname` - Key: `/request/form/firstname`
Access: Read-Only - Access: Read-Only
Returned Value: `Jane` - Returned Value: `Jane`
Comment: That would provide read-only access to the value of the field `firstname` of the form. - Comment: That would provide read-only access to the value of the field `firstname` of the form.
- Set the response status code.
5. Set the response status code. - Scenario: A request is being attended.
Scenario: A request is being attended. - Key: `/response/status`
Key: `/response/status` - Access: Write-Only
Access: Write-Only - Acceptable Value: A 3-digit integer. Must match `[0-9]{3}`.
Acceptable Value: A 3-digit integer. Must match `[0-9]{3}`. - Default Value: `200`
Default Value: 200 - Comment: It is customary to use the HTTP status code as defined at [RFC2616](https://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.1.1).
Comment: It is customary to use the HTTP status code as defined at [https://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.1.1](RFC2616). - Set the response body.
- Scenario: A request is being attended.
6. Set the response body. - Key: `/response/body`
Scenario: A request is being attended. - Access: Write-Only
Key: `/response/body` - Acceptable Value: Any string of bytes.
Access: Write-Only - Default Value: N/A
Acceptable Value: Any string of bytes. - Comment: For media types other than `application/octet-stream` you should specify the appropiate `Content-Type` header.
Default Value: N/A
Comment: For media types other than `application/octet-stream` you should
specify the appropiate `Content-Type` header.
**Note**: Parameters under `request` are read-only and, conversely, parameters under **Note**: Parameters under `request` are read-only and, conversely, parameters under
`response` are write-only. `response` are write-only.
#### Get handler key #### Get handler key
Returns the value of the requested key, or an error if the key doesn't exist or is invalid. Returns the value of the requested key, or an error if the key doesn't exist or is invalid.
* **URL**
`/handlers/{:handler_id}{:key}`
* **Method**
`GET`
* **URL Params**
FIXME: We think that here should be options to cook the value in some way, or get it raw.
* **Success Responses**
* **URL**: `/handlers/{:handler_id}{:key}`
* **Method**: `GET`
* **URL Params**: FIXME: We think that here should be options to cook the value in some way, or get it raw.
* **Success Responses**:
* **Code**: `200 OK`<br /> * **Code**: `200 OK`<br />
**Header**: `Content-Type: application/octet-stream`<br /> **Header**: `Content-Type: application/octet-stream`<br />
**Content**: The value for that key. Note that it may be empty. **Content**: The value for that key. Note that it may be empty.
* **Error Responses**:
* **Error Responses** * Key is invalid.<br />
* Key is invalid.
**Code**: `400 Bad Request`<br /> **Code**: `400 Bad Request`<br />
**Content**: None.<br /> **Content**: None.<br />
**Notes**: Check the list of valid keys at the top of this section. **Notes**: Check the list of valid keys at the top of this section.
* Entry not found.<br />
* Entry not found.
**Code**: `404 Not Found`<br /> **Code**: `404 Not Found`<br />
**Content**: None.<br /> **Content**: None.<br />
* **Sample Call**: TODO
* **Sample Call** * **Notes**: TODO
TODO
* **Notes**
#### Overwrite the value for a handler key #### Overwrite the value for a handler key
* **URL**
* **Method** * **URL**:
POST * **Method**: `POST`
* **URL Params** * **URL Params**:
* **Data Params** * **Data Params**:
* **Success Response** * **Success Response**:
* **Error Response** * **Error Response**:
* **Sample Call** * **Sample Call**:
* **Notes** * **Notes**:
## Usage Example ## Usage Example
## Test Suite Notes ## Test Suite Notes
The test suite is located on [blebleble] directory. The test suite is located on [blebleble] directory.
@@ -469,32 +397,46 @@ You can run it by ...
# Framework # Framework
## Commands ## Commands
Any compliant implementation of Kapow! must provide these commands: Any compliant implementation of Kapow! must provide these commands:
### `kapow` ### `kapow`
This implements the server, yaddayadda This implements the server, yaddayadda
#### Example #### Example
### `kroute` ### `kroute`
TODISCUSS: maybe consider using `kapow route` instead TODISCUSS: maybe consider using `kapow route` instead
#### Example #### Example
### `request` ### `request`
#### Example #### Example
### `response` ### `response`
#### Example #### Example
## Full-fledged example (TODO: express it more simply)
## An End-to-End Example
## Test Suite Notes ## Test Suite Notes
# Server # Server