Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit da74d2d

Browse files
SQUASH ME: feat($httpBackend): JSONP requests now require trusted resource
1 parent fcd8fa9 commit da74d2d

File tree

3 files changed

+50
-17
lines changed

3 files changed

+50
-17
lines changed

docs/content/error/$http/badreq.ngdoc

+5-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33
@fullName Bad Request Configuration
44
@description
55

6-
This error occurs when the request configuration parameter passed to the {@link ng.$http `$http`} service is not an object.  `$http` expects a single parameter, the request configuration object, but received a parameter that was not an object.  The error message should provide additional context such as the actual value of the parameter that was received.  If you passed a string parameter, perhaps you meant to call one of the shorthand methods on `$http` such as `$http.get(…)`, etc.
6+
This error occurs when the request configuration parameter passed to the {@link ng.$http `$http`} service is not a valid object.
7+
`$http` expects a single parameter, the request configuration object, but received a parameter that was not an object or did not contain valid properties.
8+
9+
The error message should provide additional context such as the actual value of the parameter that was received.
10+
If you passed a string parameter, perhaps you meant to call one of the shorthand methods on `$http` such as `$http.get(…)`, etc.
711

812
To resolve this error, make sure you pass a valid request configuration object to `$http`.
913

src/ng/http.js

+24-10
Original file line numberDiff line numberDiff line change
@@ -802,7 +802,8 @@ function $HttpProvider() {
802802
* processed. The object has following properties:
803803
*
804804
* - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)
805-
* - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.
805+
* - **url** – `{string|TrustedObject}` – Absolute or relative URL of the resource that is being requested;
806+
* or an object created by a call to `$sce.trustAsResourceUrl(url)`.
806807
* - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be serialized
807808
* with the `paramSerializer` and appended as GET parameters.
808809
* - **data** – `{string|Object}` – Data to be sent as the request message data.
@@ -882,6 +883,7 @@ function $HttpProvider() {
882883
<file name="script.js">
883884
angular.module('httpExample', [])
884885
.config(['$sceDelegateProvider', function($sceDelegateProvider) {
886+
// We must whitelist the JSONP endpoint that we are using to show that we trust it
885887
$sceDelegateProvider.resourceUrlWhitelist([
886888
'self',
887889
'https://angularjs.org/**'
@@ -955,7 +957,7 @@ function $HttpProvider() {
955957
}
956958

957959
if (!isString($sce.valueOf(requestConfig.url))) {
958-
throw minErr('$http')('badreq', 'Http request configuration url must be a string. Received: {0}', requestConfig.url);
960+
throw minErr('$http')('badreq', 'Http request configuration url must be a string or a $sce trusted object. Received: {0}', requestConfig.url);
959961
}
960962

961963
var config = extend({
@@ -1095,11 +1097,10 @@ function $HttpProvider() {
10951097

10961098
// send request
10971099
try {
1098-
var promise = sendReq(config, reqData);
1100+
return sendReq(config, reqData).then(transformResponse, transformResponse);
10991101
} catch (e) {
11001102
return $q.reject(e);
11011103
}
1102-
return promise.then(transformResponse, transformResponse);
11031104
}
11041105

11051106
function transformResponse(response) {
@@ -1122,7 +1123,8 @@ function $HttpProvider() {
11221123
* @description
11231124
* Shortcut method to perform `GET` request.
11241125
*
1125-
* @param {string} url Relative or absolute URL specifying the destination of the request
1126+
* @param {string|TrustedObject} url Absolute or relative URL of the resource that is being requested;
1127+
* or an object created by a call to `$sce.trustAsResourceUrl(url)`.
11261128
* @param {Object=} config Optional configuration object
11271129
* @returns {HttpPromise} Future object
11281130
*/
@@ -1134,7 +1136,8 @@ function $HttpProvider() {
11341136
* @description
11351137
* Shortcut method to perform `DELETE` request.
11361138
*
1137-
* @param {string} url Relative or absolute URL specifying the destination of the request
1139+
* @param {string|TrustedObject} url Absolute or relative URL of the resource that is being requested;
1140+
* or an object created by a call to `$sce.trustAsResourceUrl(url)`.
11381141
* @param {Object=} config Optional configuration object
11391142
* @returns {HttpPromise} Future object
11401143
*/
@@ -1146,7 +1149,8 @@ function $HttpProvider() {
11461149
* @description
11471150
* Shortcut method to perform `HEAD` request.
11481151
*
1149-
* @param {string} url Relative or absolute URL specifying the destination of the request
1152+
* @param {string|TrustedObject} url Absolute or relative URL of the resource that is being requested;
1153+
* or an object created by a call to `$sce.trustAsResourceUrl(url)`.
11501154
* @param {Object=} config Optional configuration object
11511155
* @returns {HttpPromise} Future object
11521156
*/
@@ -1157,11 +1161,18 @@ function $HttpProvider() {
11571161
*
11581162
* @description
11591163
* Shortcut method to perform `JSONP` request.
1164+
*
1165+
* Note that, since JSONP requests are sensitive because the response is given full acces to the browser,
1166+
* the url must be declared, via {@link $sce} as a trusted resource URL.
1167+
* You can trust a URL by adding it to the whitelist via
1168+
* {@link $sceDelegateProvider#resourceUrlWhitelist `$sceDelegateProvider.resourceUrlWhitelist`} or
1169+
* by explicitly trusted the URL via {@link $sce#trustAsResourceUrl `$sce.trustAsResourceUrl(url)`}.
1170+
*
11601171
* If you would like to customise where and how the callbacks are stored then try overriding
11611172
* or decorating the {@link $jsonpCallbacks} service.
11621173
*
1163-
* @param {string} url Relative or absolute URL specifying the destination of the request.
1164-
* The name of the callback should be the string `JSON_CALLBACK`.
1174+
* @param {string|TrustedObject} url Absolute or relative URL of the resource that is being requested;
1175+
* or an object created by a call to `$sce.trustAsResourceUrl(url)`.
11651176
* @param {Object=} config Optional configuration object
11661177
* @returns {HttpPromise} Future object
11671178
*/
@@ -1263,9 +1274,12 @@ function $HttpProvider() {
12631274
url = config.url;
12641275

12651276
if (lowercase(config.method) === 'jsonp') {
1266-
// This is a pretty sensitive operation where we're allowing a script to have full access to
1277+
// JSONP is a pretty sensitive operation where we're allowing a script to have full access to
12671278
// our DOM and JS space. So we require that the URL satisfies SCE.RESOURCE_URL.
12681279
url = $sce.getTrustedResourceUrl(url);
1280+
} else if (!isString(url)) {
1281+
// If it is not a string then the URL must be a $sce trusted object
1282+
url = $sce.valueOf(url);
12691283
}
12701284

12711285
url = buildUrl(url, config.paramSerializer(config.params));

test/ng/httpSpec.js

+21-6
Original file line numberDiff line numberDiff line change
@@ -306,16 +306,31 @@ describe('$http', function() {
306306

307307
it('should throw error if the request configuration is not an object', function() {
308308
expect(function() {
309-
$http('/url');
309+
$http('/url');
310310
}).toThrowMinErr('$http','badreq', 'Http request configuration must be an object. Received: /url');
311311
});
312312

313-
it('should throw error if the request configuration url is not a string', function() {
313+
it('should throw error if the request configuration url is not a string nor a trusted object', function() {
314314
expect(function() {
315-
$http({url: false});
316-
}).toThrowMinErr('$http','badreq', 'Http request configuration url must be a string. Received: false');
315+
$http({url: false});
316+
}).toThrowMinErr('$http','badreq', 'Http request configuration url must be a string or a $sce trusted object. Received: false');
317+
expect(function() {
318+
$http({url: null});
319+
}).toThrowMinErr('$http','badreq', 'Http request configuration url must be a string or a $sce trusted object. Received: null');
320+
expect(function() {
321+
$http({url: 42});
322+
}).toThrowMinErr('$http','badreq', 'Http request configuration url must be a string or a $sce trusted object. Received: 42');
323+
expect(function() {
324+
$http({});
325+
}).toThrowMinErr('$http','badreq', 'Http request configuration url must be a string or a $sce trusted object. Received: undefined');
317326
});
318327

328+
it('should accept a $sce trusted object for the request configuration url', function() {
329+
expect(function() {
330+
$httpBackend.expect('GET', '/url').respond('');
331+
$http({url: $sce.trustAsResourceUrl('/url')});
332+
}).not.toThrowMinErr('$http','badreq', 'Http request configuration url must be a string. Received: false');
333+
});
319334

320335
it('should send GET requests if no method specified', function() {
321336
$httpBackend.expect('GET', '/url').respond('');
@@ -1033,7 +1048,7 @@ describe('$http', function() {
10331048
function(e) { error = e; }
10341049
);
10351050
$rootScope.$digest();
1036-
expect(error.message).toContain("[$sce:insecurl]");
1051+
expect(error.message).toContain('[$sce:insecurl]');
10371052
});
10381053

10391054
it('should not throw error if the url is an explicitly trusted resource', function() {
@@ -1043,7 +1058,7 @@ describe('$http', function() {
10431058
}).not.toThrow();
10441059
});
10451060

1046-
it('jsonp() should allow trusted url', inject(['$sce', function($sce) {
1061+
it('jsonp() should accept explictly trusted urls', inject(['$sce', function($sce) {
10471062
$httpBackend.expect('JSONP', '/url').respond('');
10481063
$http({method: 'JSONP', url: $sce.trustAsResourceUrl('/url')});
10491064

0 commit comments

Comments
 (0)