Skip to content

Commit f0f5cb7

Browse files
[ERSSUP-61674]-[JW/AO]-[Retrieve Binary R4 API design]-[FV]
1 parent e655d16 commit f0f5cb7

File tree

9 files changed

+137
-2
lines changed

9 files changed

+137
-2
lines changed

sandbox/src/routes/index.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ const retrieveHealthcareService = require('./r4/retrieveHealthcareService')
4242
const searchForHealthcareServices = require('./r4/searchForHealthcareServices')
4343
const searchServiceRequest = require('./r4/searchServiceRequest')
4444
const requestUploadUri = require('./r4/requestUploadUri')
45+
const retrieveBinary = require('./r4/retrieveBinary')
46+
const retrieveBinaryHelper = require('./r4/retrieveBinaryHelper')
4547

4648
const routes = [].concat(
4749
getStatus,
@@ -80,7 +82,9 @@ const routes = [].concat(
8082
retrieveAppointment,
8183
retrieveAdviceAndGuidanceOverviewPdf,
8284
searchServiceRequest,
83-
requestUploadUri
85+
requestUploadUri,
86+
retrieveBinary,
87+
retrieveBinaryHelper
8488
)
8589

8690
module.exports = routes
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
const businessFunctionValidator = require('../../services/businessFunctionValidator')
2+
3+
module.exports = [
4+
/**
5+
* Sandbox implementation for retrieveBinary A039 (R4) endpoint
6+
*/
7+
{
8+
method: 'GET',
9+
path: '/FHIR/R4/Binary/{attachmentUuid}',
10+
handler: (request, h) => {
11+
12+
const allowedBusinessFunctions = ["REFERRING_CLINICIAN", "REFERRING_CLINICIAN_ADMIN", "SERVICE_PROVIDER_CLINICIAN", "SERVICE_PROVIDER_CLINICIAN_ADMIN"]
13+
14+
const validationResult = businessFunctionValidator.validateBusinessFunction(request, h, allowedBusinessFunctions)
15+
if (validationResult) {
16+
return validationResult
17+
}
18+
19+
const uuid = request.params.attachmentUuid;
20+
const url = request.url.href;
21+
const objectStore = "/ObjectStore/RetrieveBinary/d497bbe3-f88b-45f1-b3d4-9c563e4c0f5f";
22+
const location = url.split('/FHIR')[0] + objectStore;
23+
24+
if (uuid === '704c3791-0873-45e9-9a04-b51996f8d93f' && request.method === 'get') {
25+
const response = h.response().code(307)
26+
response.headers["Location"] = location;
27+
return response
28+
} else {
29+
return h.file('SandboxErrorOutcome.json').code(422);
30+
}
31+
32+
}
33+
}
34+
]
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
module.exports = [
2+
/**
3+
* Sandbox implementation for retrieveBinary (R4) endpoint helper,
4+
* with an ObjectStore 'mock', allowing redirection and example file retrieval.
5+
*/
6+
{
7+
method: 'GET',
8+
path: '/ObjectStore/RetrieveBinary/{fileDownloadUuid}',
9+
handler: (request, h) => {
10+
11+
const uuid = request.params.fileDownloadUuid
12+
const exampleResponsePath = 'retrieveAttachment/responses/example_attachment.pdf'
13+
const filename = 'example_attachment.pdf'
14+
const responseCode = 200
15+
16+
if (uuid === 'd497bbe3-f88b-45f1-b3d4-9c563e4c0f5f') {
17+
return h.file(exampleResponsePath, {
18+
mode: 'attachment',
19+
filename: filename,
20+
etagMethod: false
21+
}).code(responseCode);
22+
}
23+
}
24+
}
25+
]

scripts/populate_placeholders.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ def main():
4646
"[[HYPERLINK_A039]]": "[A039 - Request pre-signed URL to upload file to document store](#api-Default-a039-request-pre-signed-url-for-file-upload)",
4747
"[[HYPERLINK_A040]]": "[A040 - Retrieve e-RS-Specific Practitioner Information](#api-Default-a040-retrieve-practitioner-info)",
4848
"[[HYPERLINK_A041]]": "[A041 - Search service request](#api-Default-a041-search-service-request)",
49+
"[[HYPERLINK_A042]]": "[A042 - Request pre-signed URL to download file from document store](#api-Default-a042-request-pre-signed-url-for-file-download)",
4950
"[[HYPERLINK_A043]]": "[A043 - Retrieve advice and guidance overview PDF](#api-Default-a043-retrieve-advice-and-guidance-overview-pdf)",
5051
"[[HYPERLINK_ONBOARDING]]": "[onboarding](#api-description__onboarding)",
5152
"[[HYPERLINK_STABLE]]": "[stable](https://digital.nhs.uk/developer/guides-and-documentation/reference-guide#api-status)",

scripts/validate_oas_examples.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
http_methods = ["post", "put", "patch", "get"]
3434

3535
# List containing http success response codes
36-
http_success_codes = ["200", "201"]
36+
http_success_codes = ["200", "201", "307"]
3737

3838
# Open OAS JSON file
3939
try:
@@ -141,6 +141,7 @@ def get_success_code(endpoint, http_method):
141141
oas_spec_from_yaml["paths"][endpoint][http_method]["responses"].keys()
142142
)
143143
filtered_code = filter(lambda x: x in http_success_codes, endpoint_return_codes)
144+
144145
return list(filtered_code)[0]
145146

146147

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
in: path
2+
name: id
3+
description: |
4+
Reference for an attachment, as provided in the response from [[HYPERLINK_A039]].
5+
required: true
6+
schema:
7+
type: string
8+
example: '704c3791-0873-45e9-9a04-b51996f8d93f'
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
description: Response redirects user agent to the large file attachment URL in the Object Store via the Location header.
2+
headers:
3+
x-correlation-id:
4+
$ref: '../../headers/response/CorrelationID.yaml'
5+
x-request-id:
6+
$ref: '../../headers/response/RequestID.yaml'
7+
Location:
8+
description: The large file attachment location in the Object Store.
9+
required: true
10+
schema:
11+
type: string
12+
example: '<ObjectStoreURL>'
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
description: |
2+
Where status code 400 (Bad Request) is returned then an [NHSDigital-OperationOutcome](https://fhir.nhs.uk/StructureDefinition/NHSDigital-OperationOutcome) will be included in the body, as detailed below.
3+
Check diagnostics property for specific information regarding the error.
4+
5+
| issue.details.coding.code | issue.code | Description |
6+
| ------------------------- | ------------ | ----------------------------------------------------- |
7+
| REC_BAD_REQUEST | required | TODO:63315 |
8+
headers:
9+
x-correlation-id:
10+
$ref: '../../headers/response/CorrelationID.yaml'
11+
x-request-id:
12+
$ref: '../../headers/response/RequestID.yaml'
13+
Content-Type:
14+
$ref: '../../headers/response/ContentTypeFhirJson.yaml'
15+
content:
16+
application/fhir+json:
17+
schema:
18+
$ref: '../../NHSDigital-OperationOutcome.yaml'
19+
example:
20+
$ref: '../../../examples/NHSDigital-OperationOutcome.json'

specification/e-referrals-service-api.yaml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3716,6 +3716,36 @@ paths:
37163716
$ref: 'components/r4/schemas/responses/R4-TooManyRequests.yaml'
37173717
'500':
37183718
$ref: 'components/r4/schemas/responses/R4-InternalServerError.yaml'
3719+
/R4/Binary/{id}:
3720+
get:
3721+
security:
3722+
- bearerAuth: []
3723+
description: |
3724+
### TODO Add later
3725+
summary: A042 - Request pre-signed URL to download file from document store
3726+
operationId: a042-request-pre-signed-url-for-file-download
3727+
parameters:
3728+
- $ref: 'components/r4/schemas/headers/request/BearerAuthorization.yaml'
3729+
- $ref: 'components/r4/schemas/headers/request/BusinessFunction.yaml'
3730+
- $ref: 'components/r4/schemas/headers/request/CorrelationID.yaml'
3731+
- $ref: 'components/r4/schemas/headers/request/OdsCode.yaml'
3732+
- $ref: 'components/r4/schemas/headers/request/OnBehalfOfUserID.yaml'
3733+
- $ref: 'components/r4/schemas/path/AttachmentUuid.yaml'
3734+
responses:
3735+
'307':
3736+
$ref: 'components/r4/schemas/responses/retrieveBinary/307Response.yaml'
3737+
'400':
3738+
$ref: 'components/r4/schemas/responses/retrieveBinary/400Response.yaml'
3739+
'401':
3740+
$ref: 'components/r4/schemas/responses/R4-Unauthorized.yaml'
3741+
'403':
3742+
$ref: 'components/r4/schemas/responses/R4-Forbidden.yaml'
3743+
'404':
3744+
$ref: 'components/r4/schemas/responses/R4-NotFound.yaml'
3745+
'429':
3746+
$ref: 'components/r4/schemas/responses/R4-TooManyRequests.yaml'
3747+
'500':
3748+
$ref: 'components/r4/schemas/responses/R4-InternalServerError.yaml'
37193749
components:
37203750
securitySchemes:
37213751
bearerAuth:

0 commit comments

Comments
 (0)