Skip to content

Fix binary response type to process as a Blob rather than text/string #986

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions src/templates/core/ApiRequestOptions.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export type ApiRequestOptions = {
readonly formData?: Record<string, any>;
readonly body?: any;
readonly mediaType?: string;
readonly responseType?: 'blob';
readonly responseHeader?: string;
readonly errors?: Record<number, string>;
};
3 changes: 2 additions & 1 deletion src/templates/core/angular/sendRequest.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ export const sendRequest = <T>(
formData: FormData | undefined,
headers: HttpHeaders
): Observable<HttpResponse<T>> => {
return http.request<T>(options.method, url, {
return http.request(options.method, url, {
headers,
body: body ?? formData,
withCredentials: config.WITH_CREDENTIALS,
observe: 'response',
responseType: options.responseType,
});
};
1 change: 1 addition & 0 deletions src/templates/core/axios/sendRequest.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export const sendRequest = async <T>(
data: body ?? formData,
method: options.method,
withCredentials: config.WITH_CREDENTIALS,
responseType: options.responseType,
cancelToken: source.token,
};

Expand Down
4 changes: 3 additions & 1 deletion src/templates/core/fetch/getResponseBody.hbs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export const getResponseBody = async (response: Response): Promise<any> => {
export const getResponseBody = async (response: Response, options: ApiRequestOptions): Promise<any> => {
if (response.status !== 204) {
try {
const contentType = response.headers.get('Content-Type');
Expand All @@ -7,6 +7,8 @@ export const getResponseBody = async (response: Response): Promise<any> => {
const isJSON = jsonTypes.some(type => contentType.toLowerCase().startsWith(type));
if (isJSON) {
return await response.json();
} else if (options.responseType === 'blob') {
return await response.blob();
} else {
return await response.text();
}
Expand Down
2 changes: 1 addition & 1 deletion src/templates/core/fetch/request.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export const request = <T>(config: OpenAPIConfig, options: ApiRequestOptions): C

if (!onCancel.isCancelled) {
const response = await sendRequest(config, options, url, body, formData, headers, onCancel);
const responseBody = await getResponseBody(response);
const responseBody = await getResponseBody(response, options);
const responseHeader = getResponseHeader(response, options.responseHeader);

const result: ApiResult = {
Expand Down
4 changes: 3 additions & 1 deletion src/templates/core/node/getResponseBody.hbs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export const getResponseBody = async (response: Response): Promise<any> => {
export const getResponseBody = async (response: Response, options: ApiRequestOptions): Promise<any> => {
if (response.status !== 204) {
try {
const contentType = response.headers.get('Content-Type');
Expand All @@ -7,6 +7,8 @@ export const getResponseBody = async (response: Response): Promise<any> => {
const isJSON = jsonTypes.some(type => contentType.toLowerCase().startsWith(type));
if (isJSON) {
return await response.json();
} else if (options.responseType === 'blob') {
return await response.blob();
} else {
return await response.text();
}
Expand Down
2 changes: 1 addition & 1 deletion src/templates/core/node/request.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export const request = <T>(config: OpenAPIConfig, options: ApiRequestOptions): C

if (!onCancel.isCancelled) {
const response = await sendRequest(options, url, body, formData, headers, onCancel);
const responseBody = await getResponseBody(response);
const responseBody = await getResponseBody(response, options);
const responseHeader = getResponseHeader(response, options.responseHeader);

const result: ApiResult = {
Expand Down
4 changes: 3 additions & 1 deletion src/templates/core/xhr/getResponseBody.hbs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export const getResponseBody = (xhr: XMLHttpRequest): any => {
export const getResponseBody = (xhr: XMLHttpRequest, options: ApiRequestOptions): any => {
if (xhr.status !== 204) {
try {
const contentType = xhr.getResponseHeader('Content-Type');
Expand All @@ -7,6 +7,8 @@ export const getResponseBody = (xhr: XMLHttpRequest): any => {
const isJSON = jsonTypes.some(type => contentType.toLowerCase().startsWith(type));
if (isJSON) {
return JSON.parse(xhr.responseText);
} else if (options.responseType === 'blob') {
return xhr.response;
} else {
return xhr.responseText;
}
Expand Down
2 changes: 1 addition & 1 deletion src/templates/core/xhr/request.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export const request = <T>(config: OpenAPIConfig, options: ApiRequestOptions): C

if (!onCancel.isCancelled) {
const response = await sendRequest(config, options, url, body, formData, headers, onCancel);
const responseBody = getResponseBody(response);
const responseBody = getResponseBody(response, options);
const responseHeader = getResponseHeader(response, options.responseHeader);

const result: ApiResult = {
Expand Down
1 change: 1 addition & 0 deletions src/templates/core/xhr/sendRequest.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export const sendRequest = async (
const xhr = new XMLHttpRequest();
xhr.open(options.method, url, true);
xhr.withCredentials = config.WITH_CREDENTIALS;
xhr.responseType = options.responseType;

headers.forEach((value, key) => {
xhr.setRequestHeader(key, value);
Expand Down
3 changes: 3 additions & 0 deletions src/templates/exportService.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@ export class {{{name}}}{{{@root.postfix}}} {
mediaType: '{{{parametersBody.mediaType}}}',
{{/if}}
{{/if}}
{{#if results}}
{{>responseType}}
{{/if}}
{{#if responseHeader}}
responseHeader: '{{{responseHeader}}}',
{{/if}}
Expand Down
5 changes: 5 additions & 0 deletions src/templates/partials/responseType.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{{~#equals results.length 1~}}
{{~#equals results.0.base 'binary'~}}
responseType: 'blob',
{{/equals}}
{{~/equals~}}
Comment on lines +1 to +5

Choose a reason for hiding this comment

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

Suggested change
{{~#equals results.length 1~}}
{{~#equals results.0.base 'binary'~}}
responseType: 'blob',
{{/equals}}
{{~/equals~}}
{{~#equals results.0.base 'binary'~}}
responseType: 'blob',
{{/equals}}

I'd like to suggest to not check on results.length 1 as there might be multiple valid responses, e.g. some 202 not ready response, which is not a blob and thus would be filtered out.

However only checking for the first element seems fine to be, as the 200 success response will be sorted and should always be the first element

2 changes: 2 additions & 0 deletions src/utils/registerHandlebarTemplates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ import partialIsNullable from '../templates/partials/isNullable.hbs';
import partialIsReadOnly from '../templates/partials/isReadOnly.hbs';
import partialIsRequired from '../templates/partials/isRequired.hbs';
import partialParameters from '../templates/partials/parameters.hbs';
import partialResponseType from '../templates/partials/responseType.hbs';
import partialResult from '../templates/partials/result.hbs';
import partialSchema from '../templates/partials/schema.hbs';
import partialSchemaArray from '../templates/partials/schemaArray.hbs';
Expand Down Expand Up @@ -147,6 +148,7 @@ export const registerHandlebarTemplates = (root: {
Handlebars.registerPartial('isReadOnly', Handlebars.template(partialIsReadOnly));
Handlebars.registerPartial('isRequired', Handlebars.template(partialIsRequired));
Handlebars.registerPartial('parameters', Handlebars.template(partialParameters));
Handlebars.registerPartial('responseType', Handlebars.template(partialResponseType));
Handlebars.registerPartial('result', Handlebars.template(partialResult));
Handlebars.registerPartial('schema', Handlebars.template(partialSchema));
Handlebars.registerPartial('schemaArray', Handlebars.template(partialSchemaArray));
Expand Down