private async parseSubRequests()

in src/blob/handlers/BlobBatchHandler.ts [325:418]


  private async parseSubRequests(
    commonRequestId: string,
    perRequestPrefix: string,
    batchRequestEnding: string,
    subRequestPathPrefix: string,
    request: IRequest,
    body: string): Promise<BlobBatchSubRequest[]> {
    const requestAll = body.split(batchRequestEnding);
    const response1 = requestAll[0]; // string after ending is useless
    const response2 = response1.split(perRequestPrefix);
    const subRequests = response2.slice(1);

    const blobBatchSubRequests: BlobBatchSubRequest[] = [];

    let previousOperation: Operation | undefined;

    for (const subRequest of subRequests) {
      const requestLines = subRequest.split(`${HTTP_LINE_ENDING}`);

      // Content-Encoding
      // Content-Type
      // Content-ID
      // empty line
      // Operation infos
      if (requestLines.length < 5) throw new Error("Bad request");

      // Get Content_ID
      let lineIndex = 0;
      let content_id: number | undefined;

      while (lineIndex < requestLines.length) {
        if (requestLines[lineIndex] === '') break;
        const header = requestLines[lineIndex].split(HTTP_HEADER_DELIMITER, 2);

        if (header.length !== 2) throw new Error("Bad Request");

        if (header[0].toLocaleLowerCase() === "content-id") {
          content_id = parseInt(header[1], 10);
        }
        ++lineIndex;
      }

      if (content_id === undefined) throw new Error("Bad request");

      // "DELETE /container166063791875402779/blob0 HTTP/1.1"
      ++lineIndex;
      const operationInfos = requestLines[lineIndex].split(" ");
      if (operationInfos.length < 3) throw new Error("Bad request");

      const requestPath = operationInfos[1].startsWith("/") ? operationInfos[1] : "/" + operationInfos[1];

      if (!requestPath.startsWith(subRequestPathPrefix)) {
        throw new Error("Request from a different container");
      }

      const url = `${request.getEndpoint()}${requestPath}`;
      const method = operationInfos[0] as HttpMethod;
      const blobBatchSubRequest = new BlobBatchSubRequest(content_id!, url, method, operationInfos[2], {});

      ++lineIndex;
      while (lineIndex < requestLines.length) {
        if (requestLines[lineIndex] === '') break; // Last line
        const header = requestLines[lineIndex].split(HTTP_HEADER_DELIMITER, 2);

        if (header.length !== 2) throw new Error("Bad Request");
        blobBatchSubRequest.setHeader(header[0], header[1]);
        ++lineIndex;
      }
      const operation = await this.getSubRequestOperation(blobBatchSubRequest);
      if (operation !== Operation.Blob_Delete && operation !== Operation.Blob_SetTier) {
        throw new Error("Not supported operation");
      }

      if (previousOperation === undefined) {
        previousOperation = operation;
      }
      else if (operation !== previousOperation!) {
        throw new StorageError(
          400,
          "AllBatchSubRequestsShouldBeSameApi",
          "All batch subrequests should be the same api.",
          commonRequestId
        );
      }

      blobBatchSubRequests.push(blobBatchSubRequest);
    }

    if (blobBatchSubRequests.length === 0) {
      throw new Error("Bad Request");
    }

    return blobBatchSubRequests;
  }