BlobServiceClient在Azurite不在默认端口时调用错误



我使用Azurite在本地运行有关将文件上传到Azure Blob存储的某些功能的测试。我通过使用docker撰写来运行它,并且我想在测试的非默认端口中运行它。我提出的配置如下:

storage:
image: mcr.microsoft.com/azure-storage/azurite
environment:
- AZURITE_ACCOUNTS=account:QUJDRA==
ports:
- "10020:10000"

我使用以下配置在Asp中注册BlobServiceClient服务。Net核心:

services.AddAzureClients(builder =>
{
builder.AddBlobServiceClient(
new Uri("http://localhost:10020/account"),
new StorageSharedKeyCredential("account", "QUJDRA=="));
});

上传文件的代码如下:

public async Task<string> UploadFile(BlobServiceClient blobServiceClient, Stream file)
{
var blobContainerClient = blobServiceClient.GetBlobContainerClient("container");
await blobContainerClient.CreateIfNotExistsAsync(PublicAccessType.BlobContainer);
var blobClient = blobContainerClient.GetBlobClient("blob");
await blobClient.UploadAsync(file);
return blobClient.Uri.ToString();
}

如果我在默认端口(10000)中运行此配置,则一切正常,并且我从Azurite容器中获得以下日志:

storage-1  | 172.21.0.1 - - [20/Jan/2023:11:02:35 +0000] "PUT /account/container?restype=container HTTP/1.1" 409 -
storage-1  | 172.21.0.1 - - [20/Jan/2023:11:02:37 +0000] "PUT /account/container/blob?comp=block&blockid=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA HTTP/1.1" 201 -
storage-1  | 172.21.0.1 - - [20/Jan/2023:11:02:37 +0000] "PUT /account/container/blob?comp=blocklist HTTP/1.1" 201 -

但是,如果我尝试在非默认端口(10020)中运行它,则上传文件的await blobClient.UploadAsync(file)行会产生以下异常:

Azure.RequestFailedException : Service request failed.
Status: 400 (Bad Request)
storage-1  | 172.25.0.1 - - [20/Jan/2023:11:18:43 +0000] "PUT /account/container?restype=container HTTP/1.1" 201 -
storage-1  | 172.25.0.1 - - [20/Jan/2023:11:18:44 +0000] "PUT /account/blob?comp=block&blockid=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA HTTP/1.1" 400 -

如果您仔细查看日志的第二行,对应于文件的上传,在这种情况下,url在帐户名之后缺少/container部分。我想这就是400错误的原因。

为什么端口的改变会以这种方式改变url ?我还遗漏了什么配置吗?

问题在于BlobContainerClient.GetBlobClient()如何尝试从Azure.Storage.Blobs(12.14.1)和Azure.Storage.Common(12.13.0)中的URI中确定帐户名称。

GetBlobClient方法在内部创建BlobUriBuilder的实例,接收容器客户端的URI。然后它尝试解构URI,但由于帐户名称在Azure存储容器(在域之前)和Azurite(路径的第一部分)中的位置不同,因此端口用于确定应该如何完成。

确定它是否是Azurite实例的白名单端口如下:


10001,10001,10002,10003,10004,
10100,10101, 10102, 10103, 10104,
11000,11001, 11002,11003,11004,
11100,11101, 11102, 11103, 11104

除了源代码,我没有找到任何公开此问题的文档。


来源:BlobUriBuilder构造函数调用uri.IsHostIPEndPointStyle()

...
if (uri.IsHostIPEndPointStyle())
{
_isPathStyleUri = true;
var accountEndIndex = path.IndexOf("/", StringComparison.InvariantCulture);

// Slash not found; path has account name & no container name
if (accountEndIndex == -1)
{
AccountName = path;
startIndex = path.Length;
}
else
{
AccountName = path.Substring(0, accountEndIndex);
startIndex = accountEndIndex + 1;
}
}
else
{
AccountName = uri.GetAccountNameFromDomain(Constants.Blob.UriSubDomain) ?? string.Empty;
}
...

来源:引用Constants.Sas.PathStylePorts

// See remarks at https://docs.microsoft.com/en-us/dotnet/api/system.net.ipaddress.tryparse?view=netframework-4.7.2
/// <summary>
/// Check to see if Uri is using IP Endpoint style.
/// </summary>
/// <param name="uri">The Uri.</param>
/// <returns>True if using IP Endpoint style.</returns>
public static bool IsHostIPEndPointStyle(this Uri uri) =>
(!string.IsNullOrEmpty(uri.Host) &&
uri.Host.IndexOf(".", StringComparison.InvariantCulture) >= 0 &&
IPAddress.TryParse(uri.Host, out _)) ||
Constants.Sas.PathStylePorts.Contains(uri.Port);

来源:用于白名单端口

/// <summary>
/// List of ports used for path style addressing.
/// Copied from Microsoft.Azure.Storage.Core.Util
/// </summary>
internal static readonly int[] PathStylePorts = { 10000, 10001, 10002, 10003, 10004, 10100, 10101, 10102, 10103, 10104, 11000, 11001, 11002, 11003, 11004, 11100, 11101, 11102, 11103, 11104 };

相关内容

  • 没有找到相关文章

最新更新