Skip to content
This repository has been archived by the owner on Nov 28, 2022. It is now read-only.

fix(oas-to-har): clean up formatting of raw json bodies #1197

Merged
merged 2 commits into from
Feb 25, 2021
Merged
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
24 changes: 24 additions & 0 deletions packages/oas-to-har/__tests__/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1124,6 +1124,30 @@ describe('requestBody', () => {
).toBe(JSON.stringify({ a: '{ "b": invalid json' }));
});

// TODO: Why do I have to json encode the resulting string? website doesn't seem to need that....
it('should parse valid arbitrary JSON request bodies', () => {
expect(
oasToHar(
oas,
{
path: '/body',
method: 'post',
requestBody: {
content: {
'application/json': {
schema: {
type: 'string',
format: 'json',
},
},
},
},
},
{ body: '{ "a": { "b": "valid json" } }' }
).log.entries[0].request.postData.text
).toBe('{"a":{"b":"valid json"}}');
});

it('should parse valid JSON as an object', () => {
expect(
oasToHar(
Expand Down
52 changes: 31 additions & 21 deletions packages/oas-to-har/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -303,33 +303,43 @@ module.exports = (
} else {
har.postData.mimeType = contentType;

// Find all `{ type: string, format: json }` properties in the schema because we need to manually JSON.parse
// them before submit, otherwise they'll be escaped instead of actual objects.
// We also only want values that the user has entered, so we drop any undefined cleanBody keys
const jsonTypes = Object.keys(requestBody.schema.properties).filter(
key => requestBody.schema.properties[key].format === 'json' && cleanBody[key] !== undefined
);
// Handle arbitrary JSON input via a string.
// In OAS you usually find this in an application/json content type.
// with a schema type=string, format=json.
// In the UI this is represented by an arbitrary text input
// This ensures we remove any newlines or tabs and use a clean json block in the example
if (requestBody.schema.type === 'string') {
Copy link
Member

Choose a reason for hiding this comment

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

Do you want to add a check to make sure type exists in requestBody.schema?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This essentially works that way right? The value will be undefined which isn't equal to string?

Copy link
Member

Choose a reason for hiding this comment

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

I've been burned so often on this shit so I'm always nervous about it, but you're right.

let tktk = {schema: {}}; tktk.schema.type === 'string'
> false

har.postData.text = JSON.stringify(JSON.parse(cleanBody));
Copy link
Contributor Author

@Dashron Dashron Feb 24, 2021

Choose a reason for hiding this comment

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

The diff sucks on this. Really all I added was this line, and indented everything else that existed under the else.

The problem was that line 318 in the right hand file was failing because these schemas have no properties, and Object.keys would error on undefined. Then we would fall back to line 338 where we stringify the value in the text area.

} else {
// Handle formatted JSON objects that have properties that accept arbitrary JSON
// Find all `{ type: string, format: json }` properties in the schema because we need to manually JSON.parse
// them before submit, otherwise they'll be escaped instead of actual objects.
// We also only want values that the user has entered, so we drop any undefined cleanBody keys
const jsonTypes = Object.keys(requestBody.schema.properties).filter(
key => requestBody.schema.properties[key].format === 'json' && cleanBody[key] !== undefined
);

if (jsonTypes.length) {
try {
jsonTypes.forEach(prop => {
try {
cleanBody[prop] = JSON.parse(cleanBody[prop]);
} catch (e) {
// leave the prop as a string value
}
});

if (jsonTypes.length) {
try {
jsonTypes.forEach(prop => {
try {
cleanBody[prop] = JSON.parse(cleanBody[prop]);
} catch (e) {
// leave the prop as a string value
if (typeof cleanBody.RAW_BODY !== 'undefined') {
cleanBody = cleanBody.RAW_BODY;
}
});

if (typeof cleanBody.RAW_BODY !== 'undefined') {
cleanBody = cleanBody.RAW_BODY;
har.postData.text = JSON.stringify(cleanBody);
} catch (e) {
har.postData.text = stringify(formData.body);
}

har.postData.text = JSON.stringify(cleanBody);
} catch (e) {
} else {
har.postData.text = stringify(formData.body);
}
} else {
har.postData.text = stringify(formData.body);
}
}
} catch (e) {
Expand Down