Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 25 additions & 3 deletions gateway-api/src/gateway_api/app.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import os
import traceback

from flask import Flask, request
from flask import Flask, Request, request
from flask.wrappers import Response

from gateway_api.common.error import AbstractCDGError, UnexpectedError
Expand All @@ -12,6 +12,7 @@
)

app = Flask(__name__)
app.logger.setLevel("INFO")


def get_app_host() -> str:
Expand All @@ -30,8 +31,29 @@ def get_app_port() -> int:
return int(port)


def log_request_received(request: Request) -> None:
log_details = {
"description": "Received request",
"method": request.method,
Comment on lines +34 to +37
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR title is focused on adding CIS2 user/user-role identity headers in the proxy config, but this change set also introduces request/error logging behavior changes in gateway_api/app.py. Please either update the PR description to explain the additional scope and rationale, or split the logging refactor into a separate PR to keep changes reviewable and traceable.

Copilot uses AI. Check for mistakes.
"path": request.path,
"headers": dict(request.headers),
}
app.logger.info(log_details)


def log_error(error: AbstractCDGError) -> None:
log_details = {
"description": "An error occurred",
"error_type": type(error).__name__,
"error_message": str(error),
"traceback": traceback.format_exc(),
}
app.logger.error(log_details)


@app.route("/patient/$gpc.getstructuredrecord", methods=["POST"])
def get_structured_record() -> Response:
log_request_received(request)
response = GetStructuredRecordResponse()
response.mirror_headers(request)
try:
Expand All @@ -40,11 +62,11 @@ def get_structured_record() -> Response:
provider_response = controller.run(request=get_structured_record_request)
response.add_provider_response(provider_response)
except AbstractCDGError as e:
e.log()
log_error(e)
response.add_error_response(e)
except Exception:
error = UnexpectedError(traceback=traceback.format_exc())
error.log()
log_error(error)
response.add_error_response(error)

return response.build()
Expand Down
4 changes: 0 additions & 4 deletions gateway-api/src/gateway_api/common/error.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import traceback
from dataclasses import dataclass
from http.client import BAD_GATEWAY, BAD_REQUEST, INTERNAL_SERVER_ERROR, NOT_FOUND

Expand Down Expand Up @@ -37,9 +36,6 @@ def operation_outcome(self) -> OperationOutcome:
)
return operation_outcome

def log(self) -> None:
print(traceback.format_exc(), flush=True)

@property
def message(self) -> str:
return self._message.format(**self.additional_details)
Expand Down
2 changes: 1 addition & 1 deletion gateway-api/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ def _fetch_env_variable[T](


REMOTE_TEST_USERNAME_ENV_VAR = "REMOTE_TEST_USERNAME"
DEFAULT_REMOTE_TEST_USERNAME = "656005750104"
DEFAULT_REMOTE_TEST_USERNAME = "656005750101"


def _get_remote_test_username() -> str:
Expand Down
3 changes: 2 additions & 1 deletion proxygen/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ Proxygen deploys a proxy instance using an OpenAPI specification file. The speci

* the **target endpoint URL** to which the proxy will forward traffic;
* the **access controls** and scopes a user needs to access the proxy;
* the **mTLS secret name** pointing to the certificate the backend expects.
* the **mTLS secret name** pointing to the certificate the backend expects;
* the **target-identity** to add user identity headers to the request.

At deploy time, this template is concatenated with the main API specification (`gateway-api/openapi.yaml`), the target URL and mTLS secret are injected, and the resulting file is passed to the Proxygen CLI.

Expand Down
3 changes: 3 additions & 0 deletions proxygen/x-nhsd-apim.template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@ x-nhsd-apim:
security:
type: mtls
secret: <replace-with-secret-name>
target-identity:
- name: cis2-uuid
- name: cis2-urid
Loading