Skip to content

Commit 8a3ea48

Browse files
NRL-512 An unsupported content-type will respond with 415, rename terraform file, add more tests
1 parent 8c024b3 commit 8a3ea48

File tree

7 files changed

+137
-19
lines changed

7 files changed

+137
-19
lines changed

terraform/infrastructure/modules/api_gateway/api_gateway.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ resource "aws_api_gateway_deployment" "api_gateway_deployment" {
5353
redeployment = sha1(jsonencode(aws_api_gateway_rest_api.api_gateway_rest_api.body))
5454
resource_change = "${md5(file("${path.module}/api_gateway.tf"))}"
5555
capabilities = sha1(var.capability_statement_content)
56-
method_responses_change = md5(file("${path.module}/method_responses.tf"))
56+
head_responses_change = md5(file("${path.module}/head_responses.tf"))
5757
parent_api_gateway_change = md5(file("${path.module}/../../api_gateway.tf"))
5858
}
5959

terraform/infrastructure/modules/api_gateway/method_responses.tf renamed to terraform/infrastructure/modules/api_gateway/head_responses.tf

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,11 @@ resource "aws_api_gateway_method" "head_method" {
2020
resource "aws_api_gateway_integration" "head_integration" {
2121
for_each = var.endpoint_allowed_methods
2222

23-
rest_api_id = aws_api_gateway_rest_api.api_gateway_rest_api.id
24-
resource_id = data.aws_api_gateway_resource.resource[each.key].id
25-
http_method = aws_api_gateway_method.head_method[each.key].http_method
26-
type = "MOCK"
27-
# passthrough_behavior = "WHEN_NO_TEMPLATES"
28-
passthrough_behavior = "WHEN_NO_MATCH"
23+
rest_api_id = aws_api_gateway_rest_api.api_gateway_rest_api.id
24+
resource_id = data.aws_api_gateway_resource.resource[each.key].id
25+
http_method = aws_api_gateway_method.head_method[each.key].http_method
26+
type = "MOCK"
27+
passthrough_behavior = "WHEN_NO_TEMPLATES"
2928

3029
request_templates = {
3130
"application/json" = <<-EOF
Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,66 @@
11
Feature: Consumer - HEAD Requests
22

3-
Scenario: DocumentReference with HEAD fails
3+
Scenario Outline: DocumentReference with HEAD fails (Content-Type: <content_type>)
44
Given the application 'DataShare' (ID 'z00z-y11y-x22x') is registered to access the API
5-
When consumer 'RX898' sends HEAD request to 'DocumentReference' endpoint
5+
When consumer 'RX898' sends HEAD request to 'DocumentReference' endpoint with headers:
6+
| header | value |
7+
| Content-Type | <content_type> |
68
Then the response status code is 405
79
And the response has an empty body
810
And the Allow header is 'GET'
11+
And the Content-Length header is '0'
912

10-
Scenario: DocumentReference/{id} with HEAD fails
13+
Examples:
14+
| content_type |
15+
| application/json |
16+
| application/json+fhir |
17+
| application/fhir+json |
18+
19+
Scenario Outline: DocumentReference/{id} with HEAD fails (Content-Type: <content_type>)
1120
Given the application 'DataShare' (ID 'z00z-y11y-x22x') is registered to access the API
12-
When consumer 'RX898' sends HEAD request to 'DocumentReference/random-id' endpoint
21+
When consumer 'RX898' sends HEAD request to 'DocumentReference/random-id' endpoint with headers:
22+
| header | value |
23+
| Content-Type | <content_type> |
1324
Then the response status code is 405
1425
And the response has an empty body
1526
And the Allow header is 'GET'
27+
And the Content-Length header is '0'
28+
29+
Examples:
30+
| content_type |
31+
| application/json |
32+
| application/json+fhir |
33+
| application/fhir+json |
34+
35+
Scenario Outline: DocumentReference with HEAD fails with 415 with unsupported (Content-Type: <content_type>)
36+
Given the application 'DataShare' (ID 'z00z-y11y-x22x') is registered to access the API
37+
When consumer 'RX898' sends HEAD request to 'DocumentReference' endpoint with headers:
38+
| header | value |
39+
| Content-Type | <content_type> |
40+
Then the response status code is 415
41+
And the Content-Type header is 'application/json'
42+
And the Content-Length header is '0'
43+
And the Allow header is not present
44+
45+
Examples:
46+
| content_type |
47+
| application/notsupported |
48+
| application/helloworld |
49+
| application/harold |
50+
51+
Scenario Outline: DocumentReference/{id} with HEAD fails (Content-Type: <content_type>)
52+
Given the application 'DataShare' (ID 'z00z-y11y-x22x') is registered to access the API
53+
When consumer 'RX898' sends HEAD request to 'DocumentReference/random-id' endpoint with headers:
54+
| header | value |
55+
| Content-Type | <content_type> |
56+
Then the response status code is 415
57+
And the response has an empty body
58+
And the Content-Type header is 'application/json'
59+
And the Content-Length header is '0'
60+
And the Allow header is not present
61+
62+
Examples:
63+
| content_type |
64+
| application/notsupported |
65+
| application/helloworld |
66+
| application/harold |
Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,63 @@
11
Feature: Producer - HEAD Requests
22

3-
Scenario: DocumentReference with HEAD fails
3+
Scenario Outline: DocumentReference with HEAD fails (Content-Type: <content_type>)
44
Given the application 'DataShare' (ID 'z00z-y11y-x22x') is registered to access the API
5-
When producer 'RX898' sends HEAD request to 'DocumentReference' endpoint
5+
When producer 'RX898' sends HEAD request to 'DocumentReference' endpoint with headers:
6+
| header | value |
7+
| Content-Type | <content_type> |
68
Then the response status code is 405
79
And the response has an empty body
810
And the Allow header is 'GET,POST'
911

10-
Scenario: DocumentReference/{id} with HEAD fails
12+
Examples:
13+
| content_type |
14+
| application/json |
15+
| application/json+fhir |
16+
| application/fhir+json |
17+
18+
Scenario Outline: DocumentReference/{id} with HEAD fails (Content-Type: <content_type>)
1119
Given the application 'DataShare' (ID 'z00z-y11y-x22x') is registered to access the API
12-
When producer 'RX898' sends HEAD request to 'DocumentReference/random-id' endpoint
20+
When producer 'RX898' sends HEAD request to 'DocumentReference/random-id' endpoint with headers:
21+
| header | value |
22+
| Content-Type | <content_type> |
1323
Then the response status code is 405
1424
And the response has an empty body
1525
And the Allow header is 'GET,PUT,DELETE'
26+
27+
Examples:
28+
| content_type |
29+
| application/json |
30+
| application/json+fhir |
31+
| application/fhir+json |
32+
33+
Scenario Outline: DocumentReference with HEAD fails with 415 with unsupported (Content-Type: <content_type>)
34+
Given the application 'DataShare' (ID 'z00z-y11y-x22x') is registered to access the API
35+
When producer 'RX898' sends HEAD request to 'DocumentReference' endpoint with headers:
36+
| header | value |
37+
| Content-Type | <content_type> |
38+
Then the response status code is 415
39+
And the Content-Type header is 'application/json'
40+
And the response has an empty body
41+
And the Allow header is not present
42+
43+
Examples:
44+
| content_type |
45+
| application/notsupported |
46+
| application/helloworld |
47+
| application/harold |
48+
49+
Scenario Outline: DocumentReference/{id} with HEAD fails with 415 with unsupported (Content-Type: <content_type>)
50+
Given the application 'DataShare' (ID 'z00z-y11y-x22x') is registered to access the API
51+
When producer 'RX898' sends HEAD request to 'DocumentReference/random-id' endpoint with headers:
52+
| header | value |
53+
| Content-Type | <content_type> |
54+
Then the response status code is 415
55+
And the Content-Type header is 'application/json'
56+
And the response has an empty body
57+
And the Allow header is not present
58+
59+
Examples:
60+
| content_type |
61+
| application/notsupported |
62+
| application/helloworld |
63+
| application/harold |

tests/features/steps/2_request.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,12 +249,19 @@ def producer_search_document_reference_step(context: Context, ods_code: str):
249249
)
250250

251251

252-
@when("{consumer_or_producer} '{ods_code}' sends HEAD request to '{endpoint}' endpoint")
252+
@when(
253+
"{consumer_or_producer} '{ods_code}' sends HEAD request to '{endpoint}' endpoint with headers"
254+
)
253255
def consumer_head_request_step(
254256
context: Context, consumer_or_producer: str, ods_code: str, endpoint: str
255257
):
258+
if not context.table:
259+
raise ValueError("No headers table provided")
260+
261+
headers = {row["header"]: row["value"] for row in context.table}
262+
256263
if consumer_or_producer == "producer":
257264
client = producer_client_from_context(context, ods_code)
258265
elif consumer_or_producer == "consumer":
259266
client = consumer_client_from_context(context, ods_code)
260-
context.response = client.head(endpoint)
267+
context.response = client.head(endpoint, headers=headers)

tests/features/steps/3_assert.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,17 @@ def assert_location_header(context: Context, header_name: str):
347347
context.pointer_id = generated_id
348348

349349

350+
@then("the {header_name} header is not present")
351+
def assert_header_not_present(context: Context, header_name: str):
352+
header_value = context.response.headers.get(header_name)
353+
assert header_value is None, format_error(
354+
f"Header {header_name} should not be present",
355+
"not present",
356+
header_value,
357+
context.response.text,
358+
)
359+
360+
350361
@then("the {header_name} header starts with '{starts_with}'")
351362
def assert_header_starts_with(context: Context, header_name: str, starts_with: str):
352363
header_value = context.response.headers.get(header_name)

tests/utilities/api_clients.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,11 +196,12 @@ def search_post(
196196
def head(
197197
self,
198198
endpoint: str,
199+
headers: dict[str, str] | None = None,
199200
extra_params: dict[str, str] | None = None,
200201
) -> Response:
202+
headers = {**(headers or {}), **self.request_headers}
201203
params = {**(extra_params or {})}
202204
url = f"{self.api_url}/{endpoint}"
203-
headers = {**self.request_headers, "Content-Type": "application/json"}
204205
return requests.head(
205206
url,
206207
params=params,
@@ -381,11 +382,12 @@ def read_capability_statement(self) -> Response:
381382
def head(
382383
self,
383384
endpoint: str,
385+
headers: dict[str, str] | None = None,
384386
extra_params: dict[str, str] | None = None,
385387
) -> Response:
388+
headers = {**(headers or {}), **self.request_headers}
386389
params = {**(extra_params or {})}
387390
url = f"{self.api_url}/{endpoint}"
388-
headers = {**self.request_headers, "Content-Type": "application/json"}
389391
return requests.head(
390392
url,
391393
params=params,

0 commit comments

Comments
 (0)