Two weeks ago, a buggy project landed in my hands, to repair. The bug report was really unclear – it was just stated a piece of code that was supposed to upload some Json files to the Azure cloud was not working on some PCs.
The code was something like this – well actually was much shittier than this, but I did some changes. I also cut some irrelevant parts:
function ReadBytesAsStream(const AFileName: string): TStream;
begin
Result := TFileStream.Create(AFileName, fmOpenRead or fmShareDenyWrite);
end;
function SendFileToCloud(AFilename: String; ShowErrors: Boolean): Boolean;
CONST
Container= 'MyContainer/';
BaseURL = 'https://xyz.blob.core.windows.net/'+ Container;
JWT = 'sp=rcwl&st=2022-10-04T00:00:26Z&'
+'se=2025-12-31T21:00:26Z&spr=https&'
+'sv=2021-06-08&' // SAS authorization token: https://learn.microsoft.com/en-us/azure/storage/common/storage-sas-overview?toc=%2Fazure%2Fstorage%2Fblobs%2Ftoc.json
+'sr=c&sig=blablabla';
VAR
FinalURL: String;
FileName: String;
FileContent: TStream;
RESTClient: TRESTClient;
RESTRequest: TRESTRequest;
RESTResponse: TRESTResponse;
begin
Result:= TRUE;
RESTClient:= NIL;
RESTRequest:= NIL;
RESTResponse:= NIL;
// Create URL
FileName := ExtractFileName(aFilename);
FinalURL := BaseURL + FileName + '?' + JWT;
FileContent := ReadBytesAsStream(AFileName); // Try to send as binary stream
FileContent.Position:= 0;
VAR sText:= ReadTextFromFile(AFileName); // Try to send as text
TRY
RESTClient := TRESTClient.Create(FinalURL);
RESTRequest := TRESTRequest.Create(RESTClient);
RESTResponse := TRESTResponse.Create(RESTClient);
RESTRequest.Client := RESTClient;
RESTRequest.Response := RESTResponse;
RESTRequest.Method := TRestRequestMethod.rmPUT;
// HEADER
RESTRequest.Params.AddItem('x-ms-blob-type', 'BlockBlob', TRESTRequestParameterKind.pkHTTPHEADER, [poDoNotEncode]);
RESTRequest.Params.AddItem('x-ms-version', '2021-06-08', TRESTRequestParameterKind.pkHTTPHEADER, [poDoNotEncode]);
RESTRequest.Params.AddItem('x-ms-date', '2023-02-28', TRESTRequestParameterKind.pkHTTPHEADER, [poDoNotEncode]);
// FILE BODY
RESTRequest.AddBody(AnsiString(sText), ctAPPLICATION_JSON);
RESTRequest.Execute;
FINALLY
FileContent.Free;
RESTResponse.Free;
RESTRequest.Free;
RESTClient.Free;
END;
end;
The code uploads a Json file on Azure, in the “Container” folder using SAS authentication, as binary blob, via PUT (put block).
The code is receiving back from the server a 201 answer (Ok, Uploaded) but the no file appeared on the server. The “people of the server” said that 201 means nothing; that the server returned 201 but internally it can have some error because the request coming from my program was malformed.
They didn’t allow access to their server (especially to the log). Instead they were sending me screenshots of the listing of the files on the server. My Json files were indeed missing.
Two weeks were spent like this.
In the end, one of their “server people” agreed to login together with me into the server (he shared the screen, I watched). I asked to see my IP into the log and the associated error for my IP. Surprise surprise, my IP did not appeared in the log. 10 minutes later, the mystery was solved.
Stay with me because it’s getting interesting: My code worked all the time! There was no bug!
What happen, was that “the people of the server” didn’t know how to read the list of the files. You see, Azure cpanel will let you display the files in a folder. It even lets you sort them by date. So, they were sorting the files by date and looked at the top of the list. My Json files were not there. Little they knew that Azure will not list ALL entries but only 5000 (random?) entries.