Azure / Azurite

A lightweight server clone of Azure Storage that simulates most of the commands supported by it with minimal dependencies
MIT License
1.8k stars 320 forks source link

Issue while fetching blobSasUrl to upload with 'PUT' #1981

Open thomasFranel opened 1 year ago

thomasFranel commented 1 year ago

Which service(blob, file, queue, table) does this issue concern?

blob

Which version of the Azurite was used?

3.23.0

Where do you get Azurite? (npm, DockerHub, NuGet, Visual Studio Code Extension)

DockerHub

What's the Node.js version?

18.13.0

What problem was encountered?

I'm trying to implement a way to let my front end (react) upload my file directly. Meaning that I call my back end for a "pre-signed" url : blobUrl + sasToken with permission 'racwd'

I give this url to my upload input, and I try fetching the url with my file in it thanks to axios

axios.put(
    uploadUrl, // My pre-signed url
    file, // my file of type File
   {
    ...(options || {}), // Options here are AxiosRequestConfig
    headers: {
      ...(options?.headers || {}),
      'Content-Type': file.type,
    },
  });

I've seen that BlobQuery are not yet implemented. Is it a project ? Or a work in progress ? Or is there any work around ?

Because when I try to do this, I get an error : Incoming Url doesn't match any of swagger defined request pattern

Steps to reproduce the issue?

Generate blobSasUrl

    const containerClient = blobServiceClient.getContainerClient(
      _containerName_,
    );
    const blockBlobClient = containerClient.getBlockBlobClient(filePath);
    const credentials = new storage.StorageSharedKeyCredential(
      _accountName_,
      _accountKey_,
    );

    const blobSas = storage
      .generateBlobSASQueryParameters(
        {
          containerName: _containerName_,
          blobName: filePath,
          permissions: storage.BlobSASPermissions.parse('racwd'),
          startsOn: new Date(),
          expiresOn: new Date(new Date().valueOf() + 86400),
        },
        credentials,
      )
      .toString();

    const sasUrl = `${blockBlobClient.url}?${blobSas}`;

And call in an uploadInput :

export const uploadObjectAsync = async (
  file: RcFile | File,
  uploadUrl: string, // Here will be sasUrl
  options?: AxiosRequestConfig,
) => {
  return axios.put(uploadUrl, file, {
    ...(options || {}),
    headers: {
      ...(options?.headers || {}),
      'Content-Type': file.type,
    },
  });
};

Have you found a mitigation/solution?

blueww commented 1 year ago

@thomasFranel Thanks for raising the issue! Could you please share the Azurite debug log to help investigation? (hide credential if any)

thomasFranel commented 1 year ago

Hi, sorry for the delay !

Here is the complete error log :

2023-06-12T16:07:15.964Z f3fa19f7-17de-43a4-a66f-7dbc7550527f info: EndMiddleware: End response. TotalTimeInMS=2 StatusCode=200 StatusMessage=undefined Headers={"server":"Azurite-Blob/3.23.0","access-control-allow-origin":"http://localhost:3000","access-control-allow-methods":"PUT","access-control-allow-headers":"content-type","access-control-max-age":900,"access-control-allow-credentials":"true"}
2023-06-12T16:07:15.972Z 76cdb4cc-ab3c-4826-ad9c-0caad518f6df info: BlobStorageContextMiddleware: RequestMethod=PUT RequestURL=http://127.0.0.1/devstoreaccount1/public/upload/00000000-0000-1000-a000-000000000001/56644b80-29cd-4343-b6ea-b98dc6a1d7d7/Satisfied-Seal.jpg?sv=2022-11-02&st=2023-06-12T16%3A07%3A15Z&se=2023-06-12T16%3A07%3A16Z&sr=b&sp=racwd&sig=smkz%2F54NQ04tbtY%2B2ktDlUrjhDuWvpPKGEA0y7T4lYA%3D RequestHeaders:{"host":"127.0.0.1:7777","connection":"keep-alive","content-length":"35415","sec-ch-ua":"\"Chromium\";v=\"113\", \"Not-A.Brand\";v=\"24\"","sec-ch-ua-platform":"\"macOS\"","dnt":"1","sec-ch-ua-mobile":"?0","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36","content-type":"image/jpeg","accept":"*/*","origin":"http://localhost:3000","sec-fetch-site":"cross-site","sec-fetch-mode":"cors","sec-fetch-dest":"empty","referer":"http://localhost:3000/","accept-encoding":"gzip, deflate, br","accept-language":"en-US,en;q=0.9,fr;q=0.8"} ClientIP=192.168.240.1 Protocol=http HTTPVersion=1.1
2023-06-12T16:07:15.976Z 76cdb4cc-ab3c-4826-ad9c-0caad518f6df info: BlobStorageContextMiddleware: Account=devstoreaccount1 Container=public Blob=upload/00000000-0000-1000-a000-000000000001/56644b80-29cd-4343-b6ea-b98dc6a1d7d7/Satisfied-Seal.jpg
2023-06-12T16:07:15.977Z 76cdb4cc-ab3c-4826-ad9c-0caad518f6df verbose: DispatchMiddleware: Dispatching request...
2023-06-12T16:07:15.981Z 76cdb4cc-ab3c-4826-ad9c-0caad518f6df error: DispatchMiddleware: Incoming URL doesn't match any of swagger defined request patterns.
2023-06-12T16:07:15.981Z 76cdb4cc-ab3c-4826-ad9c-0caad518f6df error: ErrorMiddleware: Received a MiddlewareError, fill error information to HTTP response
2023-06-12T16:07:15.981Z 76cdb4cc-ab3c-4826-ad9c-0caad518f6df error: ErrorMiddleware: ErrorName=UnsupportedRequestError ErrorMessage=Incoming URL doesn't match any of swagger defined request patterns.  ErrorHTTPStatusCode=400 ErrorHTTPStatusMessage=undefined ErrorHTTPHeaders=undefined ErrorHTTPBody=undefined ErrorStack="UnsupportedRequestError: Incoming URL doesn't match any of swagger defined request patterns.\n    at dispatchMiddleware (/opt/azurite/dist/src/blob/generated/middleware/dispatch.middleware.js:41:30)\n    at /opt/azurite/dist/src/blob/generated/ExpressMiddlewareFactory.js:50:47\n    at Layer.handle [as handle_request] (/opt/azurite/node_modules/express/lib/router/layer.js:95:5)\n    at trim_prefix (/opt/azurite/node_modules/express/lib/router/index.js:328:13)\n    at /opt/azurite/node_modules/express/lib/router/index.js:286:9\n    at Function.process_params (/opt/azurite/node_modules/express/lib/router/index.js:346:12)\n    at next (/opt/azurite/node_modules/express/lib/router/index.js:280:10)\n    at blobStorageContextMiddleware (/opt/azurite/dist/src/blob/middlewares/blobStorageContext.middleware.js:133:5)\n    at /opt/azurite/dist/src/blob/middlewares/blobStorageContext.middleware.js:15:16\n    at Layer.handle [as handle_request] (/opt/azurite/node_modules/express/lib/router/layer.js:95:5)"
2023-06-12T16:07:15.981Z 76cdb4cc-ab3c-4826-ad9c-0caad518f6df error: ErrorMiddleware: Set HTTP code: 400
2023-06-12T16:07:15.981Z 76cdb4cc-ab3c-4826-ad9c-0caad518f6df error: ErrorMiddleware: Set HTTP body: undefined
2023-06-12T16:07:15.981Z 76cdb4cc-ab3c-4826-ad9c-0caad518f6df info: EndMiddleware: End response. TotalTimeInMS=10 StatusCode=400 StatusMessage=undefined Headers={"server":"Azurite-Blob/3.23.0","access-control-expose-headers":"server,Date,Connection,Transfer-Encoding","access-control-allow-origin":"*"}
2023-06-12T16:07:16.040Z e0937588-2759-41c2-9b05-db0dbc0502b4 info: BlobStorageContextMiddleware: RequestMethod=GET RequestURL=http://127.0.0.1/devstoreaccount1/public/upload/00000000-0000-1000-a000-000000000001/56644b80-29cd-4343-b6ea-b98dc6a1d7d7/Satisfied-Seal.jpg RequestHeaders:{"host":"127.0.0.1:7777","connection":"keep-alive","sec-ch-ua":"\"Chromium\";v=\"113\", \"Not-A.Brand\";v=\"24\"","dnt":"1","sec-ch-ua-mobile":"?0","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36","sec-ch-ua-platform":"\"macOS\"","accept":"image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8","sec-fetch-site":"cross-site","sec-fetch-mode":"no-cors","sec-fetch-dest":"image","referer":"http://localhost:3000/","accept-encoding":"gzip, deflate, br","accept-language":"en-US,en;q=0.9,fr;q=0.8"} ClientIP=192.168.240.1 Protocol=http HTTPVersion=1.1
2023-06-12T16:07:16.040Z e0937588-2759-41c2-9b05-db0dbc0502b4 info: BlobStorageContextMiddleware: Account=devstoreaccount1 Container=public Blob=upload/00000000-0000-1000-a000-000000000001/56644b80-29cd-4343-b6ea-b98dc6a1d7d7/Satisfied-Seal.jpg
blueww commented 1 year ago

@thomasFranel It looks you are trying to upload a blob, but the request missed some required header like x-ms-blob-type, see detail in the rest API doc. So Azurite can't handle this request successfully.

Besides that, Azurite still not support blob query, see details in https://github.com/Azure/Azurite#support-matrix

thomasFranel commented 1 year ago

Oh thank you @blueww ! I didn't notice it needed this header ^^'

Do you know if that something Azurite will support at some point ?

blueww commented 1 year ago

@thomasFranel We are working on implement some other features that has more customer requests.

Azurite welcome contribution! It would be great if you can raise a PR to implement it! https://github.com/Azure/Azurite/blob/7ab45f7e5016b672eb8433443c395eba78213cbf/src/blob/handlers/BlobHandler.ts#L1242

thomasFranel commented 1 year ago

@blueww That can be a good idea ;)

I don't know if I have the knowledge to implement it but I can try, if that can help other people I'm in ;)

I'll just have to manage my schedule first (quite busy atm)