Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit be134f5

Browse files
authored
[core-client] Switch _response property for callback. (Azure#13132)
* Switch _response property for callback.
1 parent 1defe37 commit be134f5

File tree

5 files changed

+66
-53
lines changed

5 files changed

+66
-53
lines changed

sdk/core/core-client/review/core-client.api.md

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ export interface OperationArguments {
202202
// @public
203203
export interface OperationOptions {
204204
abortSignal?: AbortSignalLike;
205+
onResponse?: RawResponseCallback;
205206
requestOptions?: OperationRequestOptions;
206207
serializerOptions?: SerializerOptions;
207208
tracingOptions?: OperationTracingOptions;
@@ -241,13 +242,6 @@ export interface OperationRequestOptions {
241242
timeout?: number;
242243
}
243244

244-
// @public
245-
export interface OperationResponse {
246-
// (undocumented)
247-
[key: string]: any;
248-
_response: FullOperationResponse;
249-
}
250-
251245
// @public
252246
export interface OperationResponseMap {
253247
bodyMapper?: Mapper;
@@ -297,6 +291,9 @@ export interface PolymorphicDiscriminator {
297291
// @public
298292
export type QueryCollectionFormat = "CSV" | "SSV" | "TSV" | "Pipes" | "Multi";
299293

294+
// @public
295+
export type RawResponseCallback = (rawResponse: FullOperationResponse, flatResponse: unknown) => void;
296+
300297
// @public (undocumented)
301298
export interface SequenceMapper extends BaseMapper {
302299
// (undocumented)
@@ -347,7 +344,7 @@ export interface SerializerOptions {
347344
// @public
348345
export class ServiceClient {
349346
constructor(options?: ServiceClientOptions);
350-
sendOperationRequest(operationArguments: OperationArguments, operationSpec: OperationSpec): Promise<OperationResponse>;
347+
sendOperationRequest<T>(operationArguments: OperationArguments, operationSpec: OperationSpec): Promise<T>;
351348
sendRequest(request: PipelineRequest): Promise<PipelineResponse>;
352349
}
353350

sdk/core/core-client/src/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,14 @@ export {
3636
OperationRequestInfo,
3737
QueryCollectionFormat,
3838
ParameterPath,
39-
OperationResponse,
4039
FullOperationResponse,
4140
PolymorphicDiscriminator,
4241
SpanConfig,
4342
XML_ATTRKEY,
4443
XML_CHARKEY,
4544
XmlOptions,
46-
SerializerOptions
45+
SerializerOptions,
46+
RawResponseCallback
4747
} from "./interfaces";
4848
export {
4949
deserializationPolicy,

sdk/core/core-client/src/interfaces.ts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,13 @@ export interface OperationOptions {
105105
* Options to override serialization/de-serialization behavior.
106106
*/
107107
serializerOptions?: SerializerOptions;
108+
109+
/**
110+
* A function to be called each time a response is received from the server
111+
* while performing the requested operation.
112+
* May be called multiple times.
113+
*/
114+
onResponse?: RawResponseCallback;
108115
}
109116

110117
/**
@@ -333,17 +340,14 @@ export interface FullOperationResponse extends PipelineResponse {
333340
}
334341

335342
/**
336-
* The processed and flattened response to an operation call.
337-
* Contains merged properties of the parsed body and headers.
343+
* A function to be called each time a response is received from the server
344+
* while performing the requested operation.
345+
* May be called multiple times.
338346
*/
339-
export interface OperationResponse {
340-
/**
341-
* The underlying HTTP response containing both raw and deserialized response data.
342-
*/
343-
_response: FullOperationResponse;
344-
345-
[key: string]: any;
346-
}
347+
export type RawResponseCallback = (
348+
rawResponse: FullOperationResponse,
349+
flatResponse: unknown
350+
) => void;
347351

348352
/**
349353
* Used to map raw response objects to final shapes.

sdk/core/core-client/src/serviceClient.ts

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import {
1313
InternalPipelineOptions
1414
} from "@azure/core-https";
1515
import {
16-
OperationResponse,
1716
OperationArguments,
1817
OperationSpec,
1918
OperationRequest,
@@ -125,13 +124,14 @@ export class ServiceClient {
125124

126125
/**
127126
* Send an HTTP request that is populated using the provided OperationSpec.
127+
* @typeParam T The typed result of the request, based on the OperationSpec.
128128
* @param {OperationArguments} operationArguments The arguments that the HTTP request's templated values will be populated from.
129129
* @param {OperationSpec} operationSpec The OperationSpec to use to populate the httpRequest.
130130
*/
131-
async sendOperationRequest(
131+
async sendOperationRequest<T>(
132132
operationArguments: OperationArguments,
133133
operationSpec: OperationSpec
134-
): Promise<OperationResponse> {
134+
): Promise<T> {
135135
const baseUri: string | undefined = operationSpec.baseUrl || this._baseUri;
136136
if (!baseUri) {
137137
throw new Error(
@@ -200,7 +200,14 @@ export class ServiceClient {
200200

201201
try {
202202
const rawResponse = await this.sendRequest(request);
203-
return flattenResponse(rawResponse, operationSpec.responses[rawResponse.status]);
203+
const flatResponse = flattenResponse(
204+
rawResponse,
205+
operationSpec.responses[rawResponse.status]
206+
) as T;
207+
if (options?.onResponse) {
208+
options.onResponse(rawResponse, flatResponse);
209+
}
210+
return flatResponse;
204211
} catch (error) {
205212
if (error.response) {
206213
error.details = flattenResponse(
@@ -285,29 +292,18 @@ export function createClientPipeline(options: ClientPipelineOptions = {}): Pipel
285292
function flattenResponse(
286293
fullResponse: FullOperationResponse,
287294
responseSpec: OperationResponseMap | undefined
288-
): OperationResponse {
295+
): unknown {
289296
const parsedHeaders = fullResponse.parsedHeaders;
290297
const bodyMapper = responseSpec && responseSpec.bodyMapper;
291298

292-
function addResponse<T extends object>(
293-
obj: T
294-
): T & { readonly _response: FullOperationResponse } {
295-
return Object.defineProperty(obj, "_response", {
296-
configurable: false,
297-
enumerable: false,
298-
writable: false,
299-
value: fullResponse
300-
});
301-
}
302-
303299
if (bodyMapper) {
304300
const typeName = bodyMapper.type.name;
305301
if (typeName === "Stream") {
306-
return addResponse({
302+
return {
307303
...parsedHeaders,
308304
blobBody: fullResponse.blobBody,
309305
readableStreamBody: fullResponse.readableStreamBody
310-
});
306+
};
311307
}
312308

313309
const modelProperties =
@@ -330,14 +326,14 @@ function flattenResponse(
330326
arrayResponse[key] = parsedHeaders[key];
331327
}
332328
}
333-
return addResponse(arrayResponse);
329+
return arrayResponse;
334330
}
335331

336332
if (typeName === "Composite" || typeName === "Dictionary") {
337-
return addResponse({
333+
return {
338334
...parsedHeaders,
339335
...fullResponse.parsedBody
340-
});
336+
};
341337
}
342338
}
343339

@@ -346,16 +342,16 @@ function flattenResponse(
346342
fullResponse.request.method === "HEAD" ||
347343
isPrimitiveType(fullResponse.parsedBody)
348344
) {
349-
return addResponse({
345+
return {
350346
...parsedHeaders,
351347
body: fullResponse.parsedBody
352-
});
348+
};
353349
}
354350

355-
return addResponse({
351+
return {
356352
...parsedHeaders,
357353
...fullResponse.parsedBody
358-
});
354+
};
359355
}
360356

361357
function getCredentialScopes(options: ServiceClientOptions): string | string[] | undefined {

sdk/core/core-client/test/serviceClient.spec.ts

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ import {
1414
Mapper,
1515
CompositeMapper,
1616
OperationSpec,
17-
serializationPolicy
17+
serializationPolicy,
18+
FullOperationResponse
1819
} from "../src";
1920
import {
2021
createHttpHeaders,
@@ -249,20 +250,26 @@ describe("ServiceClient", function() {
249250
assert.deepEqual(request!.headers.toJSON(), expected);
250251
});
251252

252-
it("responses should not show the _response property when serializing", async function() {
253+
it("should call rawResponseCallback with the full response", async function() {
253254
let request: OperationRequest;
254255
const client = new ServiceClient({
255256
httpsClient: {
256257
sendRequest: (req) => {
257258
request = req;
258-
return Promise.resolve({ request, status: 200, headers: createHttpHeaders() });
259+
return Promise.resolve({
260+
request,
261+
status: 200,
262+
headers: createHttpHeaders({ "X-Extra-Info": "foo" })
263+
});
259264
}
260265
},
261266
pipeline: createEmptyPipeline()
262267
});
263268

269+
let rawResponse: FullOperationResponse | undefined;
270+
264271
const response = await client.sendOperationRequest(
265-
{},
272+
{ options: { onResponse: (response) => (rawResponse = response) } },
266273
{
267274
httpMethod: "GET",
268275
baseUrl: "https://example.com",
@@ -275,8 +282,10 @@ describe("ServiceClient", function() {
275282
);
276283

277284
assert(request!);
278-
// _response should be not enumerable
279285
assert.strictEqual(JSON.stringify(response), "{}");
286+
assert.strictEqual(rawResponse?.status, 200);
287+
assert.strictEqual(rawResponse?.request, request!);
288+
assert.strictEqual(rawResponse?.headers.get("X-Extra-Info"), "foo");
280289
});
281290

282291
it("should serialize collection:csv query parameters", async function() {
@@ -336,8 +345,15 @@ describe("ServiceClient", function() {
336345
pipeline
337346
});
338347

339-
const res = await client1.sendOperationRequest(
340-
{},
348+
let rawResponse: FullOperationResponse | undefined;
349+
const res = await client1.sendOperationRequest<Array<number>>(
350+
{
351+
options: {
352+
onResponse: (response) => {
353+
rawResponse = response;
354+
}
355+
}
356+
},
341357
{
342358
serializer: createSerializer(),
343359
httpMethod: "GET",
@@ -359,7 +375,7 @@ describe("ServiceClient", function() {
359375
}
360376
);
361377

362-
assert.strictEqual(res._response.status, 200);
378+
assert.strictEqual(rawResponse?.status, 200);
363379
assert.deepStrictEqual(res.slice(), [1, 2, 3]);
364380
});
365381

0 commit comments

Comments
 (0)