From 22dceb3c52e0a4de7df5b19f6969f36e5b8b5e53 Mon Sep 17 00:00:00 2001
From: Ellie Bound <175816742+ellie-bound1-NHSD@users.noreply.github.com>
Date: Fri, 23 May 2025 12:41:59 +0100
Subject: [PATCH 1/6] NPA-4284: Add small description about our request header
policy
---
specification/validated-relationships-service-api.yaml | 3 +++
1 file changed, 3 insertions(+)
diff --git a/specification/validated-relationships-service-api.yaml b/specification/validated-relationships-service-api.yaml
index a06da7e3..8dab3159 100644
--- a/specification/validated-relationships-service-api.yaml
+++ b/specification/validated-relationships-service-api.yaml
@@ -87,6 +87,9 @@ info:
|[NHS login - combined authentication and authorisation](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation/user-restricted-restful-apis-nhs-login-combined-authentication-and-authorisation) |OAuth 2.0 authorisation code with API key and secret |No need to integrate and onboard separately with NHS login. |No access to user information. |
|[NHS login - separate authentication and authorisation](https://digital.nhs.uk/developer/guides-and-documentation/security-and-authorisation/user-restricted-restful-apis-nhs-login-separate-authentication-and-authorisation) |OAuth 2.0 token exchange with signed JWT |Gives access to user information. |Need to integrate and onboard separately with NHS login. |
+ ## Headers
+ This API is case-insensitive when processing request headers, meaning it will accept headers regardless of the letter casing used. (e.g. X-Request-Id, x-request-id are treated the same). When sending headers back in the response, we preserve the exact casing as received in the original request.
+
## Errors
We use standard HTTP status codes to show whether an API request succeeded or not. They are usually in the range:
From 0cd2707665f9880b229830228431b1e721b59a27 Mon Sep 17 00:00:00 2001
From: Ellie Bound <175816742+ellie-bound1-NHSD@users.noreply.github.com>
Date: Fri, 23 May 2025 14:23:09 +0100
Subject: [PATCH 2/6] NPA-4284: Add python script to translate request headers
---
.../apiproxy/policies/TranslateRequestHeaders.xml | 6 ++++++
.../resources/py/translate-request-headers.py | 15 +++++++++++++++
proxies/live/apiproxy/targets/target.xml | 3 +++
3 files changed, 24 insertions(+)
create mode 100644 proxies/live/apiproxy/policies/TranslateRequestHeaders.xml
create mode 100644 proxies/live/apiproxy/resources/py/translate-request-headers.py
diff --git a/proxies/live/apiproxy/policies/TranslateRequestHeaders.xml b/proxies/live/apiproxy/policies/TranslateRequestHeaders.xml
new file mode 100644
index 00000000..06297ce7
--- /dev/null
+++ b/proxies/live/apiproxy/policies/TranslateRequestHeaders.xml
@@ -0,0 +1,6 @@
+
+
\ No newline at end of file
diff --git a/proxies/live/apiproxy/resources/py/translate-request-headers.py b/proxies/live/apiproxy/resources/py/translate-request-headers.py
new file mode 100644
index 00000000..d83b3ec0
--- /dev/null
+++ b/proxies/live/apiproxy/resources/py/translate-request-headers.py
@@ -0,0 +1,15 @@
+# Access request headers dictionary
+request_headers = request.headers
+
+# Map of lowercase header name to desired parcel case header name
+request_header_translation = {
+ "x-request-id": "X-Request-ID",
+ "x-correlation-id": "X-Correlation-ID"
+}
+
+# Loop through request headers
+for key, value in request_headers.items():
+ key = key.lower()
+ desired_name = request_header_translation.get(key)
+ if desired_name:
+ flow.setVariable(f"request.header.{desired_name}", value)
diff --git a/proxies/live/apiproxy/targets/target.xml b/proxies/live/apiproxy/targets/target.xml
index f779224d..3a0d7572 100644
--- a/proxies/live/apiproxy/targets/target.xml
+++ b/proxies/live/apiproxy/targets/target.xml
@@ -8,6 +8,9 @@
FlowCallout.ApplyRateLimiting
+
+ TranslateRequestHeaders
+
AddDeveloperAppData
From 828f33ad511d7a4c67f44aadacfee9582f9d0b68 Mon Sep 17 00:00:00 2001
From: Ellie Bound <175816742+ellie-bound1-NHSD@users.noreply.github.com>
Date: Fri, 23 May 2025 14:23:18 +0100
Subject: [PATCH 3/6] NPA-4284: Add python script to translate request headers
---
.../live/apiproxy/resources/py/translate-request-headers.py | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/proxies/live/apiproxy/resources/py/translate-request-headers.py b/proxies/live/apiproxy/resources/py/translate-request-headers.py
index d83b3ec0..69065a83 100644
--- a/proxies/live/apiproxy/resources/py/translate-request-headers.py
+++ b/proxies/live/apiproxy/resources/py/translate-request-headers.py
@@ -2,10 +2,7 @@
request_headers = request.headers
# Map of lowercase header name to desired parcel case header name
-request_header_translation = {
- "x-request-id": "X-Request-ID",
- "x-correlation-id": "X-Correlation-ID"
-}
+request_header_translation = {"x-request-id": "X-Request-ID", "x-correlation-id": "X-Correlation-ID"}
# Loop through request headers
for key, value in request_headers.items():
From e9ea4d163b9e2a6bcf6bba368212526c5f17bf8a Mon Sep 17 00:00:00 2001
From: Ellie Bound <175816742+ellie-bound1-NHSD@users.noreply.github.com>
Date: Fri, 23 May 2025 14:51:06 +0100
Subject: [PATCH 4/6] NPA-4284: Add mirror request headers in response script
---
.../policies/MirrorRequestHeaders.xml | 6 +++++
.../policies/TranslateRequestHeaders.xml | 2 +-
.../resources/py/mirror-request-headers.py | 6 +++++
.../resources/py/translate-request-headers.py | 22 +++++++++++++++----
proxies/live/apiproxy/targets/target.xml | 9 +++++++-
5 files changed, 39 insertions(+), 6 deletions(-)
create mode 100644 proxies/live/apiproxy/policies/MirrorRequestHeaders.xml
create mode 100644 proxies/live/apiproxy/resources/py/mirror-request-headers.py
diff --git a/proxies/live/apiproxy/policies/MirrorRequestHeaders.xml b/proxies/live/apiproxy/policies/MirrorRequestHeaders.xml
new file mode 100644
index 00000000..f3e57777
--- /dev/null
+++ b/proxies/live/apiproxy/policies/MirrorRequestHeaders.xml
@@ -0,0 +1,6 @@
+
+
\ No newline at end of file
diff --git a/proxies/live/apiproxy/policies/TranslateRequestHeaders.xml b/proxies/live/apiproxy/policies/TranslateRequestHeaders.xml
index 06297ce7..22e9c5cf 100644
--- a/proxies/live/apiproxy/policies/TranslateRequestHeaders.xml
+++ b/proxies/live/apiproxy/policies/TranslateRequestHeaders.xml
@@ -1,5 +1,5 @@
-
\ No newline at end of file
diff --git a/proxies/live/apiproxy/policies/TranslateRequestHeaders.xml b/proxies/live/apiproxy/policies/TranslateRequestHeaders.xml
index 22e9c5cf..160b92df 100644
--- a/proxies/live/apiproxy/policies/TranslateRequestHeaders.xml
+++ b/proxies/live/apiproxy/policies/TranslateRequestHeaders.xml
@@ -1,6 +1,6 @@
\ No newline at end of file
diff --git a/proxies/live/apiproxy/targets/target.xml b/proxies/live/apiproxy/targets/target.xml
index 3fb5a6c2..37dce55c 100644
--- a/proxies/live/apiproxy/targets/target.xml
+++ b/proxies/live/apiproxy/targets/target.xml
@@ -78,24 +78,33 @@
-
+
MirrorRequestHeaders
-
+
+
+ MirrorRequestHeaders
+
RaiseFault.401Unauthorized
oauthV2.OauthV2.VerifyAccessToken.failed = true or fault.name = "invalid_access_token" or fault.name = "InvalidAccessToken" or fault.name = "access_token_not_approved" or fault.name = "apiresource_doesnot_exist" or fault.name = "InvalidAPICallAsNo" or fault.name = "ApiProductMatchFound" or fault.name = "access_token_expired"
+
+ MirrorRequestHeaders
+
RaiseFault.404NotFound
response.header.x-amzn-ErrorType = "IncompleteSignatureException"
+
+ MirrorRequestHeaders
+
RaiseFault.ApplicationOperationOutcome
response.header.x-amzn-RequestId != null