@@ -293,42 +293,60 @@ info:
293293
294294 **Notes**
295295 - the API rejects the request if the `timestamp` supplied is not within 2 hours of the server time
296- - in the example below `SHARED_KEY` has been `[REDACTED]`, this is the 'environment shared secret' which you received as part of creating your mailbox
296+ - in the example below `SHARED_KEY` has been `[REDACTED_SHARED_KEY]`, this is the 'environment shared secret' which you received as part of creating your mailbox
297+ - in the example below `MAILBOX_PASSWORD` has been `[REDACTED_PASSWORD]`, this is the 'mesh mailbox password' which you received as part of creating your mailbox
297298
298299 ### Example implementation
299300 Here is an implementation of the above in `python3`.
300301 ```python
301302 """ Python code to generate a valid authorization header. """
302303 import hmac
303304 import uuid
304- import datetime from hashlib
305- import sha256
306-
307- AUTHSCHEMANAME = "NHSMESH " # Note: Space at the end of the schema.
308- SHARED_KEY = "[REDACTED]" # Note: Don't hard code your passwords in a real implementation.
309-
310- def build_auth_header(mailbox_id: str, password: str = "password", nonce: str = None, noncecount: int = 0):
311- """ Generate MESH Authorization header for mailboxid. """
312- #Generate a GUID if required.
313- if not nonce:
314- nonce = str(uuid.uuid4())
315- #Current time formatted as yyyyMMddHHmm
316- #for example, 4th May 2020 13:05 would be 202005041305
317- timestamp = datetime.datetime.now().strftime("%Y%m%d%H%M")
318-
319- #for example, NHSMESH AMP01HC001:bd0e2bd5-218e-41d0-83a9-73fdec414803:0:202005041305
320- hmac_msg = mailbox_id + ":" + nonce + ":" + str(nonce_count) + ":" + password + ":" + timestamp
321-
322- #HMAC is a standard crypto hash method built in the python standard library.
323- hash_code = hmac.HMAC(SHARED_KEY.encode(), hmac_msg.encode(), sha256).hexdigest()
324- return (
325- AUTH_SCHEMA_NAME # Note: No colon between 1st and 2nd elements.
326- + mailbox_id + ":"
327- + nonce + ":"
328- + str(nonce_count) + ":"
329- + timestamp+ ":"
330- + hash_code
331- )
305+ import datetime
306+ from hashlib import sha256
307+
308+ AUTH_SCHEMA_NAME = "NHSMESH " # Note: Space at the end of the schema.
309+ SHARED_KEY = "[REDACTED_SHARED_KEY]" # Note: Don't hard code your passwords in a real implementation.
310+
311+
312+ def build_auth_header(mailbox_id: str, password: str = "password", nonce: str = None, nonce_count: int = 0):
313+ """ Generate MESH Authorization header for mailboxid. """
314+ # Generate a GUID if required.
315+ if not nonce:
316+ nonce = str(uuid.uuid4())
317+ # Current time formatted as yyyyMMddHHmm
318+ # for example, 4th May 2020 13:05 would be 202005041305
319+ timestamp = datetime.datetime.now().strftime("%Y%m%d%H%M")
320+
321+ # for example, NHSMESH AMP01HC001:bd0e2bd5-218e-41d0-83a9-73fdec414803:0:202005041305
322+ hmac_msg = mailbox_id + ":" + nonce + ":" + str(nonce_count) + ":" + password + ":" + timestamp
323+
324+ # HMAC is a standard crypto hash method built in the python standard library.
325+ hash_code = hmac.HMAC(SHARED_KEY.encode(), hmac_msg.encode(), sha256).hexdigest()
326+ return (
327+ AUTH_SCHEMA_NAME # Note: No colon between 1st and 2nd elements.
328+ + mailbox_id + ":"
329+ + nonce + ":"
330+ + str(nonce_count) + ":"
331+ + timestamp+ ":"
332+ + hash_code
333+ )
334+
335+
336+ # example usage
337+ MAILBOX_ID = "X26AB1234" # Note: Don't hard code your mailbox id in a real implementation.
338+ MAILBOX_PASSWORD = "[REDACTED_PASSWORD]" # Note: Don't hard code your passwords in a real implementation.
339+
340+ # send a new nonce each time
341+ print(build_auth_header(MAILBOX_ID, MAILBOX_PASSWORD))
342+
343+ # or reuse the nonce and increment the nonce_count
344+ my_nonce = str(uuid.uuid4())
345+
346+ print(build_auth_header(MAILBOX_ID, MAILBOX_PASSWORD, my_nonce, nonce_count=1))
347+ print(build_auth_header(MAILBOX_ID, MAILBOX_PASSWORD, my_nonce, nonce_count=2))
348+
349+
332350 ```
333351
334352 ## MESH API pseudocode
@@ -862,12 +880,18 @@ paths:
862880 responses :
863881 ' 200 ' :
864882 description : OK, full message retrieved
865- content : {}
883+ content :
884+ application/octet-stream :
885+ schema :
886+ format : binary
866887 ' 403 ' :
867888 description : Authentication failed
868889 ' 206 ' :
869890 description : Partial Content - Indicates that chunk has been downloaded successfully and that there are further chunks.
870- content : {}
891+ content :
892+ application/octet-stream :
893+ schema :
894+ format : binary
871895 ' 404 ' :
872896 description : Not Found, message does not exist
873897 ' 410 ' :
@@ -1240,12 +1264,18 @@ paths:
12401264 responses :
12411265 ' 200 ' :
12421266 description : OK - chunk downloaded and no further chunks exist
1243- content : {}
1267+ content :
1268+ application/octet-stream :
1269+ schema :
1270+ format : binary
12441271 ' 403 ' :
12451272 description : Authentication failed
12461273 ' 206 ' :
12471274 description : Partial Content - Indicates that chunk has been downloaded successfully and that there are further chunks.
1248- content : {}
1275+ content :
1276+ application/octet-stream :
1277+ schema :
1278+ format : binary
12491279 ' 404 ' :
12501280 description : Not Found, message does not exist
12511281 ' 410 ' :
@@ -1396,7 +1426,7 @@ paths:
13961426 ```json
13971427 {"messageID": "20200529155357895317_3573F8"}
13981428 ```
1399- operationId : send_message_messageexchange__mailbox_id__outbox_post
1429+ operationId : send_message
14001430 parameters :
14011431 - description : mailbox identifier
14021432 required : true
@@ -1618,6 +1648,20 @@ paths:
16181648 title : HTTPValidationError
16191649 type : object
16201650 properties : *id001
1651+ requestBody :
1652+ description : message payload or chunk, optionally encoded with content-encoding
1653+ required : true
1654+ content :
1655+ application/octet-stream :
1656+ schema :
1657+ format : binary
1658+ example : ' ... message payload bytes...'
1659+ ' */* ' :
1660+ schema :
1661+ format : any
1662+ example : |-
1663+ message content....
1664+ any content type is acceptable but use application/octet-stream if you want a single default
16211665 /messageexchange/{mailbox_id}/outbox/{message_id}/{chunk_number} :
16221666 post :
16231667 tags :
@@ -1708,7 +1752,7 @@ paths:
17081752 --data-binary '@./message.txt_ab.gz' \
17091753 https://mesh-sync.spineservices.nhs.uk/messageexchange/X26HC006/outbox/20200601122152994285_D59900/2
17101754 ```
1711- operationId : send_chunk_messageexchange__mailbox_id__outbox__message_id___chunk_number__post
1755+ operationId : send_chunk
17121756 parameters :
17131757 - description : The index number of the chunk
17141758 required : true
@@ -1881,6 +1925,20 @@ paths:
18811925 title : HTTPValidationError
18821926 type : object
18831927 properties : *id001
1928+ requestBody :
1929+ description : message payload or chunk, optionally encoded with content-encoding
1930+ required : true
1931+ content :
1932+ application/octet-stream :
1933+ schema :
1934+ format : binary
1935+ example : ' ... message payload bytes...'
1936+ ' */* ' :
1937+ schema :
1938+ format : any
1939+ example : |-
1940+ message content....
1941+ any content type is acceptable but use application/octet-stream if you want a single default
18841942 /messageexchange/{mailbox_id}/outbox/tracking :
18851943 get :
18861944 tags :
0 commit comments