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