Skip to content
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

Support content-type with parameters #40

Merged
merged 5 commits into from
Jun 7, 2019

Conversation

mactkg
Copy link
Contributor

@mactkg mactkg commented Jun 6, 2019

A current code can't process HTTP request included content-type with parameters such as application/json;charset=utf-8.
This PR resolve it, also, define default behaviour when content-type isn't set.
According to RFC2616, we should treat unknown content-type data as "application/octet-stream".

ref: https://www.w3.org/Protocols/rfc2616/rfc2616-sec7.html

A previous code can't process HTTP request included content-type with parameters such as "application/json;charset=utf-8".
This commit resolve it, also, define default behaviour when content-type isn't set.
According to RFC2616, we should treat unknown content-type data as "application/octet-stream".
mod.ts Outdated
@@ -114,6 +119,9 @@ export class App {
}
Object.assign(params, obj);
break;
case 'application/octet-stream':
params['data'] = decodedBody
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can't come up with the best way to treat application/octet-stream data...

Copy link
Owner

@syumai syumai Jun 6, 2019

Choose a reason for hiding this comment

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

Thank you for catching this!

I think the data of 'application/octet-stream' is not params, it's request body and it should implement Deno.Reader.

In my opinion, req.body should be passed to the handler as body prop in ctx.
The line of decoder.decode(await readAll(req.body)); is just a workaround and I must fix this.

I'm sorry that I can't accept data param as a request body.

I opened issue for this.
#41

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In my opinion, req.body should be passed to the handler as body prop in ctx.

I think so too. For now, can I remove a case for processing application/octet-stream data?
The code will be modified like this:

switch(type) {
  // bla bla...
    Object..assign(params, obj);
    break;
  case 'application/octet-stream':
    // FIXME: we skip here for now, it should be implemented when Issue #41 resolved.
    break;
}

Copy link
Owner

Choose a reason for hiding this comment

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

Looks good! Thanks!

Copy link
Owner

@syumai syumai left a comment

Choose a reason for hiding this comment

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

Thank you for giving me a PR! ;)
Please take a look at my comments.

mod.ts Outdated
@@ -114,6 +119,9 @@ export class App {
}
Object.assign(params, obj);
break;
case 'application/octet-stream':
params['data'] = decodedBody
Copy link
Owner

@syumai syumai Jun 6, 2019

Choose a reason for hiding this comment

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

Thank you for catching this!

I think the data of 'application/octet-stream' is not params, it's request body and it should implement Deno.Reader.

In my opinion, req.body should be passed to the handler as body prop in ctx.
The line of decoder.decode(await readAll(req.body)); is just a workaround and I must fix this.

I'm sorry that I can't accept data param as a request body.

I opened issue for this.
#41

@@ -48,6 +49,23 @@ const testCases: Array<testCase> = [
method: Method.GET,
expected: 'john',
},
{
name: 'valid post',
Copy link
Owner

Choose a reason for hiding this comment

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

Thanks! 🎉

mod.ts Outdated Show resolved Hide resolved
mod.ts Outdated
const contentType = req.headers.get('content-type');
const rawContentType = req.headers.get('content-type') || "application/octet-stream";
const [contentType, ...typeParamsArray] = rawContentType.split(';')
const typeParams = Object.assign({}, ...typeParamsArray.map(params => params.split('=')))
Copy link
Owner

Choose a reason for hiding this comment

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

This code looks not correct, how about using reduce?

Suggested change
const typeParams = Object.assign({}, ...typeParamsArray.map(params => params.split('=')))
const typeParams = typeParamsArray.reduce((params, curr) => {
const [key, value] = curr.split('=');
params[key] = value;
return params;
}, {});

Please see this: https://jsbin.com/verabuh/edit?js,console

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Indeed...! Tests I wrote are passed but the default value of params['charset'] just worked... 😓

mod.ts Outdated
const [contentType, ...typeParamsArray] = rawContentType.split(';')
const typeParams = Object.assign({}, ...typeParamsArray.map(params => params.split('=')))

const decoder = new TextDecoder(typeParams['charset'] || "utf-8")
Copy link
Owner

@syumai syumai Jun 6, 2019

Choose a reason for hiding this comment

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

To get charset in this form, keys must be transformed using function like lowerCase in lodash.
I just want a TODO comment for this ;)

Suggested change
const decoder = new TextDecoder(typeParams['charset'] || "utf-8")
const decoder = new TextDecoder(typeParams['charset'] || "utf-8"); // TODO: downcase `charset` key

serve_test.ts Outdated
registered: post('/params', ({ params }) => [200, params.name]),
path: 'params',
params: JSON.stringify({ name: 'tom' }),
headers: {['content-type']: 'application/json; charset=utf-8'},
Copy link
Owner

Choose a reason for hiding this comment

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

No brackets are needed here.

Suggested change
headers: {['content-type']: 'application/json; charset=utf-8'},
headers: { 'content-type': 'application/json; charset=utf-8' },

serve_test.ts Outdated
@@ -79,7 +97,7 @@ for (const tc of testCases) {
const reqInit: RequestInit = { method: tc.method };
if (typeof tc.params === 'string') {
reqInit.body = tc.params;
reqInit.headers = { 'content-type': 'application/json' };
reqInit.headers = Object.assign({ 'content-type': 'application/json' }, tc.headers);
Copy link
Owner

Choose a reason for hiding this comment

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

In this case, I prefer this form.

Suggested change
reqInit.headers = Object.assign({ 'content-type': 'application/json' }, tc.headers);
reqInit.headers = tc.headers || { 'content-type': 'application/json' };

@mactkg
Copy link
Contributor Author

mactkg commented Jun 7, 2019

@syumai Thanks for your reviewing. Please review again 🐈

Copy link
Owner

@syumai syumai left a comment

Choose a reason for hiding this comment

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

LGTM, Thanks! 🎉

@syumai syumai merged commit 530c0a3 into syumai:master Jun 7, 2019
@mactkg mactkg deleted the feature/support-mime-with-params branch June 7, 2019 02:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants