Skip to content

Commit 08a39e8

Browse files
committed
WIP
1 parent bac3f83 commit 08a39e8

File tree

2 files changed

+428
-38
lines changed

2 files changed

+428
-38
lines changed

app/clients/letter/dvla.py

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import base64
21
import contextlib
32
import secrets
43
import string
@@ -254,6 +253,36 @@ def _get_auth_headers(self):
254253
"X-API-Key": self.dvla_api_key.get(),
255254
}
256255

256+
def _get_upload_url(self):
257+
"""
258+
Calls the DVLA endpoint to get a presigned URL to use to upload a letter
259+
"""
260+
261+
def _handle_http_errors(e: requests.HTTPError):
262+
if e.response.status_code == 400:
263+
raise DvlaNonRetryableException(e.response.json()["errors"][0]["detail"]) from e
264+
elif e.response.status_code in {401, 403}:
265+
# probably the api key is not valid
266+
self.dvla_api_key.clear()
267+
268+
raise DvlaUnauthorisedRequestException(e.response.json()["errors"][0]["detail"]) from e
269+
270+
with _handle_common_dvla_errors(custom_httperror_exc_handler=_handle_http_errors):
271+
response = self.session.get(
272+
f"{self.base_url}/print-request/v1/print/files/upload-url",
273+
headers=self._get_auth_headers(),
274+
)
275+
response.raise_for_status()
276+
return response.json()
277+
278+
def _upload_file(self, *, upload_url: str, pdf_file: bytes):
279+
"""
280+
Uploads the letter to the given presigned URL
281+
"""
282+
with _handle_common_dvla_errors():
283+
response = self.session.put(upload_url, headers={"Content-Type": "application/pdf"}, data=pdf_file)
284+
response.raise_for_status()
285+
257286
def send_letter(
258287
self,
259288
*,
@@ -269,6 +298,16 @@ def send_letter(
269298
"""
270299
Sends a letter to the DVLA for printing
271300
"""
301+
url_response = self._get_upload_url()
302+
upload_id = url_response["uploadId"]
303+
upload_url = url_response["uploadUrl"]
304+
305+
self._upload_file(upload_url=upload_url, pdf_file=pdf_file)
306+
current_app.logger.info(
307+
"Letter with notification id %s uploaded to DVLA presigned URL",
308+
notification_id,
309+
extra={"notification_id": notification_id},
310+
)
272311

273312
def _handle_http_errors(e: requests.HTTPError):
274313
if e.response.status_code == 400:
@@ -292,15 +331,15 @@ def _handle_http_errors(e: requests.HTTPError):
292331
postage=postage,
293332
service_id=service_id,
294333
organisation_id=organisation_id,
295-
pdf_file=pdf_file,
334+
upload_id=upload_id,
296335
callback_url=callback_url,
297336
),
298337
)
299338
response.raise_for_status()
300339
return response.json()
301340

302341
def _format_create_print_job_json(
303-
self, *, notification_id, reference, address, postage, service_id, organisation_id, pdf_file, callback_url
342+
self, *, notification_id, reference, address, postage, service_id, organisation_id, upload_id, callback_url
304343
):
305344
# We shouldn't need to pass the postage in, as the address has a postage field. However, at this point we've
306345
# recorded the postage on the notification so we should respect that rather than introduce any possible
@@ -320,7 +359,6 @@ def _format_create_print_job_json(
320359
"address": address_data,
321360
},
322361
"customParams": [
323-
{"key": "pdfContent", "value": base64.b64encode(pdf_file).decode("utf-8")},
324362
{"key": "organisationIdentifier", "value": organisation_id},
325363
{"key": "serviceIdentifier", "value": service_id},
326364
],
@@ -331,6 +369,8 @@ def _format_create_print_job_json(
331369
"retryParams": {"enabled": True, "maxRetryWindow": 10800},
332370
}
333371

372+
json_payload["fileParams"] = [{"fileId": notification_id, "uploadId": upload_id}]
373+
334374
# `despatchMethod` should not be added for second class letters
335375
if postage == FIRST_CLASS:
336376
json_payload["standardParams"]["despatchMethod"] = "FIRST"

0 commit comments

Comments
 (0)