Skip to content

Commit f1b780b

Browse files
committed
Add rate limiting
1 parent 5e4d320 commit f1b780b

File tree

3 files changed

+98
-28
lines changed

3 files changed

+98
-28
lines changed

EditorsDraft/edit.html

+23-13
Original file line numberDiff line numberDiff line change
@@ -1160,7 +1160,7 @@
11601160
<pre class="example" title="Order Creation: OrderQuote example success response" data-transform="dataExampleOrderQuoteCreationResponse">
11611161
</pre>
11621162

1163-
If there are any issues with the `orderedItem`s provided in the `OrderQuote`, the <a>Booking System</a> MUST respond with a `409 Conflict` response, with `error` details provided against each offending `OrderItem`. Note that `totalPaymentDue` and `totalTaxSpecification` MUST be calculated excluding any `OrderItem`s that include `error`s.
1163+
If there are any issues with the `orderedItem`s provided in the `OrderQuote`, the <a>Booking System</a> MUST respond with a `409 Conflict` response (as the error is expected to be resolved, and the request resubmitted, as per [[RFC2616]]), with `error` details provided against each offending `OrderItem`. Note that `totalPaymentDue` and `totalTaxSpecification` MUST be calculated excluding any `OrderItem`s that include `error`s.
11641164

11651165
<pre class="example" title="Order Creation: OrderQuote example OrderItem error response" data-transform="dataExampleOrderQuoteCreationOrderItemErrorResponse">
11661166
</pre>
@@ -1171,7 +1171,6 @@
11711171
</pre>
11721172

11731173

1174-
11751174
#### `Order`
11761175

11771176
A PUT request to the Order Creation endpoint of the <a>Booking System</a> with an object of type `Order` will create the `Order` and complete the booking from the point of the view of the <a>Booking System</a>.
@@ -1605,10 +1604,13 @@
16051604
| `IncompleteCustomerDetailsError` | 400 | If the `email` address of the customer is not supplied within a `schema:Person` object; or if the `customer` property supplied is not a valid `schema:Person` or `schema:Organization` object. |
16061605
| `IncompleteBrokerDetailsError` | 400 | If there is insufficient detail in the `schema:Organisation` object describing the <a>Broker</a>; or if the `broker` property supplied is not a valid schema:Organisation object. |
16071606
| `IncompletePaymentDetailsError` | 400 | If the `payment` property of the `Order` is missing or does not include an `identifier` or `paymentMethod`. |
1607+
| `OrderAlreadyExistsError` | 400 | If the UUID used for an `OrderQuote` already represents a completed Order. |
16081608

16091609

16101610
#### Order Creation - `OrderItem` errors
16111611

1612+
Note that all `OrderItem` errors for an `OrderQuote` request result in a `409 Conflict` response, as the error is expected to be resolved, and the request resubmitted, as per [[RFC2616]] section 10.4.10.
1613+
16121614
| Error Type | Status Code | Use Case |
16131615
|---------------------------------------------|-------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
16141616
| `IncompleteOrderItemError` | 409 | If there is a missing `acceptedOffer` or `orderedItem` property on the `schema:OrderItem`. |
@@ -1634,6 +1636,7 @@
16341636

16351637
| Error Type | Status Code | Use Case |
16361638
|---------------------------------------------|-------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
1639+
| `TemporarilyUnableToProduceOrderQuoteError` | 500 | If the <a>Booking System</a> is unable for technical reasons to produce an `OrderQuote` where the data provided to it is sufficient to allow it to do so. |
16371640
| `TemporarilyUnableToCreateOrderError` | 500 | If the <a>Booking System</a> is unable for technical reasons to create an `Order` where the data provided to it is sufficient to allow it to do so. |
16381641
| `TemporarilyUnableToUpdateOrderError` | 500 | If the <a>Booking System</a> is unable for technical reasons to update an `Order` (which includes attempting to PATCH for cancellation) where the data provided to it is sufficient to allow it to do so. |
16391642
| `TemporarilyUnableToDeleteOrderError` | 500 | If the <a>Booking System</a> is unable for technical reasons to delete an `Order` where the data provided to it is sufficient to allow it to do so |
@@ -1648,6 +1651,9 @@
16481651
| `NotFoundError` | 404 | Where a <a>Booking System</a> does not have the generic resource specified. |
16491652
| `MethodNotAllowed` | 405 | Where a <a>Booking System</a> does not recognise a specific HTTP method for the endpoint requested with that specific HTTP verb. |
16501653
| `GoneError` | 410 | Where an `Order` has been soft-deleted by an Order Deletion request. |
1654+
| `TooManyRequestsError` | 429 | Where the <a>Booking System</a> is rate-limiting the <a>Broker</a>. |
1655+
1656+
16511657

16521658

16531659
</section>
@@ -1719,19 +1725,23 @@
17191725

17201726
## Errors
17211727

1722-
Error responses MUST be served using an appropriate HTTP 4XX status code or HTTP
1723-
5XX status code specified in the model.
1728+
Error responses MUST be served using an appropriate HTTP 4XX status code or HTTP 5XX status code specified in the model.
17241729

1725-
All error responses from this API MUST be returned in a JSON-LD format using a
1726-
content type of `application/vnd.openactive+json`, and optionally any version
1727-
parameters, and include at least one `OpenBookingError` object.
1730+
All error responses from this API MUST be returned in a JSON-LD format subclass of the `OpenBookingError` using a content type of `application/vnd.openactive+json` (optionally including any version parameters).
17281731

1729-
<pre class="example" title="Error response format">
1730-
{
1731-
"@context": "https://openactive.io/",
1732-
"type": "IncompleteCustomerDetailsError",
1733-
"description": "No customer details supplied"
1734-
}
1732+
<pre class="example" title="Error response example" data-transform="dataExampleErrorResponse">
1733+
</pre>
1734+
1735+
1736+
## Rate Limiting
1737+
1738+
The <a>Booking System</a> MAY choose to apply rate limiting for each unique set of authentication credentials, in which case they MUST adhere to the following.
1739+
1740+
All rate-limited responses from this API MUST return a JSON-LD format `TooManyRequestsError` object using a content type of `application/vnd.openactive+json` (optionally including any version parameters).
1741+
1742+
The response MUST also include the `Retry-After` HTTP Header with a value set to the number of seconds after which the <a>Broker</a> SHOULD retry as per [[RFC2616]] section 14.37.
1743+
1744+
<pre class="example" title="Rate limited response example" data-transform="dataExampleRateLimitResponse">
17351745
</pre>
17361746

17371747

EditorsDraft/examples.js

+30
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,39 @@ function dataExampleOrderQuoteCreationOrderItemErrorResponse(utils, content) {
4646
}
4747

4848
function dataExampleOrderQuoteCreationErrorResponse(utils, content) {
49+
return generateResponse("500 Internal Server Error", null, OPERATIONS_MEDIA_TYPE, {
50+
"@context": CONTEXT,
51+
"type": "TemporarilyUnableToProduceOrderQuoteError",
52+
"description": "Temporary error occurred in the database"
53+
});
54+
}
55+
56+
function dataExampleErrorResponse(utils, content) {
4957
return generateResponse("400 Bad Request", null, OPERATIONS_MEDIA_TYPE, {
5058
"@context": CONTEXT,
5159
"type": "IncompleteCustomerDetailsError",
5260
"description": "No customer details supplied"
5361
});
5462
}
5563

64+
function dataExampleRateLimitResponse(utils, content) {
65+
return generateResponseWithHeaders("429 Too Many Requests", null, OPERATIONS_MEDIA_TYPE,
66+
"Retry-After: 8", {
67+
"@context": CONTEXT,
68+
"type": "TooManyRequestsError",
69+
"description": "Rate Limit Reached. Retry in 8 seconds."
70+
});
71+
}
72+
73+
//TODO: Include rate limiting scheme!! [DONE]
74+
75+
76+
//TODO: A page on the OA docs site summarising what you can do and can't do with the OpenActive booking specification (to talk through with operators)
77+
//TODO: Read Iain's slides and stephenage notes from a while back to check we've not missed anything
78+
79+
80+
//TODO: Allow for a "lite" signup-only / no cancellation version to exist? No point, it's too simple to need a spec for that...?
81+
5682
//TODO: Allow multiple errors only for order creation
5783

5884
//TODO: Should we have a separate type for OrderRequest to better define the required params?
@@ -645,6 +671,10 @@ function generateRequest(verb, path, mediaType, json) {
645671
return generateRequestHeaders(verb, path, mediaType) + (json ? "\n\n" + jsonStringify(json) : "");
646672
}
647673

674+
function generateResponseWithHeaders(responseCode, path, mediaType, headers, json) {
675+
return generateResponseHeaders(responseCode, path, mediaType) + "\n" + headers + (json ? "\n\n" + jsonStringify(json) : "");
676+
}
677+
648678
function generateResponse(responseCode, path, mediaType, json) {
649679
return generateResponseHeaders(responseCode, path, mediaType) + (json ? "\n\n" + jsonStringify(json) : "");
650680
}

0 commit comments

Comments
 (0)