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;
}