Skip to content
Open

Sfi #2608

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15,476 changes: 2,871 additions & 12,605 deletions package-lock.json

Large diffs are not rendered by default.

14 changes: 7 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@
"vscode": "^1.39.0"
},
"dependencies": {
"@azure/ms-rest-js": "^1.5.0",
"@azure/ms-rest-js": "^2.7.0",
"applicationinsights": "^2.9.6",
"args": "^5.0.1",
"axios": "^0.27.0",
"axios": "^0.30.0",
"etag": "^1.8.1",
"express": "^4.16.4",
"fs-extra": "^11.1.1",
Expand All @@ -36,7 +36,7 @@
"rimraf": "^3.0.2",
"sequelize": "^6.31.0",
"stoppable": "^1.1.0",
"tedious": "^16.7.0",
"tedious": "^18.6.1",
"to-readable-stream": "^2.1.0",
"tslib": "^2.3.0",
"uri-templates": "^0.2.0",
Expand All @@ -48,8 +48,8 @@
"@azure/core-auth": "^1.3.2",
"@azure/core-rest-pipeline": "^1.2.0",
"@azure/data-tables": "^13.0.1",
"@azure/storage-blob": "^12.9.0",
"@azure/storage-queue": "^12.8.0",
"@azure/storage-blob": "^12.28.0",
"@azure/storage-queue": "^12.27.0",
"@types/args": "^5.0.0",
"@types/async": "^3.0.1",
"@types/bluebird": "^3.5.27",
Expand All @@ -73,7 +73,6 @@
"@typescript-eslint/eslint-plugin": "^5.54.1",
"@typescript-eslint/parser": "^5.54.1",
"autorest": "^3.6.0",
"azure-storage": "^2.10.3",
"cross-env": "^7.0.3",
"cross-var": "^1.1.0",
"eslint": "^8.35.0",
Expand All @@ -87,7 +86,8 @@
"ts-mockito": "^2.6.1",
"ts-node": "^10.0.0",
"typescript": "^5.0.3",
"vsce": "^2.7.0"
"vsce": "^2.7.0",
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

azure-storage has been removed from devDependencies, but the test suite still imports it in multiple places (e.g. tests/exe.test.ts, several tests/table/** files). This will cause install/build/test failures. Either keep azure-storage until the table tests are migrated off it, or update the remaining tests and utilities to remove the dependency in the same PR.

Suggested change
"vsce": "^2.7.0",
"vsce": "^2.7.0",
"azure-storage": "^2.10.7",

Copilot uses AI. Check for mistakes.
"@azure/identity": "^4.2.1"
},
"activationEvents": [
"onStartupFinished"
Expand Down
13 changes: 6 additions & 7 deletions src/blob/authentication/BlobSharedKeyAuthenticator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export default class BlobSharedKeyAuthenticator implements IAuthenticator {
public constructor(
private readonly dataStore: IAccountDataStore,
private readonly logger: ILogger
) {}
) { }

public async validate(
req: IRequest,
Expand Down Expand Up @@ -77,8 +77,8 @@ export default class BlobSharedKeyAuthenticator implements IAuthenticator {
const stringToSign: string =
[
req.getMethod().toUpperCase(),
this.getHeaderValueToSign(req, HeaderConstants.CONTENT_ENCODING),
this.getHeaderValueToSign(req, HeaderConstants.CONTENT_LANGUAGE),
this.getHeaderValueToSign(req, HeaderConstants.CONTENT_ENCODING),
Comment on lines 80 to +81
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The shared-key string-to-sign header order looks incorrect: Content-Language is currently appended before Content-Encoding. For Azure Storage SharedKey auth, the canonical string should include Content-Encoding before Content-Language. Swapping these will cause signature mismatches whenever either header is present.

Suggested change
this.getHeaderValueToSign(req, HeaderConstants.CONTENT_LANGUAGE),
this.getHeaderValueToSign(req, HeaderConstants.CONTENT_ENCODING),
this.getHeaderValueToSign(req, HeaderConstants.CONTENT_ENCODING),
this.getHeaderValueToSign(req, HeaderConstants.CONTENT_LANGUAGE),

Copilot uses AI. Check for mistakes.
this.getHeaderValueToSign(req, HeaderConstants.CONTENT_LENGTH),
this.getHeaderValueToSign(req, HeaderConstants.CONTENT_MD5),
this.getHeaderValueToSign(req, HeaderConstants.CONTENT_TYPE),
Expand Down Expand Up @@ -137,10 +137,9 @@ export default class BlobSharedKeyAuthenticator implements IAuthenticator {
}
}

if (context.context.isSecondary && blobContext.authenticationPath?.indexOf(account) === 1)
{
// JS/.net Track2 SDK will generate stringToSign from IP style URI with "-secondary" in authenticationPath, so will also compare signature with this kind stringToSign
const stringToSign_secondary: string =
if (context.context.isSecondary && blobContext.authenticationPath?.indexOf(account) === 1) {
// JS/.net Track2 SDK will generate stringToSign from IP style URI with "-secondary" in authenticationPath, so will also compare signature with this kind stringToSign
const stringToSign_secondary: string =
[
req.getMethod().toUpperCase(),
this.getHeaderValueToSign(req, HeaderConstants.CONTENT_ENCODING),
Expand Down Expand Up @@ -171,7 +170,7 @@ export default class BlobSharedKeyAuthenticator implements IAuthenticator {
blobContext.contextId
);

const signature1_secondary= computeHMACSHA256(stringToSign_secondary, accountProperties.key1);
const signature1_secondary = computeHMACSHA256(stringToSign_secondary, accountProperties.key1);
const authValue1_secondary = `SharedKey ${account}:${signature1_secondary}`;
this.logger.info(
`BlobSharedKeyAuthenticator:validate() Calculated authentication header based on key1 and stringToSign with "-secondary": ${authValue1_secondary}`,
Expand Down
10 changes: 8 additions & 2 deletions src/blob/generated/ExpressRequestAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Request } from 'express';
import IRequest, { HttpMethod } from './IRequest';

export default class ExpressRequestAdapter implements IRequest {
public constructor(private readonly req: Request) {}
public constructor(private readonly req: Request) { }

public getMethod(): HttpMethod {
return this.req.method.toUpperCase() as HttpMethod;
Expand Down Expand Up @@ -48,7 +48,13 @@ export default class ExpressRequestAdapter implements IRequest {
}

public getQuery(key: string): string | undefined {
return this.req.query[key];
const queryValue = this.req.query[key];
if ((typeof queryValue) === "string") {
return queryValue;
}
else {
return undefined;
}
}

public getProtocol(): string {
Expand Down
1 change: 0 additions & 1 deletion src/blob/generated/artifacts/parameters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,6 @@ export const blobSequenceNumber: msRest.OperationParameter = {
],
mapper: {
serializedName: "x-ms-blob-sequence-number",
defaultValue: 0,
type: {
name: "Number"
}
Expand Down
4 changes: 1 addition & 3 deletions src/blob/generated/utils/xml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ import * as xml2js from 'xml2js';

export function stringifyXML(obj: any, opts?: { rootName?: string }) {
const builder = new xml2js.Builder({
explicitArray: false,
explicitCharkey: false,
renderOpts: {
pretty: false
},
Expand All @@ -25,7 +23,7 @@ export function parseXML(
emptyTag: undefined
});
return new Promise((resolve, reject) => {
xmlParser.parseString(str, (err?: Error, res?: any) => {
xmlParser.parseString(str, (err?: Error | null, res?: any) => {
if (err) {
reject(err);
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/blob/handlers/AppendBlobHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ export default class AppendBlobHandler extends BaseHandler
requestId: context.contextId,
eTag: properties.etag,
lastModified: properties.lastModified,
contentMD5: contentMD5Buffer,
contentMD5: contentMD5Buffer ? new Uint8Array(contentMD5Buffer) : undefined,
xMsContentCrc64: undefined,
clientRequestId: options.requestId,
version: BLOB_API_VERSION,
Expand Down
2 changes: 1 addition & 1 deletion src/blob/handlers/BlobBatchHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ export class BlobBatchHandler {
return;
}

buffer.fill(chunk, pos, pos + chunk.length);
buffer.fill(new Uint8Array(chunk), pos, pos + chunk.length);
pos += chunk.length;
});

Expand Down
4 changes: 2 additions & 2 deletions src/blob/handlers/BlobBatchSubResponse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,11 @@ export class BlobBatchSubResponse implements IResponse {
return this.bodyStream;
}

public getBodyContent(): string{
public getBodyContent(): string {
return this.bodyStream.getBodyContent();
}

public end(): void{
public end(): void {
this.setStatusMessage(STATUS_CODES[this.statusCode!] || 'unknown');
}
}
12 changes: 6 additions & 6 deletions src/blob/handlers/SubResponseTextBodyStream.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { Writable } from "stream";
import { BlobBatchSubResponse } from "./BlobBatchSubResponse";

export class SubResponseTextBodyStream extends Writable
{
export class SubResponseTextBodyStream extends Writable {
private bodyText: string;
public constructor(
private readonly subResponse: BlobBatchSubResponse) {
Expand All @@ -15,12 +14,13 @@ export class SubResponseTextBodyStream extends Writable
callback();
}

public end(cb?: (() => void) | undefined): void;
public end(chunk: any, cb?: (() => void) | undefined): void;
public end(chunk: any, encoding: BufferEncoding, cb?: (() => void) | undefined): void;
public end(chunk?: unknown, encoding?: unknown, cb?: unknown): void {
public end(cb?: (() => void) | undefined): this;
public end(chunk: any, cb?: (() => void) | undefined): this;
public end(chunk: any, encoding: BufferEncoding, cb?: (() => void) | undefined): this;
public end(chunk?: unknown, encoding?: unknown, cb?: unknown): this {
if (chunk) this.bodyText += (chunk! as any).toString();
this.subResponse.end();
return this;
Comment on lines 21 to +23
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SubResponseTextBodyStream.end(...) overrides Writable.end but doesn't delegate to super.end(...) or invoke the optional callback. This can break expected stream semantics (e.g., finish events / callback-based completion) and may cause hangs if any caller relies on the callback. Consider calling super.end(chunk as any, encoding as any, cb as any) and only then notifying subResponse.end() (or wrapping it in the callback).

Suggested change
if (chunk) this.bodyText += (chunk! as any).toString();
this.subResponse.end();
return this;
let finalChunk = chunk;
let finalEncoding = encoding;
let finalCallback = cb as (() => void) | undefined;
if (typeof finalChunk === "function") {
finalCallback = finalChunk as () => void;
finalChunk = undefined;
finalEncoding = undefined;
} else if (typeof finalEncoding === "function") {
finalCallback = finalEncoding as () => void;
finalEncoding = undefined;
}
const wrappedCallback = () => {
this.subResponse.end();
if (finalCallback) {
finalCallback();
}
};
return super.end(finalChunk as any, finalEncoding as any, wrappedCallback as any);

Copilot uses AI. Check for mistakes.
}

public getBodyContent(): string {
Expand Down
5 changes: 3 additions & 2 deletions src/blob/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ function shutdown(server: BlobServer | SqlBlobServer) {
});
}


/**
* Entry for Azurite blob service.
*/
Expand All @@ -45,9 +46,9 @@ async function main() {
console.log(
`Azurite Blob service successfully listens on ${server.getHttpServerAddress()}`
);

const location = await env.location();
AzuriteTelemetryClient.init(location, !env.disableTelemetry(), env);
AzuriteTelemetryClient.init(location, !env.disableTelemetry(), env);
await AzuriteTelemetryClient.TraceStartEvent("Blob");

// Handle close event
Expand Down
10 changes: 3 additions & 7 deletions src/blob/persistence/LokiBlobMetadataStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3113,12 +3113,8 @@ export default class LokiBlobMetadataStore
return undefined;
}

if (obj instanceof Uint8Array) {
return obj;
}

if (obj.type === "Buffer") {
obj = obj.data;
if (obj instanceof Buffer) {
return new Uint8Array(obj);
}

const length = Object.keys(obj).length;
Expand All @@ -3134,7 +3130,7 @@ export default class LokiBlobMetadataStore
arr[i] = obj[i];
}

return arr;
return new Uint8Array(arr);
}

/**
Expand Down
Loading
Loading