From 94c37c09c58cc37d61c5a678b37a0111c90936d6 Mon Sep 17 00:00:00 2001 From: Levi Cameron Date: Thu, 25 May 2017 20:07:34 +1000 Subject: [PATCH 1/4] Fix browsable API not supporting multipart/form-data correctly - Autodetect missing boundary parameter for Content-Type header - textarea value normalises EOL chars to \n when multipart/form-data requires \r\n --- rest_framework/static/rest_framework/js/ajax-form.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/rest_framework/static/rest_framework/js/ajax-form.js b/rest_framework/static/rest_framework/js/ajax-form.js index ce17729d1..88cb133bf 100644 --- a/rest_framework/static/rest_framework/js/ajax-form.js +++ b/rest_framework/static/rest_framework/js/ajax-form.js @@ -37,6 +37,17 @@ function doAjaxSubmit(e) { if (contentType) { data = form.find('[data-override="content"]').val() || '' + + if (contentType === 'multipart/form-data') { + // We need to add a boundary parameter to the header + var re = /^--([0-9A-Z'()+_,-./:=?]{1,70})[ \f\t\v\u00a0\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]*$/im; + var boundary = re.exec(data); + if (boundary !== null) { + contentType += '; boundary="' + boundary[1] + '"'; + } + // Fix textarea.value EOL normalisation (multipart/form-data should use CR+NL, not NL) + data = data.replace(/\n/g, '\r\n'); + } } else { contentType = form.attr('enctype') || form.attr('encoding') From 1c44ef2b11f42b28af188b6ac60a91c95102391f Mon Sep 17 00:00:00 2001 From: Levi Cameron Date: Tue, 30 May 2017 10:43:33 +1000 Subject: [PATCH 2/4] Improvements to code clarity --- rest_framework/static/rest_framework/js/ajax-form.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/rest_framework/static/rest_framework/js/ajax-form.js b/rest_framework/static/rest_framework/js/ajax-form.js index 88cb133bf..cb41343ee 100644 --- a/rest_framework/static/rest_framework/js/ajax-form.js +++ b/rest_framework/static/rest_framework/js/ajax-form.js @@ -40,8 +40,10 @@ function doAjaxSubmit(e) { if (contentType === 'multipart/form-data') { // We need to add a boundary parameter to the header + // We assume the first valid-looking boundary line in the body is correct + // regex is from RFC 2046 appendix A var re = /^--([0-9A-Z'()+_,-./:=?]{1,70})[ \f\t\v\u00a0\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]*$/im; - var boundary = re.exec(data); + var boundary = data.match(re); if (boundary !== null) { contentType += '; boundary="' + boundary[1] + '"'; } From 6b8d6019eaae72e93c02130c1794353994e08c7e Mon Sep 17 00:00:00 2001 From: Levi Cameron Date: Wed, 31 May 2017 13:12:06 +1000 Subject: [PATCH 3/4] Fix boundary detection regex not handling spaces inside boundary marker correctly --- rest_framework/static/rest_framework/js/ajax-form.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/rest_framework/static/rest_framework/js/ajax-form.js b/rest_framework/static/rest_framework/js/ajax-form.js index cb41343ee..fc00926f5 100644 --- a/rest_framework/static/rest_framework/js/ajax-form.js +++ b/rest_framework/static/rest_framework/js/ajax-form.js @@ -42,7 +42,9 @@ function doAjaxSubmit(e) { // We need to add a boundary parameter to the header // We assume the first valid-looking boundary line in the body is correct // regex is from RFC 2046 appendix A - var re = /^--([0-9A-Z'()+_,-./:=?]{1,70})[ \f\t\v\u00a0\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]*$/im; + var boundaryCharNoSpace = "[0-9A-Z'()+_,-./:=?"; + var boundaryChar = boundaryCharNoSpace + ' '; + var re = new RegExp('^--([' + boundaryChar + ']{0,69}[' + boundaryCharNoSpace + '])[\\s]*?$', 'im'); var boundary = data.match(re); if (boundary !== null) { contentType += '; boundary="' + boundary[1] + '"'; From 5cbfcbc56f3d55d3a2f91db7fe67e981c740d2cb Mon Sep 17 00:00:00 2001 From: Levi Cameron Date: Fri, 16 Jun 2017 21:53:06 +1000 Subject: [PATCH 4/4] Fix regex typo allowing '[' in boundary string --- rest_framework/static/rest_framework/js/ajax-form.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest_framework/static/rest_framework/js/ajax-form.js b/rest_framework/static/rest_framework/js/ajax-form.js index fc00926f5..1483305ff 100644 --- a/rest_framework/static/rest_framework/js/ajax-form.js +++ b/rest_framework/static/rest_framework/js/ajax-form.js @@ -42,7 +42,7 @@ function doAjaxSubmit(e) { // We need to add a boundary parameter to the header // We assume the first valid-looking boundary line in the body is correct // regex is from RFC 2046 appendix A - var boundaryCharNoSpace = "[0-9A-Z'()+_,-./:=?"; + var boundaryCharNoSpace = "0-9A-Z'()+_,-./:=?"; var boundaryChar = boundaryCharNoSpace + ' '; var re = new RegExp('^--([' + boundaryChar + ']{0,69}[' + boundaryCharNoSpace + '])[\\s]*?$', 'im'); var boundary = data.match(re);