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

Commit

Permalink
Allow option to send chunking specific params as custom header params (
Browse files Browse the repository at this point in the history
  • Loading branch information
thomas-hickl committed Jul 25, 2017
1 parent f99e7e4 commit 08d0787
Show file tree
Hide file tree
Showing 11 changed files with 118 additions and 35 deletions.
2 changes: 1 addition & 1 deletion client/js/s3/s3.form.upload.handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ qq.s3.FormUploadHandler = function(options, proxy) {
method: method,
endpoint: endpoint,
params: params,
paramsInBody: true,
paramsMode: qq.paramsMode.paramsInBody,
targetName: iframe.name
});

Expand Down
3 changes: 2 additions & 1 deletion client/js/traditional/traditional.form.upload.handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ qq.traditional.FormUploadHandler = function(options, proxy) {
method: method,
endpoint: endpoint,
params: params,
paramsInBody: options.paramsInBody,
paramsMode: options.paramsMode,
headerParamPrefix: options.headerParamPrefix,
targetName: iframe.name
});
}
Expand Down
13 changes: 10 additions & 3 deletions client/js/traditional/traditional.xhr.upload.handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ qq.traditional.XhrUploadHandler = function(spec, proxy) {
getSize = proxy.getSize,
getUuid = proxy.getUuid,
log = proxy.log,
multipart = spec.forceMultipart || spec.paramsInBody,
multipart = spec.forceMultipart || spec.paramsMode === qq.paramsMode.paramsInBody,

addChunkingSpecificParams = function(id, params, chunkData) {
var size = getSize(id),
Expand Down Expand Up @@ -142,21 +142,28 @@ qq.traditional.XhrUploadHandler = function(spec, proxy) {
}

//build query string
if (!spec.paramsInBody) {
if (spec.paramsMode === qq.paramsMode.paramsInUrl) {
if (!multipart) {
params[spec.inputName] = name;
}
endpoint = qq.obj2url(params, endpoint);
}

xhr.open(method, endpoint, true);
if (spec.paramsMode === qq.paramsMode.paramsInHeader) {
var headerParamPrefix = spec.headerParamPrefix || qq.headerParamPrefix;

qq.each(params, function (key, val) {
xhr.setRequestHeader(headerParamPrefix + key, "" + val);
});
}

if (spec.cors.expected && spec.cors.sendCredentials) {
xhr.withCredentials = true;
}

if (multipart) {
if (spec.paramsInBody) {
if (spec.paramsMode === qq.paramsMode.paramsInBody) {
qq.obj2FormData(params, formData);
}

Expand Down
8 changes: 4 additions & 4 deletions client/js/upload-handler/form.upload.handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -255,22 +255,22 @@ qq.FormUploadHandler = function(spec) {
* that the form is hidden from view.
*
* @param spec An object containing various properties to be used when constructing the form. Required properties are
* currently: `method`, `endpoint`, `params`, `paramsInBody`, and `targetName`.
* currently: `method`, `endpoint`, `params`, `paramsMode` and `targetName`.
* @returns {HTMLFormElement} The created form
*/
_initFormForUpload: function(spec) {
var method = spec.method,
endpoint = spec.endpoint,
params = spec.params,
paramsInBody = spec.paramsInBody,
paramsMode = spec.paramsMode,
targetName = spec.targetName,
form = qq.toElement("<form method='" + method + "' enctype='multipart/form-data'></form>"),
url = endpoint;

if (paramsInBody) {
if (paramsMode === qq.paramsMode.paramsInBody) {
qq.obj2Inputs(params, form);
}
else {
else if (paramsMode === qq.paramsMode.paramsInUrl){
url = qq.obj2url(params, endpoint);
}

Expand Down
2 changes: 1 addition & 1 deletion client/js/uploader.basic.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
inputName: "qqfile",
method: "POST",
params: {},
paramsInBody: true,
paramsMode: qq.paramsMode.paramsInBody,
totalFileSizeName: "qqtotalfilesize",
uuidName: "qquuid"
},
Expand Down
8 changes: 8 additions & 0 deletions client/js/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,14 @@ var qq = function(element) {
(function() {
"use strict";

qq.paramsMode = {
paramsInBody: "paramsInBody",
paramsInHeader: "paramsInHeader",
paramsInUrl: "paramsInUrl"
};

qq.headerParamPrefix = "";

qq.canvasToBlob = function(canvas, mime, quality) {
return qq.dataUriToBlob(canvas.toDataURL(mime, quality));
};
Expand Down
15 changes: 10 additions & 5 deletions client/typescript/fine-uploader.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -672,14 +672,19 @@ declare namespace FineUploader {
*/
params?: any;
/**
* Enable or disable sending parameters in the request body.
* Configure the mode parameters are added to the request.
*
* If `false`, parameters are sent in the URL.
* Otherwise, parameters are sent in the request body
* `qq.paramsMode.paramsInBody` sends params in the request body.
* `qq.paramsMode.paramsInUrl` sends params in the request url.
* `qq.paramsMode.paramsInHeader` sends params in the request header.
*
* @default `true`
* @default `qq.paramsMode.paramsInBody`
*/
paramsMode?: string;
/**
* The prefix for parameters sent in the request's header. Only matters if `paramsMode` is set to `qq.paramsMode.paramsInHeader`
*/
paramsInBody?: boolean;
headerParamPrefix?: string;
/**
* The name of the parameter the uniquely identifies each associated item. The value is a Level 4 UUID
*
Expand Down
5 changes: 3 additions & 2 deletions docs/features/request-parameters.jmd
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,9 @@ To change parameters again, call `setParams` again with the associated `id`.""",

Sometimes it may prove useful to send request parameters in the URL
query string, and fortunately Fine Uploader supports this right out of the
box. By disabling the `request.paramsInBody` option, you can pass parameters
through the query string rather than the request body.
box. By setting the `request.paramsInUrl` option, you can pass parameters
through the query string rather than the request body. Alternatively `request.paramsInHeader`
adds parameters in the request header, concatenated with the optional `request.paramHeaderPrefix`.

{{ alert(
"""All parameters in the query string are [URI Component Encoded](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/encodeURIComponent).
Expand Down
5 changes: 3 additions & 2 deletions test/unit/chunked-uploads.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,15 @@ if (qqtest.canDownloadFileAsBlob) {

function testChunkedUpload(spec) {
var customParams = spec.customParams || {},
chunkingParamNames = spec.chunkingParamNames || new qq.FineUploaderBasic({})._options.chunking.paramNames;
chunkingParamNames = spec.chunkingParamNames || new qq.FineUploaderBasic({})._options.chunking.paramNames,
paramsMode = !!spec.mpe ? qq.paramsMode.paramsInBody : qq.paramsMode.paramsInUrl;

assert.expect(3 + (expectedChunks * (20 + (Object.keys(customParams).length))), spec.done);

var uploader = new qq.FineUploaderBasic({
request: {
endpoint: testUploadEndpoint,
paramsInBody: !!spec.mpe,
paramsMode: paramsMode,
forceMultipart: !!spec.mpe,
params: customParams
},
Expand Down
88 changes: 74 additions & 14 deletions test/unit/file-upload-params-and-headers.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ if (qqtest.canDownloadFileAsBlob) {
var uploader = new qq.FineUploaderBasic({
request: {
endpoint: testUploadEndpoint,
paramsInBody: mpe,
paramsMode: mpe ? qq.paramsMode.paramsInBody : qq.paramsMode.paramsInUrl,
forceMultipart: mpe,
params: paramsAsOptions ? params : {},
autoUpload: false
Expand All @@ -32,6 +32,22 @@ if (qqtest.canDownloadFileAsBlob) {
return uploader;
}

function getSimpleParamsInHeaderUploader(paramsAsOptions, headerParamPrefix) {
var uploader = new qq.FineUploaderBasic({
request: {
endpoint: testUploadEndpoint,
paramsMode: qq.paramsMode.paramsInHeader,
headerParamPrefix: headerParamPrefix,
forceMultipart: true,
params: paramsAsOptions ? params : {},
autoUpload: false
}
});

!paramsAsOptions && uploader.setParams(params);
return uploader;
}

function getSimpleHeadersUploader(headersAsOptions) {
var uploader = new qq.FineUploaderBasic({
request: {
Expand All @@ -45,16 +61,18 @@ if (qqtest.canDownloadFileAsBlob) {
return uploader;
}

function assertParamsInRequest(uploader, mpe, done, overrideParams) {
function assertParamsInRequest(uploader, paramsMode, done, overrideParams) {
assert.expect(4, done);

qqtest.downloadFileAsBlob("up.jpg", "image/jpeg").then(function(blob) {

fileTestHelper.mockXhr();

var request,
requestParams,
purlUrl,
theparams = overrideParams || params;
theparams = overrideParams || params,
headerParamPrefix = headerParamPrefix || "";

uploader.addFiles({name: "test", blob: blob});
uploader.uploadStoredFiles();
Expand All @@ -64,9 +82,21 @@ if (qqtest.canDownloadFileAsBlob) {
requestParams = request.requestBody.fields;
purlUrl = purl(request.url);

assert.equal(mpe ? requestParams.foo : purlUrl.param("foo"), theparams.foo, "'foo' param value incorrect");
assert.equal(mpe ? requestParams.one : purlUrl.param("one"), theparams.one, "'one' param value incorrect");
assert.equal(mpe ? requestParams.thefunc : purlUrl.param("thefunc"), theparams.thefunc(), "'thefunc' param value incorrect");
if (paramsMode === qq.paramsMode.paramsInBody) {
assert.equal(requestParams.foo, theparams.foo, "'foo' param value incorrect");
assert.equal(requestParams.one, theparams.one, "'one' param value incorrect");
assert.equal(requestParams.thefunc, theparams.thefunc(), "'thefunc' param value incorrect");
}
else if (paramsMode === qq.paramsMode.paramsInUrl) {
assert.equal(purlUrl.param("foo"), theparams.foo, "'foo' param value incorrect");
assert.equal(purlUrl.param("one"), theparams.one, "'one' param value incorrect");
assert.equal(purlUrl.param("thefunc"), theparams.thefunc(), "'thefunc' param value incorrect");
}
else if (paramsMode === qq.paramsMode.paramsInHeader) {
assert.equal(request.requestHeaders.foo, theparams.foo, "'foo' param value incorrect");
assert.equal(request.requestHeaders.one, theparams.one, "'one' param value incorrect");
assert.equal(request.requestHeaders.thefunc, theparams.thefunc, "'thefunc' param value incorrect");
}

fileTestHelper.getRequests()[0].respond(200, null, JSON.stringify({success: true}));
});
Expand Down Expand Up @@ -96,38 +126,68 @@ if (qqtest.canDownloadFileAsBlob) {

it("sends correct params in request for MPE uploads w/ params specified as options only", function(done) {
var uploader = getSimpleParamsUploader(true, true);
assertParamsInRequest(uploader, true, done);
assertParamsInRequest(uploader, qq.paramsMode.paramsInBody, done);
});

it("sends correct params in request for non-MPE uploads w/ params specified as options only", function(done) {
var uploader = getSimpleParamsUploader(false, true);
assertParamsInRequest(uploader, false, done);
assertParamsInRequest(uploader, qq.paramsMode.paramsInUrl, done);
});

it("sends correct params in header of request for MPE uploads w/ params specified as options only", function(done) {
var uploader = getSimpleParamsInHeaderUploader(true, "");
assertParamsInRequest(uploader, qq.paramsMode.paramsInHeader, done);
});

it("sends correct params in header of request with prefix for MPE uploads w/ params specified as options only", function(done) {
var headerParamPrefix = "x-upload-data-",
uploader = getSimpleParamsInHeaderUploader(true, headerParamPrefix);

assert.expect(4, done);

qqtest.downloadFileAsBlob("up.jpg", "image/jpeg").then(function(blob) {
fileTestHelper.mockXhr();

var requestHeaders;

uploader.addFiles({name: "test", blob: blob});
uploader.uploadStoredFiles();

assert.equal(fileTestHelper.getRequests().length, 1, "Wrong # of requests");
requestHeaders = fileTestHelper.getRequests()[0].requestHeaders;

assert.equal(requestHeaders[headerParamPrefix + "foo"], params.foo, "'foo' param value incorrect");
assert.equal(requestHeaders[headerParamPrefix + "one"], params.one, "'one' param value incorrect");
assert.equal(requestHeaders[headerParamPrefix + "thefunc"], params.thefunc, "'thefunc' param value incorrect");

fileTestHelper.getRequests()[0].respond(200, null, JSON.stringify({success: true}));
});
});

it("Sends correct params in request for MPE uploads w/ params specified via API only", function(done) {
var uploader = getSimpleParamsUploader(true, false);
assertParamsInRequest(uploader, true, done);
assertParamsInRequest(uploader, qq.paramsMode.paramsInBody, done);
});

it("sends correct params in request for non-MPE uploads w/ params specified as options only", function(done) {
var uploader = getSimpleParamsUploader(false, false);
assertParamsInRequest(uploader, false, done);
assertParamsInRequest(uploader, qq.paramsMode.paramsInUrl, done);
});

it("sends correct params in request for MPE uploads w/ params initially specified via options then overriden via API", function(done) {
var uploader = getSimpleParamsUploader(true, true),
overridenParams = qq.extend({one: 3}, params);

uploader.setParams(overridenParams);
assertParamsInRequest(uploader, true, done, overridenParams);
assertParamsInRequest(uploader, qq.paramsMode.paramsInBody, done, overridenParams);
});

it("sends correct params in request for non-MPE uploads w/ params initially specified via options then overriden via API", function(done) {
var uploader = getSimpleParamsUploader(false, true),
overridenParams = qq.extend({foo: "abc"}, params);

uploader.setParams(overridenParams);
assertParamsInRequest(uploader, false, done, overridenParams);
assertParamsInRequest(uploader, qq.paramsMode.paramsInUrl, done, overridenParams);
});

it("sends correct params in request for MPE uploads when params are overriden via API for specific files", function(done) {
Expand All @@ -136,7 +196,7 @@ if (qqtest.canDownloadFileAsBlob) {

uploader.setParams(overridenParams, 0);
uploader.setParams({}, 1);
assertParamsInRequest(uploader, true, done, overridenParams);
assertParamsInRequest(uploader, qq.paramsMode.paramsInBody, done, overridenParams);
});

it("sends correct params in request for non-MPE uploads when params are overriden via API for specific files", function(done) {
Expand All @@ -145,7 +205,7 @@ if (qqtest.canDownloadFileAsBlob) {

uploader.setParams(overridenParams, 0);
uploader.setParams({}, 1);
assertParamsInRequest(uploader, false, done, overridenParams);
assertParamsInRequest(uploader, qq.paramsMode.paramsInUrl, done, overridenParams);
});

it("sends correct headers in request w/ headers specified as options", function(done) {
Expand Down
4 changes: 2 additions & 2 deletions test/unit/simple-file-uploads.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ if (qqtest.canDownloadFileAsBlob) {
autoUpload: autoUpload,
request: {
endpoint: testUploadEndpoint,
paramsInBody: mpe,
paramsMode: mpe ? qq.paramsMode.paramsInBody : qq.paramsMode.paramsInUrl,
forceMultipart: mpe
},
callbacks: {
Expand Down Expand Up @@ -478,7 +478,7 @@ if (qqtest.canDownloadFileAsBlob) {
uploader.addFiles(canvasWrapper);
});
});

it("removes reference to a Blob via API", function(done) {
qqtest.downloadFileAsBlob("up.jpg", "image/jpeg").then(function(blob) {
fileTestHelper.mockXhr();
Expand Down

0 comments on commit 08d0787

Please sign in to comment.