mirror of
https://github.com/ferdikoomen/openapi-typescript-codegen.git
synced 2025-12-08 20:16:21 +00:00
- Supporting response header parsing
This commit is contained in:
parent
de79de4f84
commit
1859e60416
1
src/client/interfaces/Operation.d.ts
vendored
1
src/client/interfaces/Operation.d.ts
vendored
@ -12,4 +12,5 @@ export interface Operation extends OperationParameters {
|
||||
path: string;
|
||||
errors: OperationError[];
|
||||
results: OperationResponse[];
|
||||
responseHeader: string | null;
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@ import { getOperationErrors } from './getOperationErrors';
|
||||
import { getOperationName } from './getOperationName';
|
||||
import { getOperationParameters } from './getOperationParameters';
|
||||
import { getOperationPath } from './getOperationPath';
|
||||
import { getOperationResponseHeader } from './getOperationResponseHeader';
|
||||
import { getOperationResponses } from './getOperationResponses';
|
||||
import { getOperationResults } from './getOperationResults';
|
||||
import { getServiceClassName } from './getServiceClassName';
|
||||
@ -36,6 +37,7 @@ export function getOperation(openApi: OpenApi, url: string, method: string, op:
|
||||
imports: [],
|
||||
errors: [],
|
||||
results: [],
|
||||
responseHeader: null,
|
||||
};
|
||||
|
||||
// Parse the operation parameters (path, query, body, etc).
|
||||
@ -56,6 +58,8 @@ export function getOperation(openApi: OpenApi, url: string, method: string, op:
|
||||
const operationResponses = getOperationResponses(openApi, op.responses);
|
||||
const operationResults = getOperationResults(operationResponses);
|
||||
operation.errors = getOperationErrors(operationResponses);
|
||||
operation.responseHeader = getOperationResponseHeader(operationResults);
|
||||
|
||||
operationResults.forEach(operationResult => {
|
||||
operation.results.push(operationResult);
|
||||
operation.imports.push(...operationResult.imports);
|
||||
|
||||
@ -28,6 +28,20 @@ export function getOperationResponse(openApi: OpenApi, response: OpenApiResponse
|
||||
properties: [],
|
||||
};
|
||||
|
||||
// We support basic properties from response headers, since both
|
||||
// fetch and XHR client just support string types.
|
||||
if (response.headers) {
|
||||
for (const name in response.headers) {
|
||||
if (response.headers.hasOwnProperty(name)) {
|
||||
operationResponse.in = 'header';
|
||||
operationResponse.name = name;
|
||||
operationResponse.type = PrimaryType.STRING;
|
||||
operationResponse.base = PrimaryType.STRING;
|
||||
return operationResponse;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If this response has a schema, then we need to check two things:
|
||||
// if this is a reference then the parameter is just the 'name' of
|
||||
// this reference type. Otherwise it might be a complex schema and
|
||||
@ -74,14 +88,5 @@ export function getOperationResponse(openApi: OpenApi, response: OpenApiResponse
|
||||
}
|
||||
}
|
||||
|
||||
if (response.headers) {
|
||||
for (const name in response.headers) {
|
||||
if (response.headers.hasOwnProperty(name)) {
|
||||
// console.log(name, response.headers[name]);
|
||||
// const header = response.headers[name];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return operationResponse;
|
||||
}
|
||||
|
||||
11
src/openApi/v2/parser/getOperationResponseHeader.ts
Normal file
11
src/openApi/v2/parser/getOperationResponseHeader.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { OperationResponse } from '../../../client/interfaces/OperationResponse';
|
||||
|
||||
export function getOperationResponseHeader(operationResponses: OperationResponse[]): string | null {
|
||||
const header = operationResponses.find(operationResponses => {
|
||||
return operationResponses.in === 'header';
|
||||
});
|
||||
if (header) {
|
||||
return header.name;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -7,6 +7,7 @@ import { getOperationName } from './getOperationName';
|
||||
import { getOperationParameters } from './getOperationParameters';
|
||||
import { getOperationPath } from './getOperationPath';
|
||||
import { getOperationRequestBody } from './getOperationRequestBody';
|
||||
import { getOperationResponseHeader } from './getOperationResponseHeader';
|
||||
import { getOperationResponses } from './getOperationResponses';
|
||||
import { getOperationResults } from './getOperationResults';
|
||||
import { getServiceClassName } from './getServiceClassName';
|
||||
@ -38,6 +39,7 @@ export function getOperation(openApi: OpenApi, url: string, method: string, op:
|
||||
imports: [],
|
||||
errors: [],
|
||||
results: [],
|
||||
responseHeader: null,
|
||||
};
|
||||
|
||||
// Parse the operation parameters (path, query, body, etc).
|
||||
@ -66,6 +68,8 @@ export function getOperation(openApi: OpenApi, url: string, method: string, op:
|
||||
const operationResponses = getOperationResponses(openApi, op.responses);
|
||||
const operationResults = getOperationResults(operationResponses);
|
||||
operation.errors = getOperationErrors(operationResponses);
|
||||
operation.responseHeader = getOperationResponseHeader(operationResults);
|
||||
|
||||
operationResults.forEach(operationResult => {
|
||||
operation.results.push(operationResult);
|
||||
operation.imports.push(...operationResult.imports);
|
||||
|
||||
@ -29,6 +29,20 @@ export function getOperationResponse(openApi: OpenApi, response: OpenApiResponse
|
||||
properties: [],
|
||||
};
|
||||
|
||||
// We support basic properties from response headers, since both
|
||||
// fetch and XHR client just support string types.
|
||||
if (response.headers) {
|
||||
for (const name in response.headers) {
|
||||
if (response.headers.hasOwnProperty(name)) {
|
||||
operationResponse.in = 'header';
|
||||
operationResponse.name = name;
|
||||
operationResponse.type = PrimaryType.STRING;
|
||||
operationResponse.base = PrimaryType.STRING;
|
||||
return operationResponse;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (response.content) {
|
||||
const schema = getContent(openApi, response.content);
|
||||
if (schema) {
|
||||
@ -74,14 +88,5 @@ export function getOperationResponse(openApi: OpenApi, response: OpenApiResponse
|
||||
}
|
||||
}
|
||||
|
||||
if (response.headers) {
|
||||
for (const name in response.headers) {
|
||||
if (response.headers.hasOwnProperty(name)) {
|
||||
// console.log(name, response.headers[name]);
|
||||
// const header = response.headers[name];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return operationResponse;
|
||||
}
|
||||
|
||||
11
src/openApi/v3/parser/getOperationResponseHeader.ts
Normal file
11
src/openApi/v3/parser/getOperationResponseHeader.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { OperationResponse } from '../../../client/interfaces/OperationResponse';
|
||||
|
||||
export function getOperationResponseHeader(operationResponses: OperationResponse[]): string | null {
|
||||
const header = operationResponses.find(operationResponses => {
|
||||
return operationResponses.in === 'header';
|
||||
});
|
||||
if (header) {
|
||||
return header.name;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -11,4 +11,5 @@ export interface RequestOptions {
|
||||
query?: { [key: string]: any };
|
||||
formData?: { [key: string]: any };
|
||||
body?: any;
|
||||
responseHeader?: string;
|
||||
}
|
||||
|
||||
@ -66,9 +66,9 @@ export async function request(options: Readonly<RequestOptions>): Promise<Result
|
||||
try {
|
||||
switch (OpenAPI.CLIENT) {
|
||||
case 'xhr':
|
||||
return await requestUsingXHR(url, request);
|
||||
return await requestUsingXHR(url, request, options.responseHeader);
|
||||
default:
|
||||
return await requestUsingFetch(url, request);
|
||||
return await requestUsingFetch(url, request, options.responseHeader);
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
|
||||
@ -30,24 +30,44 @@ async function parseBody(response: Response): Promise<any> {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the response header (if specified)
|
||||
* @param response Response object from fetch
|
||||
* @param responseHeader The name of the header to fetch
|
||||
*/
|
||||
function parseHeader(response: Response, responseHeader?: string): string | null {
|
||||
if (responseHeader) {
|
||||
const content = response.headers.get(responseHeader);
|
||||
if (typeof content === 'string') {
|
||||
return content;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request content using the new Fetch API. This is the default API that is used and
|
||||
* is create for all JSON, XML and text objects. However it is limited to UTF-8.
|
||||
* This is a problem for some of the Docs content, since that requires UTF-16!
|
||||
* @param url The url to request.
|
||||
* @param request The request object, containing method, headers, body, etc.
|
||||
* @param responseHeader The header we want to parse.
|
||||
*/
|
||||
export async function requestUsingFetch(url: string, request: Readonly<RequestInit>): Promise<Result> {
|
||||
export async function requestUsingFetch(url: string, request: Readonly<RequestInit>, responseHeader?: string): Promise<Result> {
|
||||
|
||||
// Fetch response using fetch API.
|
||||
const response = await fetch(url, request);
|
||||
|
||||
// Get content of response header or response body
|
||||
const contentHeader = parseHeader(response, responseHeader);
|
||||
const contentBody = await parseBody(response);
|
||||
|
||||
// Create result object.
|
||||
return {
|
||||
url,
|
||||
ok: response.ok,
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
body: await parseBody(response),
|
||||
body: contentHeader || contentBody,
|
||||
};
|
||||
}
|
||||
|
||||
@ -31,6 +31,21 @@ function parseBody(xhr: XMLHttpRequest): any {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the response header (if specified)
|
||||
* @param xhr XHR request object
|
||||
* @param responseHeader The name of the header to fetch
|
||||
*/
|
||||
function parseHeader(xhr: XMLHttpRequest, responseHeader?: string): string | null {
|
||||
if (responseHeader) {
|
||||
const content = xhr.getResponseHeader(responseHeader);
|
||||
if (typeof content === 'string') {
|
||||
return content;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request content using the new legacy XMLHttpRequest API. This method is useful
|
||||
* when we want to request UTF-16 content, since it natively supports loading UTF-16.
|
||||
@ -38,8 +53,9 @@ function parseBody(xhr: XMLHttpRequest): any {
|
||||
* content using JavaScript... And that is very very slow.
|
||||
* @param url The url to request.
|
||||
* @param request The request object, containing method, headers, body, etc.
|
||||
* @param responseHeader The header we want to parse.
|
||||
*/
|
||||
export async function requestUsingXHR(url: string, request: Readonly<RequestInit>): Promise<Result> {
|
||||
export async function requestUsingXHR(url: string, request: Readonly<RequestInit>, responseHeader?: string): Promise<Result> {
|
||||
return new Promise(resolve => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
|
||||
@ -57,16 +73,19 @@ export async function requestUsingXHR(url: string, request: Readonly<RequestInit
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === XMLHttpRequest.DONE) {
|
||||
|
||||
// Get content of response header or response body
|
||||
const contentHeader = parseHeader(xhr, responseHeader);
|
||||
const contentBody = parseBody(xhr);
|
||||
|
||||
// Create result object.
|
||||
const result: Result = {
|
||||
url,
|
||||
ok: isSuccess(xhr.status),
|
||||
status: xhr.status,
|
||||
statusText: xhr.statusText,
|
||||
body: parseBody(xhr),
|
||||
body: contentHeader || contentBody,
|
||||
};
|
||||
|
||||
|
||||
// Done!
|
||||
resolve(result);
|
||||
}
|
||||
|
||||
@ -71,6 +71,9 @@ export class {{{name}}} {
|
||||
{{#if parametersBody~}}
|
||||
body: {{{parametersBody.name}}},
|
||||
{{/if}}
|
||||
{{#if responseHeader~}}
|
||||
responseHeader: '{{{responseHeader}}}',
|
||||
{{/if}}
|
||||
});
|
||||
{{#if errors}}
|
||||
|
||||
|
||||
@ -17,7 +17,7 @@ export function postProcessServiceOperations(service: Service, client: Client, u
|
||||
clone.imports.push(...flatMap(clone.parameters, parameter => parameter.imports));
|
||||
clone.imports.push(...flatMap(clone.results, result => result.imports));
|
||||
|
||||
// Check of the operation name
|
||||
// Check if the operation name is unique, if not then prefix this with a number
|
||||
const name = clone.name;
|
||||
const index = names.get(name) || 0;
|
||||
if (index > 0) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user