From c195435d2b552a08ba73fd1b0642c9a1f8245dba Mon Sep 17 00:00:00 2001 From: Jeremy Meng Date: Wed, 21 Apr 2021 12:19:29 -0700 Subject: [PATCH 1/2] [core-client] expose allowInsecureConection in `ServiceClientOptions` and `OperationRequestOptions` to allow operation requests to HTTP endpoints --- sdk/core/core-client/CHANGELOG.md | 1 + sdk/core/core-client/review/core-client.api.md | 2 ++ sdk/core/core-client/src/interfaces.ts | 6 ++++++ sdk/core/core-client/src/serviceClient.ts | 14 ++++++++++++++ 4 files changed, 23 insertions(+) diff --git a/sdk/core/core-client/CHANGELOG.md b/sdk/core/core-client/CHANGELOG.md index 2ba31bda1b62..160331e2458f 100644 --- a/sdk/core/core-client/CHANGELOG.md +++ b/sdk/core/core-client/CHANGELOG.md @@ -2,6 +2,7 @@ ## 1.1.1 (Unreleased) +- Expose `allowInsecureConnection` in `ServiceClientOptions` and `OperationRequestOptions` to allow operation requests to HTTP endpoints ## 1.1.0 (2021-03-30) diff --git a/sdk/core/core-client/review/core-client.api.md b/sdk/core/core-client/review/core-client.api.md index 70e6d67461c0..5091d890876f 100644 --- a/sdk/core/core-client/review/core-client.api.md +++ b/sdk/core/core-client/review/core-client.api.md @@ -232,6 +232,7 @@ export interface OperationRequestInfo { // @public export interface OperationRequestOptions { + allowInsecureConnection?: boolean; customHeaders?: { [key: string]: string; }; @@ -350,6 +351,7 @@ export class ServiceClient { // @public export interface ServiceClientOptions extends CommonClientOptions { + allowInsecureConnection?: boolean; baseUri?: string; credential?: TokenCredential; credentialScopes?: string | string[]; diff --git a/sdk/core/core-client/src/interfaces.ts b/sdk/core/core-client/src/interfaces.ts index 4fe6a7b9979c..1250e111039b 100644 --- a/sdk/core/core-client/src/interfaces.ts +++ b/sdk/core/core-client/src/interfaces.ts @@ -139,11 +139,17 @@ export interface OperationRequestOptions { * Callback which fires upon download progress. */ onDownloadProgress?: (progress: TransferProgressEvent) => void; + /** * Whether or not the HttpOperationResponse should be deserialized. If this is undefined, then the * HttpOperationResponse should be deserialized. */ shouldDeserialize?: boolean | ((response: PipelineResponse) => boolean); + + /** + * Set to true if the request is sent over HTTP instead of HTTPS + */ + allowInsecureConnection?: boolean; } /** diff --git a/sdk/core/core-client/src/serviceClient.ts b/sdk/core/core-client/src/serviceClient.ts index f52be6bb485f..dc5bef86fc40 100644 --- a/sdk/core/core-client/src/serviceClient.ts +++ b/sdk/core/core-client/src/serviceClient.ts @@ -49,6 +49,10 @@ export interface ServiceClientOptions extends CommonClientOptions { * A customized pipeline to use, otherwise a default one will be created. */ pipeline?: Pipeline; + /** + * Set to true if the request is sent over HTTP instead of HTTPS + */ + allowInsecureConnection?: boolean; } /** @@ -67,6 +71,11 @@ export class ServiceClient { */ private readonly _requestContentType?: string; + /** + * Set to true if the request is sent over HTTP instead of HTTPS + */ + private readonly _allowInsecureConnection?: boolean; + /** * The HTTP client that will be used to send requests. */ @@ -85,6 +94,7 @@ export class ServiceClient { constructor(options: ServiceClientOptions = {}) { this._requestContentType = options.requestContentType; this._baseUri = options.baseUri; + this._allowInsecureConnection = options.allowInsecureConnection; this._httpClient = options.httpClient || getCachedDefaultHttpClient(); this.pipeline = options.pipeline || createDefaultPipeline(options); @@ -152,6 +162,10 @@ export class ServiceClient { if (requestOptions.shouldDeserialize !== undefined) { operationInfo.shouldDeserialize = requestOptions.shouldDeserialize; } + + if (this._allowInsecureConnection || requestOptions.allowInsecureConnection) { + request.allowInsecureConnection = true; + } } if (options.abortSignal) { From e806e604a4502a514492e5c9730d27643196f89c Mon Sep 17 00:00:00 2001 From: Jeremy Meng Date: Thu, 22 Apr 2021 15:59:34 -0700 Subject: [PATCH 2/2] Add tests --- sdk/core/core-client/src/serviceClient.ts | 6 +- .../core-client/test/serviceClient.spec.ts | 67 +++++++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/sdk/core/core-client/src/serviceClient.ts b/sdk/core/core-client/src/serviceClient.ts index dc5bef86fc40..9a7fdd2e1098 100644 --- a/sdk/core/core-client/src/serviceClient.ts +++ b/sdk/core/core-client/src/serviceClient.ts @@ -163,7 +163,7 @@ export class ServiceClient { operationInfo.shouldDeserialize = requestOptions.shouldDeserialize; } - if (this._allowInsecureConnection || requestOptions.allowInsecureConnection) { + if (requestOptions.allowInsecureConnection) { request.allowInsecureConnection = true; } } @@ -177,6 +177,10 @@ export class ServiceClient { } } + if (this._allowInsecureConnection) { + request.allowInsecureConnection = true; + } + if (request.streamResponseStatusCodes === undefined) { request.streamResponseStatusCodes = getStreamingResponseStatusCodes(operationSpec); } diff --git a/sdk/core/core-client/test/serviceClient.spec.ts b/sdk/core/core-client/test/serviceClient.spec.ts index 348ff1614712..69c72cb74de8 100644 --- a/sdk/core/core-client/test/serviceClient.spec.ts +++ b/sdk/core/core-client/test/serviceClient.spec.ts @@ -1098,6 +1098,73 @@ describe("ServiceClient", function() { const client = new ServiceClient(); assert.strictEqual((client as any)._httpClient, getCachedDefaultHttpClient()); }); + + it("should not allow insecure connection by default", async function() { + const operationSpec: OperationSpec = { + httpMethod: "GET", + responses: { + default: {} + }, + baseUrl: "http://example.com", + serializer: createSerializer() + }; + + const client = new ServiceClient({ + httpClient: { + sendRequest: (req) => { + assert.isFalse(req.allowInsecureConnection); + return Promise.resolve({ request: req, status: 200, headers: createHttpHeaders() }); + } + } + }); + await client.sendOperationRequest({}, operationSpec); + }); + + it("should allow insecure connection if configured via client options", async function() { + const operationSpec: OperationSpec = { + httpMethod: "GET", + responses: { + default: {} + }, + baseUrl: "http://example.com", + serializer: createSerializer() + }; + + const client = new ServiceClient({ + allowInsecureConnection: true, + httpClient: { + sendRequest: (req) => { + assert.isTrue(req.allowInsecureConnection); + return Promise.resolve({ request: req, status: 200, headers: createHttpHeaders() }); + } + } + }); + await client.sendOperationRequest({}, operationSpec); + }); + + it("should allow insecure connection if configured via request options", async function() { + const operationSpec: OperationSpec = { + httpMethod: "GET", + responses: { + default: {} + }, + baseUrl: "http://example.com", + serializer: createSerializer() + }; + + const client = new ServiceClient({ + httpClient: { + sendRequest: (req) => { + assert.isTrue(req.allowInsecureConnection); + return Promise.resolve({ request: req, status: 200, headers: createHttpHeaders() }); + } + } + }); + await client.sendOperationRequest( + { options: { requestOptions: { allowInsecureConnection: true } } }, + operationSpec + ); + }); }); async function testSendOperationRequest(