Azure / azure-sdk-for-js

This repository is for active development of the Azure SDK for JavaScript (NodeJS & Browser). For consumers of the SDK we recommend visiting our public developer docs at https://docs.microsoft.com/javascript/azure/ or our versioned developer docs at https://azure.github.io/azure-sdk-for-js.
MIT License
2.09k stars 1.2k forks source link

Blob storage client: multiple upload on single client fails #30371

Open gsouf opened 4 months ago

gsouf commented 4 months ago

Describe the bug

When uploading more than one file with BlobServiceClient, the second upload will result in an authorization error

To Reproduce Steps to reproduce the behavior:

  1. Start Azurite locally
  2. create a new directory and install azure blob storage: npm install @azure/storage-blob
  3. Create a js file with the following code:
    
    const {BlobServiceClient} = require("@azure/storage-blob");

main();

async function upload(containerClient, filePath, blobName) { const blobClient = containerClient.getBlockBlobClient(blobName); await blobClient.uploadFile(filePath); }

async function main() {

const connectionString = "UseDevelopmentStorage=true;DevelopmentStorageProxyUri=http://localhost:10000";

const blobService = BlobServiceClient.fromConnectionString(connectionString);
const containerClient = blobService.getContainerClient('pdf-to-image');

const file1 = 'path/to/some/file';
const file2 = 'path/to/some/file';

await upload(containerClient, file1, 'blob1')
await upload(containerClient, file2, 'blob2')

}

4. replace value of `file1` and `file2` with path to existing files
5. execute the js file using node

**Expected behavior**
2 files uploaded to azurite

**Actual behavior**
1 file uploaded, second file throws error:

...../node_modules/@azure/core-client/dist/commonjs/deserializationPolicy.js:148 const error = new core_rest_pipeline_1.RestError(initialErrorMessage, { ^

RestError: Server failed to authenticate the request. Make sure the value of the Authorization header is formed correctly including the signature. RequestId:bbd059bc-d4fd-4625-964c-c85f9eaab0aa Time:2024-07-11T00:25:51.903Z at handleErrorResponse (...../node_modules/@azure/core-client/dist/commonjs/deserializationPolicy.js:148:19) at deserializeResponseBody (...../node_modules/@azure/core-client/dist/commonjs/deserializationPolicy.js:83:45) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async StorageContextClient.sendOperationRequest (...../node_modules/@azure/core-client/dist/commonjs/serviceClient.js:110:33) at async StorageContextClient.sendOperationRequest (...../node_modules/@azure/core-http-compat/dist/commonjs/extendedClient.js:45:24) at async ...../node_modules/@azure/storage-blob/dist/index.js:20568:35 at async Object.withSpan (...../node_modules/@azure/core-tracing/dist/commonjs/tracingClient.js:36:28) at async ...../node_modules/@azure/storage-blob/dist/index.js:20854:39 at async Object.withSpan (...../node_modules/@azure/core-tracing/dist/commonjs/tracingClient.js:36:28) at async Object.withSpan (...../node_modules/@azure/core-tracing/dist/commonjs/tracingClient.js:36:28) { code: 'AuthorizationFailure', statusCode: 403,


**Additional context**

Used docker version of azurite. See `docker-compose.yml` file:

```yml
services:
  dev.azurite:
    image: mcr.microsoft.com/azure-storage/azurite:3.31.0
    restart: no
    command: "azurite --disableProductStyleUrl --blobHost 0.0.0.0 --queueHost 0.0.0.0 --tableHost 0.0.0.0"
    volumes:
      - ./volumes/azurite-data:/data
    ports:
      - "10000:10000"
      - "10001:10001"
      - "10002:10002"

Workaround

Creating a new client for each upload fixes the issue :

async function upload( filePath, blobName) {

    // + add client connection here

    const connectionString = "UseDevelopmentStorage=true;DevelopmentStorageProxyUri=http://localhost:10000";

    const blobService = BlobServiceClient.fromConnectionString(connectionString);
    const containerClient = blobService.getContainerClient('pdf-to-image');
    const blobClient = containerClient.getBlockBlobClient(blobName);
    await blobClient.uploadFile(filePath);
}

async function main() {

    // - removed client connection here

    const file1 = 'path/to/some/file';
    const file2 = 'path/to/some/file';

    await upload( file1, 'blob1')
    await upload( file2, 'blob2')
}
github-actions[bot] commented 4 months ago

Thanks for the feedback! We are routing this to the appropriate team for follow-up. cc @xgithubtriage.