From 45f0939758c5bce397ea7434645dd53b99860a83 Mon Sep 17 00:00:00 2001 From: Georgios Kalpakas Date: Wed, 13 Jul 2016 15:30:32 +0300 Subject: [PATCH 1/2] fix($resource): allow params in `hostname` (except for IPv6 addresses) Support for IPv6 addresses (in b643f0d) was too aggressive and broke support for params in the `hostname` part of a URL. This commit restores support for params in the `hostname`, as long as it is not an IPv6 address. Fixes #14542 --- src/ngResource/resource.js | 10 +++---- test/ngResource/resourceSpec.js | 50 +++++++++++++++++++++++++++++---- 2 files changed, 50 insertions(+), 10 deletions(-) diff --git a/src/ngResource/resource.js b/src/ngResource/resource.js index 5c875a97ce55..f9f33670bd04 100644 --- a/src/ngResource/resource.js +++ b/src/ngResource/resource.js @@ -430,7 +430,7 @@ function shallowClearAndCopy(src, dst) { */ angular.module('ngResource', ['ng']). provider('$resource', function ResourceProvider() { - var PROTOCOL_AND_DOMAIN_REGEX = /^https?:\/\/[^/]*/; + var PROTOCOL_AND_IPV6_REGEX = /^https?:\/\/\[[^\]]*][^/]*/; var provider = this; @@ -541,7 +541,7 @@ angular.module('ngResource', ['ng']). url = actionUrl || self.template, val, encodedVal, - protocolAndDomain = ''; + protocolAndIpv6 = ''; var urlParams = self.urlParams = Object.create(null); forEach(url.split(/\W/), function(param) { @@ -556,8 +556,8 @@ angular.module('ngResource', ['ng']). } }); url = url.replace(/\\:/g, ':'); - url = url.replace(PROTOCOL_AND_DOMAIN_REGEX, function(match) { - protocolAndDomain = match; + url = url.replace(PROTOCOL_AND_IPV6_REGEX, function(match) { + protocolAndIpv6 = match; return ''; }); @@ -594,7 +594,7 @@ angular.module('ngResource', ['ng']). // E.g. `http://url.com/id./format?q=x` becomes `http://url.com/id.format?q=x` url = url.replace(/\/\.(?=\w+($|\?))/, '.'); // replace escaped `/\.` with `/.` - config.url = protocolAndDomain + url.replace(/\/\\\./, '/.'); + config.url = protocolAndIpv6 + url.replace(/\/\\\./, '/.'); // set params - delegate param encoding to $http diff --git a/test/ngResource/resourceSpec.js b/test/ngResource/resourceSpec.js index 41dc071b37a7..2c87d52d921a 100644 --- a/test/ngResource/resourceSpec.js +++ b/test/ngResource/resourceSpec.js @@ -321,11 +321,51 @@ describe('basic usage', function() { }); it('should support IPv6 URLs', function() { - var R = $resource('http://[2620:0:861:ed1a::1]/:ed1a/', {}, {}, {stripTrailingSlashes: false}); - $httpBackend.expect('GET', 'http://[2620:0:861:ed1a::1]/foo/').respond({}); - $httpBackend.expect('GET', 'http://[2620:0:861:ed1a::1]/').respond({}); - R.get({ed1a: 'foo'}); - R.get({}); + var keepSlashes = {stripTrailingSlashes: false}; + + var R1 = $resource('http://[2620:0:861:ed1a::1]', null, null, keepSlashes); + var R2 = $resource('http://[2620:0:861:ed1a::1]/', null, null, keepSlashes); + var R3 = $resource('http://[2620:0:861:ed1a::1]/:ed1a', null, null, keepSlashes); + var R4 = $resource('http://[2620:0:861:ed1a::1]/:ed1a/', null, null, keepSlashes); + + $httpBackend.expect('GET', 'http://[2620:0:861:ed1a::1]').respond(null); // R1 + $httpBackend.expect('GET', 'http://[2620:0:861:ed1a::1]/').respond(null); // R2 + $httpBackend.expect('GET', 'http://[2620:0:861:ed1a::1]/foo').respond(null); // R3 + $httpBackend.expect('GET', 'http://[2620:0:861:ed1a::1]/').respond(null); // R3 + $httpBackend.expect('GET', 'http://[2620:0:861:ed1a::1]/foo/').respond(null); // R4 + $httpBackend.expect('GET', 'http://[2620:0:861:ed1a::1]/').respond(null); // R4 + + R1.get({ed1a: 'foo'}); + R2.get({ed1a: 'foo'}); + R3.get({ed1a: 'foo'}); + R3.get({}); + R4.get({ed1a: 'foo'}); + R4.get({}); + }); + + it('should support params in the `hostname` part of the URL', function() { + var keepSlashes = {stripTrailingSlashes: false}; + + var R1 = $resource('http://:hostname', null, null, keepSlashes); + var R2 = $resource('http://:hostname/', null, null, keepSlashes); + var R3 = $resource('http://:l2Domain.:l1Domain', null, null, keepSlashes); + var R4 = $resource('http://:l2Domain.:l1Domain/', null, null, keepSlashes); + var R5 = $resource('http://127.0.0.:octet', null, null, keepSlashes); + var R6 = $resource('http://127.0.0.:octet/', null, null, keepSlashes); + + $httpBackend.expect('GET', 'http://foo.com').respond(null); // R1 + $httpBackend.expect('GET', 'http://foo.com/').respond(null); // R2 + $httpBackend.expect('GET', 'http://bar.com').respond(null); // R3 + $httpBackend.expect('GET', 'http://bar.com/').respond(null); // R4 + $httpBackend.expect('GET', 'http://127.0.0.42').respond(null); // R5 + $httpBackend.expect('GET', 'http://127.0.0.42/').respond(null); // R6 + + R1.get({hostname: 'foo.com'}); + R2.get({hostname: 'foo.com'}); + R3.get({l1Domain: 'com', l2Domain: 'bar'}); + R4.get({l1Domain: 'com', l2Domain: 'bar'}); + R5.get({octet: 42}); + R6.get({octet: 42}); }); it('should support overriding provider default trailing-slash stripping configuration', function() { From b617b25582bbb206777225ba9e472ea43ce950ba Mon Sep 17 00:00:00 2001 From: Georgios Kalpakas Date: Sat, 3 Dec 2016 00:42:26 +0200 Subject: [PATCH 2/2] fixup! fix($resource): allow params in `hostname` (except for IPv6 addresses) --- test/ngResource/resourceSpec.js | 68 +++++++++++++-------------------- 1 file changed, 26 insertions(+), 42 deletions(-) diff --git a/test/ngResource/resourceSpec.js b/test/ngResource/resourceSpec.js index 2c87d52d921a..3e59ccb11fea 100644 --- a/test/ngResource/resourceSpec.js +++ b/test/ngResource/resourceSpec.js @@ -321,51 +321,35 @@ describe('basic usage', function() { }); it('should support IPv6 URLs', function() { - var keepSlashes = {stripTrailingSlashes: false}; - - var R1 = $resource('http://[2620:0:861:ed1a::1]', null, null, keepSlashes); - var R2 = $resource('http://[2620:0:861:ed1a::1]/', null, null, keepSlashes); - var R3 = $resource('http://[2620:0:861:ed1a::1]/:ed1a', null, null, keepSlashes); - var R4 = $resource('http://[2620:0:861:ed1a::1]/:ed1a/', null, null, keepSlashes); - - $httpBackend.expect('GET', 'http://[2620:0:861:ed1a::1]').respond(null); // R1 - $httpBackend.expect('GET', 'http://[2620:0:861:ed1a::1]/').respond(null); // R2 - $httpBackend.expect('GET', 'http://[2620:0:861:ed1a::1]/foo').respond(null); // R3 - $httpBackend.expect('GET', 'http://[2620:0:861:ed1a::1]/').respond(null); // R3 - $httpBackend.expect('GET', 'http://[2620:0:861:ed1a::1]/foo/').respond(null); // R4 - $httpBackend.expect('GET', 'http://[2620:0:861:ed1a::1]/').respond(null); // R4 - - R1.get({ed1a: 'foo'}); - R2.get({ed1a: 'foo'}); - R3.get({ed1a: 'foo'}); - R3.get({}); - R4.get({ed1a: 'foo'}); - R4.get({}); + test('http://[2620:0:861:ed1a::1]', {ed1a: 'foo'}, 'http://[2620:0:861:ed1a::1]'); + test('http://[2620:0:861:ed1a::1]/', {ed1a: 'foo'}, 'http://[2620:0:861:ed1a::1]/'); + test('http://[2620:0:861:ed1a::1]/:ed1a', {ed1a: 'foo'}, 'http://[2620:0:861:ed1a::1]/foo'); + test('http://[2620:0:861:ed1a::1]/:ed1a', {}, 'http://[2620:0:861:ed1a::1]/'); + test('http://[2620:0:861:ed1a::1]/:ed1a/', {ed1a: 'foo'}, 'http://[2620:0:861:ed1a::1]/foo/'); + test('http://[2620:0:861:ed1a::1]/:ed1a/', {}, 'http://[2620:0:861:ed1a::1]/'); + + // Helpers + function test(templateUrl, params, actualUrl) { + var R = $resource(templateUrl, null, null, {stripTrailingSlashes: false}); + $httpBackend.expect('GET', actualUrl).respond(null); + R.get(params); + } }); it('should support params in the `hostname` part of the URL', function() { - var keepSlashes = {stripTrailingSlashes: false}; - - var R1 = $resource('http://:hostname', null, null, keepSlashes); - var R2 = $resource('http://:hostname/', null, null, keepSlashes); - var R3 = $resource('http://:l2Domain.:l1Domain', null, null, keepSlashes); - var R4 = $resource('http://:l2Domain.:l1Domain/', null, null, keepSlashes); - var R5 = $resource('http://127.0.0.:octet', null, null, keepSlashes); - var R6 = $resource('http://127.0.0.:octet/', null, null, keepSlashes); - - $httpBackend.expect('GET', 'http://foo.com').respond(null); // R1 - $httpBackend.expect('GET', 'http://foo.com/').respond(null); // R2 - $httpBackend.expect('GET', 'http://bar.com').respond(null); // R3 - $httpBackend.expect('GET', 'http://bar.com/').respond(null); // R4 - $httpBackend.expect('GET', 'http://127.0.0.42').respond(null); // R5 - $httpBackend.expect('GET', 'http://127.0.0.42/').respond(null); // R6 - - R1.get({hostname: 'foo.com'}); - R2.get({hostname: 'foo.com'}); - R3.get({l1Domain: 'com', l2Domain: 'bar'}); - R4.get({l1Domain: 'com', l2Domain: 'bar'}); - R5.get({octet: 42}); - R6.get({octet: 42}); + test('http://:hostname', {hostname: 'foo.com'}, 'http://foo.com'); + test('http://:hostname/', {hostname: 'foo.com'}, 'http://foo.com/'); + test('http://:l2Domain.:l1Domain', {l1Domain: 'com', l2Domain: 'bar'}, 'http://bar.com'); + test('http://:l2Domain.:l1Domain/', {l1Domain: 'com', l2Domain: 'bar'}, 'http://bar.com/'); + test('http://127.0.0.:octet', {octet: 42}, 'http://127.0.0.42'); + test('http://127.0.0.:octet/', {octet: 42}, 'http://127.0.0.42/'); + + // Helpers + function test(templateUrl, params, actualUrl) { + var R = $resource(templateUrl, null, null, {stripTrailingSlashes: false}); + $httpBackend.expect('GET', actualUrl).respond(null); + R.get(params); + } }); it('should support overriding provider default trailing-slash stripping configuration', function() {