Hello Guys,
Im currently trying to send a PUT Request to my Azure Blob Storage via AL. But im facing the problem setting up a working Request. Im receiving a 403 Error.
I have already implemented this in c# for testing this in general. This works like a charm.
{ procedure PutBlob(var TmpBlob: Codeunit "Temp Blob")
var
UtcDateTimeMgt: Codeunit "Type Helper";
WebClient: HttpClient;
WebResponse: HttpResponseMessage;
Headers: HttpHeaders;
Content: HttpContent;
Uri: Text;
InStr: InStream;
begin
UtcNow := UtcDateTimeMgt.GetCurrUTCDateTimeAsText();
Uri := StrSubstNo('http://%1.blob.core.windows.net/%2/%3', GetStorageAccountName(), GetContainerName(), GetFutureBlobName());
AddDefaultHeaderWithCheckUp(WebClient, 'x-ms-blob-type', 'Blockblob');
AddDefaultHeaderWithCheckUp(WebClient, 'x-ms-date', UtcNow);
AddDefaultHeaderWithCheckUp(WebClient, 'x-ms-version', GetApiVersion());
TmpBlob.CreateInStream(InStr);
Content.Clear();
Content.WriteFrom(InStr);
Headers.Clear();
Content.GetHeaders(Headers);
Headers.Remove('Content-Type');
Headers.Add('Content-Type', FileMgt.GetFileNameMimeType(GetFutureBlobName()));
Headers.Add('Content-Length', Format(TmpBlob.Length(), 0, 9));
Content.GetHeaders(Headers);
WebClient.DefaultRequestHeaders.Add('Authorization', GetAuthorizationHeader(TmpBlob));
if WebClient.Put(Uri, Content, WebResponse) = false then
Error(WebResponse.ReasonPhrase())
else
Message(StrSubstNo('Reason:%1', WebResponse.ReasonPhrase()));
end;
local procedure GetAuthorizationHeader(var TmpBlob: Codeunit "Temp Blob") AuthorizationHeader: Text
var
Hmac: Codeunit "Cryptography Management";
HeaderResource: Text;
UrlResource: Text;
Signature: Text;
HashAlgo: Option HMACMD5,HMACSHA1,HMACSHA256,HMACSHA384,HMACSHA512;
begin
NewLine[1] := 10;
HeaderResource := 'x-ms-blob-type:BlockBlob' NewLine 'x-ms-date:' UtcNow NewLine 'x-ms-version:' GetApiVersion();
UrlResource := '/' GetStorageAccountName() '/' GetContainerName() '/' GetFutureBlobName();
//Signature=Base64(HMAC-SHA256(UTF8(StringToSign), Base64.decode()))
Signature := 'PUT' NewLine NewLine NewLine Format(TmpBlob.Length(), 0, 9) NewLine NewLine FileMgt.GetFileNameMimeType(GetFutureBlobName())
NewLine NewLine NewLine NewLine NewLine NewLine NewLine HeaderResource NewLine UrlResource;
AuthorizationHeader := 'SharedKey ' GetStorageAccountName() ':' Hmac.GenerateBase64KeyedHashAsBase64String(Signature, GetStorageKey(), HashAlgo::HMACSHA256);
//https://github.com/microsoft/ALAppExtensions/blob/master/Modules/System/Cryptography Management/README.md#generatehashasbase64string-method--1
end;
local procedure AddDefaultHeaderWithCheckUp(Webclient: HttpClient; Name: Text; Value: Text)
begin
if not Webclient.DefaultRequestHeaders.Add(Name, Value) then
Error((StrSubstNo('Error on %1', Name)));
end;
I really dont know how to make this working since its similar to my C# Put Request.
I did some local procedures for example login data. (The GetObjectName() procedures). The API Version im using is
-
local procedure GetApiVersion() Version: Text
begin
Version := '2014-02-14';
end;
feel free to ask me If you have any Questions about my Code above.
Thanks in advance. :-)