Skip to content

Commit

Permalink
Fixed issue with double encoding urls
Browse files Browse the repository at this point in the history
  • Loading branch information
jonsamwell committed Oct 11, 2015
1 parent 5f32770 commit e63d0a5
Show file tree
Hide file tree
Showing 10 changed files with 168 additions and 30 deletions.
4 changes: 2 additions & 2 deletions .jshintrc
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"noarg": true,
"noempty": true,
"nonew": true,
"trailing": true,
"trailing": false,
"maxlen": 512,
"boss": true,
"eqnull": false,
Expand All @@ -30,4 +30,4 @@
"it": true,
"should": true
}
}
}
2 changes: 1 addition & 1 deletion bower.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "angular-http-batcher",
"version": "1.11.3",
"version": "1.12.0",
"description": "Enables transparent HTTP batch requests with Angular",
"main": "dist/angular-http-batch.js",
"keywords": [
Expand Down
5 changes: 5 additions & 0 deletions dist/ChangeLog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
12/10/2015 V1.12.0
Now handles multiple JSON Vulnerability Prefixes in same response
Add unique request part names to Content-Disposition header for use with tomcat servlet 3.1
Fix to stop multiple url encoding of query string parameters in http batch adapter

27/08/2015 V1.11.3
Fixed error when trimming response to protect against JSON vulnerability error (pr by @magarcia https://github.com/magarcia)
Use encodeURI to process query strings with spaces and other such characters in default http adapter. (pr by https://github.com/tiwariarvin)
Expand Down
55 changes: 34 additions & 21 deletions dist/angular-http-batch.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* angular-http-batcher - v1.11.3 - 2015-08-27
* angular-http-batcher - v1.12.0 - 2015-10-12
* https://github.com/jonsamwell/angular-http-batcher
* Copyright (c) 2015 Jon Samwell
*/
Expand Down Expand Up @@ -29,7 +29,8 @@ function HttpBatchConfigFn() {
ignoredVerbs: ['head'],
sendCookies: false,
enabled: true,
adapter: defaultBatchAdapter
adapter: defaultBatchAdapter,
uniqueRequestName: null
};

/**
Expand Down Expand Up @@ -203,7 +204,9 @@ function HttpBatchAdapter($document, $window, httpBatchConfig) {
singleSpace: ' ',
forwardSlash: '/',
doubleDash: '--',
colon: ':'
colon: ':',
semiColon: ';',
requestName: 'name='
};

self.key = 'httpBatchAdapter';
Expand Down Expand Up @@ -231,7 +234,7 @@ function HttpBatchAdapter($document, $window, httpBatchConfig) {
headers: config.batchRequestHeaders || {}
},
batchBody = [],
urlInfo, i, request, header;
urlInfo, i, request, header, relativeUrlParts, encodedRelativeUrl;

httpConfig.headers[constants.contentType] = 'multipart/mixed; boundary=' + boundary;

Expand All @@ -242,13 +245,24 @@ function HttpBatchAdapter($document, $window, httpBatchConfig) {
batchBody.push(constants.doubleDash + boundary);
if (config.batchPartRequestHeaders) {
for (header in config.batchPartRequestHeaders) {
batchBody.push(header + constants.colon + constants.singleSpace + config.batchPartRequestHeaders[header]);
if (config.batchPartRequestHeaders.hasOwnProperty(header)) {
var currHeader = header + constants.colon + constants.singleSpace + config.batchPartRequestHeaders[header];
if (header.toLowerCase() === "content-disposition" && config.uniqueRequestName !== null && config.uniqueRequestName !== undefined) {
currHeader += constants.semiColon + constants.singleSpace + constants.requestName + config.uniqueRequestName + i;
}
batchBody.push(currHeader);
}
}
}

batchBody.push('Content-Type: application/http; msgtype=request', constants.emptyString);

batchBody.push(request.method + ' ' + encodeURI(urlInfo.relativeUrl) + ' ' + constants.httpVersion);
// angular would have already encoded the parameters *if* the dev passed them in via the params parameter to $http
// so we only need to url encode the url not the query string part
relativeUrlParts = urlInfo.relativeUrl.split('?');
encodedRelativeUrl = encodeURI(relativeUrlParts[0]) + (relativeUrlParts.length > 1 ? '?' + relativeUrlParts[1] : '');

batchBody.push(request.method + ' ' + encodedRelativeUrl + ' ' + constants.httpVersion);
batchBody.push('Host: ' + urlInfo.host);

for (header in request.headers) {
Expand Down Expand Up @@ -365,18 +379,30 @@ function HttpBatchAdapter($document, $window, httpBatchConfig) {
function findResponseBoundary(contentType) {
var boundaryText = 'boundary=',
startIndex = contentType.indexOf(boundaryText),
boundary = contentType.substring(startIndex + boundaryText.length);
endIndex = contentType.indexOf(';', startIndex),
boundary = contentType.substring(startIndex + boundaryText.length, endIndex > 0 ? endIndex : contentType.length);

// the boundary might be quoted so remove the quotes
boundary = boundary.replace(/"/g, constants.emptyString);
return boundary;
}

/**
* see https://docs.angularjs.org/api/ng/service/$http#json-vulnerability-protection
* @param data
* @returns {*|void|string}
*/
function trimJsonProtectionVulnerability(data) {
return typeof (data) === 'string' ? data.replace(')]}\',\n', '') : data;
}

function convertDataToCorrectType(contentType, dataStr) {
var data = dataStr;
contentType = contentType.toLowerCase();

if (contentType.indexOf('json') > -1) {
// only remove json vulnerability prefix if we're parsing json
dataStr = trimJsonProtectionVulnerability(dataStr);
data = angular.fromJson(dataStr);
}

Expand Down Expand Up @@ -559,27 +585,14 @@ function addRequestFn(request) {
return true;
}

/**
* see https://docs.angularjs.org/api/ng/service/$http#json-vulnerability-protection
* @param data
* @returns {*|void|string}
*/
function trimJsonProtectionVulnerability(data) {
return typeof (data) === 'string' ? data.replace(')]}\',\n', '') : data;
}

function sendFn() {
var self = this,
adapter = self.getAdapter(),
httpBatchConfig = adapter.buildRequest(self.requests, self.config);

self.sendCallback();
self.$injector.get('$http')(httpBatchConfig).then(function (response) {
var batchResponses;

response.data = trimJsonProtectionVulnerability(response.data);

batchResponses = adapter.parseResponse(self.requests, response, self.config);
var batchResponses = adapter.parseResponse(self.requests, response, self.config);

angular.forEach(batchResponses, function (batchResponse) {
batchResponse.request.callback(
Expand Down
Loading

0 comments on commit e63d0a5

Please sign in to comment.