Skip to content

Commit

Permalink
Merge pull request #1296 from hey-api/fix/client-fetch-parse-as-charset
Browse files Browse the repository at this point in the history
fix: handle charset in auto parseAs detection
  • Loading branch information
mrlubos authored Nov 17, 2024
2 parents ee7a411 + 4c853d0 commit 2822bc4
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 25 deletions.
5 changes: 5 additions & 0 deletions .changeset/lazy-badgers-retire.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@hey-api/client-fetch': patch
---

fix: handle charset in auto parseAs detection
18 changes: 11 additions & 7 deletions packages/client-fetch/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -326,30 +326,34 @@ export const createQuerySerializer = <T = unknown>({
* Infers parseAs value from provided Content-Type header.
*/
export const getParseAs = (
content: string | null,
contentType: string | null,
): Exclude<Config['parseAs'], 'auto' | 'stream'> => {
if (!content) {
if (!contentType) {
return;
}

// TODO: parser - better detection of MIME types
if (content.startsWith('application/json') || content.endsWith('+json')) {
const cleanContent = contentType.split(';')[0].trim();

if (
cleanContent.startsWith('application/json') ||
cleanContent.endsWith('+json')
) {
return 'json';
}

if (content === 'multipart/form-data') {
if (cleanContent === 'multipart/form-data') {
return 'formData';
}

if (
['application/', 'audio/', 'image/', 'video/'].some((type) =>
content.startsWith(type),
cleanContent.startsWith(type),
)
) {
return 'blob';
}

if (content.startsWith('text/')) {
if (cleanContent.startsWith('text/')) {
return 'text';
}
};
Expand Down
66 changes: 66 additions & 0 deletions packages/client-fetch/test/utils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { describe, expect, it } from 'vitest';

import { getParseAs } from '../src/utils';

describe('getParseAs', () => {
const scenarios: Array<{
content: Parameters<typeof getParseAs>[0];
parseAs: ReturnType<typeof getParseAs>;
}> = [
{
content: null,
parseAs: undefined,
},
{
content: 'application/json',
parseAs: 'json',
},
{
content: 'application/ld+json',
parseAs: 'json',
},
{
content: 'application/ld+json;charset=utf-8',
parseAs: 'json',
},
{
content: 'application/ld+json; charset=utf-8',
parseAs: 'json',
},
{
content: 'multipart/form-data',
parseAs: 'formData',
},
{
content: 'application/*',
parseAs: 'blob',
},
{
content: 'audio/*',
parseAs: 'blob',
},
{
content: 'image/*',
parseAs: 'blob',
},
{
content: 'video/*',
parseAs: 'blob',
},
{
content: 'text/*',
parseAs: 'text',
},
{
content: 'unsupported',
parseAs: undefined,
},
];

it.each(scenarios)(
'detects $content as $parseAs',
async ({ content, parseAs }) => {
expect(getParseAs(content)).toEqual(parseAs);
},
);
});
Original file line number Diff line number Diff line change
Expand Up @@ -326,30 +326,34 @@ export const createQuerySerializer = <T = unknown>({
* Infers parseAs value from provided Content-Type header.
*/
export const getParseAs = (
content: string | null,
contentType: string | null,
): Exclude<Config['parseAs'], 'auto' | 'stream'> => {
if (!content) {
if (!contentType) {
return;
}
// TODO: parser - better detection of MIME types
if (content.startsWith('application/json') || content.endsWith('+json')) {
const cleanContent = contentType.split(';')[0].trim();
if (
cleanContent.startsWith('application/json') ||
cleanContent.endsWith('+json')
) {
return 'json';
}
if (content === 'multipart/form-data') {
if (cleanContent === 'multipart/form-data') {
return 'formData';
}
if (
['application/', 'audio/', 'image/', 'video/'].some((type) =>
content.startsWith(type),
cleanContent.startsWith(type),
)
) {
return 'blob';
}
if (content.startsWith('text/')) {
if (cleanContent.startsWith('text/')) {
return 'text';
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -326,30 +326,34 @@ export const createQuerySerializer = <T = unknown>({
* Infers parseAs value from provided Content-Type header.
*/
export const getParseAs = (
content: string | null,
contentType: string | null,
): Exclude<Config['parseAs'], 'auto' | 'stream'> => {
if (!content) {
if (!contentType) {
return;
}
// TODO: parser - better detection of MIME types
if (content.startsWith('application/json') || content.endsWith('+json')) {
const cleanContent = contentType.split(';')[0].trim();
if (
cleanContent.startsWith('application/json') ||
cleanContent.endsWith('+json')
) {
return 'json';
}
if (content === 'multipart/form-data') {
if (cleanContent === 'multipart/form-data') {
return 'formData';
}
if (
['application/', 'audio/', 'image/', 'video/'].some((type) =>
content.startsWith(type),
cleanContent.startsWith(type),
)
) {
return 'blob';
}
if (content.startsWith('text/')) {
if (cleanContent.startsWith('text/')) {
return 'text';
}
};
Expand Down
7 changes: 3 additions & 4 deletions packages/openapi-ts/test/sample.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ const main = async () => {
input: {
// include:
// '^(#/components/schemas/import|#/paths/api/v{api-version}/simple/options)$',
// path: './test/spec/3.1.x/discriminator-one-of.yaml',
path: './test/spec/3.0.x/full.json',
// path: 'https://mongodb-mms-prod-build-server.s3.amazonaws.com/openapi/2caffd88277a4e27c95dcefc7e3b6a63a3b03297-v2-2023-11-15.json',
},
Expand All @@ -31,7 +30,7 @@ const main = async () => {
{
// asClass: true,
// include...
// name: '@hey-api/services',
name: '@hey-api/services',
// operationId: false,
// serviceNameBuilder: '^Parameters',
},
Expand All @@ -45,14 +44,14 @@ const main = async () => {
// enums: 'javascript',
name: '@hey-api/types',
// style: 'PascalCase',
tree: true,
// tree: true,
},
{
// name: '@tanstack/react-query',
},
{
// name: 'zod',
name: 'fastify',
// name: 'fastify',
},
],
// useOptions: false,
Expand Down

0 comments on commit 2822bc4

Please sign in to comment.