-
Notifications
You must be signed in to change notification settings - Fork 17
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
Conversation
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 |
There was a problem hiding this comment.
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...
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good! Thanks!
There was a problem hiding this 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 |
There was a problem hiding this comment.
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', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! 🎉
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('='))) |
There was a problem hiding this comment.
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
?
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
There was a problem hiding this comment.
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") |
There was a problem hiding this comment.
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 ;)
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'}, |
There was a problem hiding this comment.
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.
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); |
There was a problem hiding this comment.
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.
reqInit.headers = Object.assign({ 'content-type': 'application/json' }, tc.headers); | |
reqInit.headers = tc.headers || { 'content-type': 'application/json' }; |
Co-Authored-By: syumai <[email protected]>
Co-Authored-By: syumai <[email protected]>
Co-Authored-By: syumai <[email protected]>
@syumai Thanks for your reviewing. Please review again 🐈 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, Thanks! 🎉
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