From e24d0855454188cedaf5e48c6507650500b823f8 Mon Sep 17 00:00:00 2001
From: Qiaoqiao Zhang <55688292+qiaozha@users.noreply.github.com>
Date: Fri, 30 Jun 2023 08:34:24 +0800
Subject: [PATCH] Add some other request options (#26331)
fixes https://github.com/Azure/autorest.typescript/issues/1902
This PR is trying to map the
[OperationOptions](https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-client/src/interfaces.ts#L98-L122)
from @azure/core-client to
[RequestParameters](https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-client-rest/src/common.ts#L19-L51)
in @azure-rest/core-client.
As the API layer internally call rest layer, we should provide every
functionality that the high level core-client @azure-rest/core-client
has and map them to the rest level core-client @azure-rest/core-client.
right now I have added `abortSignal`, `tracingOptions`, `onResponse`
into the RequestParameters.
```typescript
/**
* The signal which can be used to abort requests.
*/
abortSignal?: AbortSignalLike;
/**
* Options used when tracing is enabled.
*/
tracingOptions?: OperationTracingOptions;
/**
* A function to be called each time a response is received from the server
* while performing the requested operation.
* May be called multiple times.
*/
onResponse?: RawResponseCallback;
```
And inside the `requestOptions`, I have added `timeout`,
`onUploadProgress`, `onDownloadProgress` and flattened it in the top
level of `RequestParameters`
```typescript
/**
* The number of milliseconds a request can take before automatically being terminated.
*/
timeout?: number;
/**
* Callback which fires upon upload progress.
*/
onUploadProgress?: (progress: TransferProgressEvent) => void;
/**
* Callback which fires upon download progress.
*/
onDownloadProgress?: (progress: TransferProgressEvent) => void;
```
Also, add an interface OperationOptions in @azure-rest/core-client, for
modular usage in specify these options.
```typescript
export interface OperationOptions {
/**
* The signal which can be used to abort requests.
*/
abortSignal?: AbortSignalLike;
/**
* Options used when creating and sending HTTP requests for this operation.
*/
requestOptions?: OperationRequestOptions;
/**
* Options used when tracing is enabled.
*/
tracingOptions?: OperationTracingOptions;
/**
* A function to be called each time a response is received from the server
* while performing the requested operation.
* May be called multiple times.
*/
onResponse?: RawResponseCallback;
}
```
---
sdk/core/core-client-rest/CHANGELOG.md | 7 +-
sdk/core/core-client-rest/package.json | 2 +
.../review/core-client.api.md | 42 ++++++
sdk/core/core-client-rest/src/common.ts | 126 ++++++++++++++++++
sdk/core/core-client-rest/src/index.ts | 1 +
.../src/operationOptionHelpers.ts | 23 ++++
sdk/core/core-client-rest/src/sendRequest.ts | 11 ++
7 files changed, 207 insertions(+), 5 deletions(-)
create mode 100644 sdk/core/core-client-rest/src/operationOptionHelpers.ts
diff --git a/sdk/core/core-client-rest/CHANGELOG.md b/sdk/core/core-client-rest/CHANGELOG.md
index 424e5e8d36ae..0a0382bfc524 100644
--- a/sdk/core/core-client-rest/CHANGELOG.md
+++ b/sdk/core/core-client-rest/CHANGELOG.md
@@ -4,11 +4,8 @@
### Features Added
-### Breaking Changes
-
-### Bugs Fixed
-
-### Other Changes
+- Add `timeout`, `onUploadProgress`, `onDownloadProgress`, `abortSignal`, `tracingOptions`, `onResponse` in the `RequestParameters` for better RLC user experience.
+- Add `OperationOptions` for better modular user experience.
## 1.1.3 (2023-05-04)
diff --git a/sdk/core/core-client-rest/package.json b/sdk/core/core-client-rest/package.json
index b607bcbf26b8..8d1f7f911bd5 100644
--- a/sdk/core/core-client-rest/package.json
+++ b/sdk/core/core-client-rest/package.json
@@ -59,6 +59,8 @@
"@azure/core-auth": "^1.3.0",
"@azure/core-rest-pipeline": "^1.5.0",
"@azure/core-util": "^1.0.0",
+ "@azure/abort-controller": "^1.1.0",
+ "@azure/core-tracing": "^1.0.1",
"tslib": "^2.2.0"
},
"devDependencies": {
diff --git a/sdk/core/core-client-rest/review/core-client.api.md b/sdk/core/core-client-rest/review/core-client.api.md
index 8e936042b204..be4721f43513 100644
--- a/sdk/core/core-client-rest/review/core-client.api.md
+++ b/sdk/core/core-client-rest/review/core-client.api.md
@@ -6,17 +6,22 @@
///
+import { AbortSignalLike } from '@azure/abort-controller';
import { HttpClient } from '@azure/core-rest-pipeline';
import { KeyCredential } from '@azure/core-auth';
import { LogPolicyOptions } from '@azure/core-rest-pipeline';
+import { OperationTracingOptions } from '@azure/core-tracing';
import { Pipeline } from '@azure/core-rest-pipeline';
import { PipelineOptions } from '@azure/core-rest-pipeline';
import { PipelinePolicy } from '@azure/core-rest-pipeline';
import { PipelineRequest } from '@azure/core-rest-pipeline';
+import { PipelineResponse } from '@azure/core-rest-pipeline';
import { RawHttpHeaders } from '@azure/core-rest-pipeline';
import { RawHttpHeadersInput } from '@azure/core-rest-pipeline';
+import { RequestBodyType } from '@azure/core-rest-pipeline';
import { RestError } from '@azure/core-rest-pipeline';
import { TokenCredential } from '@azure/core-auth';
+import { TransferProgressEvent } from '@azure/core-rest-pipeline';
// @public
export function addCredentialPipelinePolicy(pipeline: Pipeline, baseUrl: string, options?: AddCredentialPipelinePolicyOptions): void;
@@ -71,6 +76,13 @@ export interface ErrorResponse {
error: ErrorModel;
}
+// @public
+export interface FullOperationResponse extends PipelineResponse {
+ parsedBody?: RequestBodyType;
+ rawHeaders?: RawHttpHeaders;
+ request: PipelineRequest;
+}
+
// @public
export function getClient(baseUrl: string, options?: ClientOptions): Client;
@@ -101,6 +113,27 @@ export interface InnerError {
innererror?: InnerError;
}
+// @public
+export interface OperationOptions {
+ abortSignal?: AbortSignalLike;
+ onResponse?: RawResponseCallback;
+ requestOptions?: OperationRequestOptions;
+ tracingOptions?: OperationTracingOptions;
+}
+
+// @public
+export function operationOptionsToRequestParameters(options: OperationOptions): RequestParameters;
+
+// @public
+export interface OperationRequestOptions {
+ allowInsecureConnection?: boolean;
+ headers?: RawHttpHeadersInput;
+ onDownloadProgress?: (progress: TransferProgressEvent) => void;
+ onUploadProgress?: (progress: TransferProgressEvent) => void;
+ skipUrlEncoding?: boolean;
+ timeout?: number;
+}
+
// @public
export type PathParameters = TRoute extends `${infer _Head}/{${infer _Param}}${infer Tail}` ? [
pathParameter: string,
@@ -116,6 +149,9 @@ export type PathUncheckedResponse = HttpResponse & {
body: any;
};
+// @public
+export type RawResponseCallback = (rawResponse: FullOperationResponse, error?: unknown) => void;
+
// @public
export type RequestParameters = {
headers?: RawHttpHeadersInput;
@@ -126,6 +162,12 @@ export type RequestParameters = {
allowInsecureConnection?: boolean;
skipUrlEncoding?: boolean;
pathParameters?: Record;
+ timeout?: number;
+ onUploadProgress?: (progress: TransferProgressEvent) => void;
+ onDownloadProgress?: (progress: TransferProgressEvent) => void;
+ abortSignal?: AbortSignalLike;
+ tracingOptions?: OperationTracingOptions;
+ onResponse?: RawResponseCallback;
};
// @public
diff --git a/sdk/core/core-client-rest/src/common.ts b/sdk/core/core-client-rest/src/common.ts
index 2e2b82df8dde..c2f3f51bc210 100644
--- a/sdk/core/core-client-rest/src/common.ts
+++ b/sdk/core/core-client-rest/src/common.ts
@@ -8,9 +8,14 @@ import {
PipelineOptions,
PipelinePolicy,
PipelineRequest,
+ PipelineResponse,
RawHttpHeaders,
+ RequestBodyType,
+ TransferProgressEvent,
} from "@azure/core-rest-pipeline";
import { RawHttpHeadersInput } from "@azure/core-rest-pipeline";
+import { AbortSignalLike } from "@azure/abort-controller";
+import { OperationTracingOptions } from "@azure/core-tracing";
/**
* Shape of the default request parameters, this may be overriden by the specific
@@ -48,8 +53,129 @@ export type RequestParameters = {
* Path parameters for custom the base url
*/
pathParameters?: Record;
+
+ /**
+ * The number of milliseconds a request can take before automatically being terminated.
+ */
+ timeout?: number;
+
+ /**
+ * Callback which fires upon upload progress.
+ */
+ onUploadProgress?: (progress: TransferProgressEvent) => void;
+
+ /**
+ * Callback which fires upon download progress.
+ */
+ onDownloadProgress?: (progress: TransferProgressEvent) => void;
+
+ /**
+ * The signal which can be used to abort requests.
+ */
+ abortSignal?: AbortSignalLike;
+
+ /**
+ * Options used when tracing is enabled.
+ */
+ tracingOptions?: OperationTracingOptions;
+
+ /**
+ * A function to be called each time a response is received from the server
+ * while performing the requested operation.
+ * May be called multiple times.
+ */
+ onResponse?: RawResponseCallback;
};
+/**
+ * A function to be called each time a response is received from the server
+ * while performing the requested operation.
+ * May be called multiple times.
+ */
+export type RawResponseCallback = (rawResponse: FullOperationResponse, error?: unknown) => void;
+
+/**
+ * Wrapper object for http request and response. Deserialized object is stored in
+ * the `parsedBody` property when the response body is received in JSON.
+ */
+export interface FullOperationResponse extends PipelineResponse {
+ /**
+ * The raw HTTP response headers.
+ */
+ rawHeaders?: RawHttpHeaders;
+
+ /**
+ * The response body as parsed JSON.
+ */
+ parsedBody?: RequestBodyType;
+
+ /**
+ * The request that generated the response.
+ */
+ request: PipelineRequest;
+}
+
+/**
+ * The base options type for all operations.
+ */
+export interface OperationOptions {
+ /**
+ * The signal which can be used to abort requests.
+ */
+ abortSignal?: AbortSignalLike;
+ /**
+ * Options used when creating and sending HTTP requests for this operation.
+ */
+ requestOptions?: OperationRequestOptions;
+ /**
+ * Options used when tracing is enabled.
+ */
+ tracingOptions?: OperationTracingOptions;
+
+ /**
+ * A function to be called each time a response is received from the server
+ * while performing the requested operation.
+ * May be called multiple times.
+ */
+ onResponse?: RawResponseCallback;
+}
+
+/**
+ * Options used when creating and sending HTTP requests for this operation.
+ */
+export interface OperationRequestOptions {
+ /**
+ * User defined custom request headers that
+ * will be applied before the request is sent.
+ */
+ headers?: RawHttpHeadersInput;
+
+ /**
+ * The number of milliseconds a request can take before automatically being terminated.
+ */
+ timeout?: number;
+
+ /**
+ * Callback which fires upon upload progress.
+ */
+ onUploadProgress?: (progress: TransferProgressEvent) => void;
+
+ /**
+ * Callback which fires upon download progress.
+ */
+ onDownloadProgress?: (progress: TransferProgressEvent) => void;
+
+ /**
+ * Set to true if the request is sent over HTTP instead of HTTPS
+ */
+ allowInsecureConnection?: boolean;
+
+ /**
+ * Set to true if you want to skip encoding the path parameters
+ */
+ skipUrlEncoding?: boolean;
+}
+
/**
* Type to use with pathUnchecked, overrides the body type to any to allow flexibility
*/
diff --git a/sdk/core/core-client-rest/src/index.ts b/sdk/core/core-client-rest/src/index.ts
index 1af1becfebd4..046849c9f07b 100644
--- a/sdk/core/core-client-rest/src/index.ts
+++ b/sdk/core/core-client-rest/src/index.ts
@@ -8,5 +8,6 @@
export { createRestError } from "./restError";
export { addCredentialPipelinePolicy, AddCredentialPipelinePolicyOptions } from "./clientHelpers";
+export { operationOptionsToRequestParameters } from "./operationOptionHelpers";
export * from "./getClient";
export * from "./common";
diff --git a/sdk/core/core-client-rest/src/operationOptionHelpers.ts b/sdk/core/core-client-rest/src/operationOptionHelpers.ts
new file mode 100644
index 000000000000..21cb63127a52
--- /dev/null
+++ b/sdk/core/core-client-rest/src/operationOptionHelpers.ts
@@ -0,0 +1,23 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+import { OperationOptions, RequestParameters } from "./common";
+
+/**
+ * Helper function to convert OperationOptions to RequestParameters
+ * @param options - the options that are used by Modular layer to send the request
+ * @returns the result of the conversion in RequestParameters of RLC layer
+ */
+export function operationOptionsToRequestParameters(options: OperationOptions): RequestParameters {
+ return {
+ allowInsecureConnection: options.requestOptions?.allowInsecureConnection,
+ timeout: options.requestOptions?.timeout,
+ skipUrlEncoding: options.requestOptions?.skipUrlEncoding,
+ abortSignal: options.abortSignal,
+ onUploadProgress: options.requestOptions?.onUploadProgress,
+ onDownloadProgress: options.requestOptions?.onDownloadProgress,
+ tracingOptions: options.tracingOptions,
+ headers: { ...options.requestOptions?.headers },
+ onResponse: options.onResponse,
+ };
+}
diff --git a/sdk/core/core-client-rest/src/sendRequest.ts b/sdk/core/core-client-rest/src/sendRequest.ts
index 4c90da57b7e8..641b0a9b8178 100644
--- a/sdk/core/core-client-rest/src/sendRequest.ts
+++ b/sdk/core/core-client-rest/src/sendRequest.ts
@@ -37,11 +37,17 @@ export async function sendRequest(
): Promise {
const httpClient = customHttpClient ?? getCachedDefaultHttpsClient();
const request = buildPipelineRequest(method, url, options);
+
const response = await pipeline.sendRequest(httpClient, request);
+
const rawHeaders: RawHttpHeaders = response.headers.toJSON();
const parsedBody: RequestBodyType | undefined = getResponseBody(response);
+ if (options?.onResponse) {
+ options.onResponse({ ...response, request, rawHeaders, parsedBody });
+ }
+
return {
request,
headers: rawHeaders,
@@ -127,6 +133,11 @@ function buildPipelineRequest(
formData,
headers,
allowInsecureConnection: options.allowInsecureConnection,
+ tracingOptions: options.tracingOptions,
+ abortSignal: options.abortSignal,
+ onUploadProgress: options.onUploadProgress,
+ onDownloadProgress: options.onDownloadProgress,
+ timeout: options.timeout,
enableBrowserStreams: true,
streamResponseStatusCodes: options.responseAsStream
? new Set([Number.POSITIVE_INFINITY])