Skip to content

Commit c91d7a7

Browse files
committed
Erase base URL parts if their preceding parts have overwritten by relative URL
1 parent e7dc9f7 commit c91d7a7

File tree

4 files changed

+19539
-100
lines changed

4 files changed

+19539
-100
lines changed

src/Curl/Url.php

Lines changed: 51 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -92,54 +92,61 @@ public static function removeDotSegments($input)
9292
private function absolutizeUrl()
9393
{
9494
$b = $this->parseUrl($this->baseUrl);
95-
96-
if (!($this->relativeUrl === null)) {
97-
$r = $this->parseUrl($this->relativeUrl);
98-
99-
// Copy relative parts to base url.
100-
if (isset($r['scheme'])) {
101-
$b['scheme'] = $r['scheme'];
102-
}
103-
if (isset($r['host'])) {
104-
$b['host'] = $r['host'];
105-
}
106-
if (isset($r['port'])) {
107-
$b['port'] = $r['port'];
108-
}
109-
if (isset($r['user'])) {
110-
$b['user'] = $r['user'];
111-
}
112-
if (isset($r['pass'])) {
113-
$b['pass'] = $r['pass'];
114-
}
115-
116-
if (!isset($r['path']) || $r['path'] === '') {
117-
$r['path'] = '/';
118-
}
119-
// Merge relative url with base when relative url's path doesn't start with a slash.
120-
if (!(StrUtil::startsWith($r['path'], '/'))) {
121-
$base = mb_strrchr($b['path'], '/', true);
122-
if ($base === false) {
123-
$base = '';
95+
if (!isset($b['path'])) {
96+
$b['path'] = '/';
97+
}
98+
if (is_null($this->relativeUrl)) {
99+
return $this->unparseUrl($b);
100+
}
101+
$r = $this->parseUrl($this->relativeUrl);
102+
$r['authorized'] = isset($r['scheme']) || isset($r['host']) || isset($r['port'])
103+
|| isset($r['user']) || isset($r['pass']);
104+
$target = array();
105+
if (isset($r['scheme'])) {
106+
$target['scheme'] = $r['scheme'];
107+
$target['host'] = isset($r['host']) ? $r['host'] : null;
108+
$target['port'] = isset($r['port']) ? $r['port'] : null;
109+
$target['user'] = isset($r['user']) ? $r['user'] : null;
110+
$target['pass'] = isset($r['pass']) ? $r['pass'] : null;
111+
$target['path'] = isset($r['path']) ? self::removeDotSegments($r['path']) : null;
112+
$target['query'] = isset($r['query']) ? $r['query'] : null;
113+
} else {
114+
$target['scheme'] = isset($b['scheme']) ? $b['scheme'] : null;
115+
if ($r['authorized']) {
116+
$target['host'] = isset($r['host']) ? $r['host'] : null;
117+
$target['port'] = isset($r['port']) ? $r['port'] : null;
118+
$target['user'] = isset($r['user']) ? $r['user'] : null;
119+
$target['pass'] = isset($r['pass']) ? $r['pass'] : null;
120+
$target['path'] = isset($r['path']) ? self::removeDotSegments($r['path']) : null;
121+
$target['query'] = isset($r['query']) ? $r['query'] : null;
122+
} else {
123+
$target['host'] = isset($b['host']) ? $b['host'] : null;
124+
$target['port'] = isset($b['port']) ? $b['port'] : null;
125+
$target['user'] = isset($b['user']) ? $b['user'] : null;
126+
$target['pass'] = isset($b['pass']) ? $b['pass'] : null;
127+
if (!isset($r['path']) || $r['path'] === '') {
128+
$target['path'] = $b['path'];
129+
$target['query'] = isset($r['query']) ? $r['query'] : (isset($b['query']) ? $b['query'] : null);
130+
} else {
131+
if (StrUtil::startsWith($r['path'], '/')) {
132+
$target['path'] = self::removeDotSegments($r['path']);
133+
} else {
134+
$base = mb_strrchr($b['path'], '/', true);
135+
if ($base === false) {
136+
$base = '';
137+
}
138+
$target['path'] = self::removeDotSegments($base . '/' . $r['path']);
139+
}
140+
$target['query'] = isset($r['query']) ? $r['query'] : null;
124141
}
125-
$r['path'] = $base . '/' . $r['path'];
126-
}
127-
$b['path'] = $r['path'];
128-
$b['path'] = $this->removeDotSegments($b['path']);
129-
130-
if (isset($r['query'])) {
131-
$b['query'] = $r['query'];
132-
}
133-
if (isset($r['fragment'])) {
134-
$b['fragment'] = $r['fragment'];
135142
}
136143
}
137-
138-
if (!isset($b['path'])) {
139-
$b['path'] = '/';
144+
if ($this->relativeUrl === '') {
145+
$target['fragment'] = isset($b['fragment']) ? $b['fragment'] : null;
146+
} else {
147+
$target['fragment'] = isset($r['fragment']) ? $r['fragment'] : null;
140148
}
141-
142-
$absolutized_url = $this->unparseUrl($b);
149+
$absolutized_url = $this->unparseUrl($target);
143150
return $absolutized_url;
144151
}
145152

tests/PHPCurlClass/PHPCurlClassTest.php

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3580,31 +3580,56 @@ public function testRelativeUrl()
35803580
foreach ($tests as $test) {
35813581
$curl = new Curl($test['args']['0']);
35823582
$curl->setUrl($test['args']['1']);
3583-
$this->assertEquals($test['expected'], $curl->getOpt(CURLOPT_URL));
3583+
$this->assertEquals(
3584+
$test['expected'],
3585+
$curl->getOpt(CURLOPT_URL),
3586+
"Joint URLs: '{$test['args']['0']}', '{$test['args']['1']}'"
3587+
);
35843588

35853589
$curl = new Curl($test['args']['0']);
35863590
$curl->setUrl($test['args']['1'], array('a' => '1', 'b' => '2'));
3587-
$this->assertEquals($test['expected'] . '?a=1&b=2', $curl->getOpt(CURLOPT_URL));
3591+
$this->assertEquals(
3592+
$test['expected'] . '?a=1&b=2',
3593+
$curl->getOpt(CURLOPT_URL),
3594+
"Joint URL '{$test['args']['0']}' with parameters a=1, b=2"
3595+
);
35883596

35893597
$curl = new Curl();
35903598
$curl->setUrl($test['args']['0']);
35913599
$curl->setUrl($test['args']['1']);
3592-
$this->assertEquals($test['expected'], $curl->getOpt(CURLOPT_URL));
3600+
$this->assertEquals(
3601+
$test['expected'],
3602+
$curl->getOpt(CURLOPT_URL),
3603+
"Joint URLs: '{$test['args']['0']}', '{$test['args']['1']}'"
3604+
);
35933605

35943606
$curl = new Curl();
35953607
$curl->setUrl($test['args']['0'], array('a' => '1', 'b' => '2'));
35963608
$curl->setUrl($test['args']['1']);
3597-
$this->assertEquals($test['expected'] . '?a=1&b=2', $curl->getOpt(CURLOPT_URL));
3609+
$this->assertEquals(
3610+
$test['expected'],
3611+
$curl->getOpt(CURLOPT_URL),
3612+
"Joint URL '{$test['args']['0']}' with parameters a=1, b=2 and URL '{$test['args']['1']}'"
3613+
);
35983614

35993615
$curl = new Curl();
36003616
$curl->setUrl($test['args']['0']);
36013617
$curl->setUrl($test['args']['1'], array('a' => '1', 'b' => '2'));
3602-
$this->assertEquals($test['expected'] . '?a=1&b=2', $curl->getOpt(CURLOPT_URL));
3618+
$this->assertEquals(
3619+
$test['expected'] . '?a=1&b=2',
3620+
$curl->getOpt(CURLOPT_URL),
3621+
"Joint URL '{$test['args']['0']}' and URL '{$test['args']['1']}' with parameters a=1, b=2"
3622+
);
36033623

36043624
$curl = new Curl();
36053625
$curl->setUrl($test['args']['0'], array('a' => '1', 'b' => '2'));
36063626
$curl->setUrl($test['args']['1'], array('c' => '3', 'd' => '4'));
3607-
$this->assertEquals($test['expected'] . '?c=3&d=4', $curl->getOpt(CURLOPT_URL));
3627+
$this->assertEquals(
3628+
$test['expected'] . '?c=3&d=4',
3629+
$curl->getOpt(CURLOPT_URL),
3630+
"Joint URL '{$test['args']['0']}' with parameters a=1, b=2 " .
3631+
"and URL '{$test['args']['1']}' with parameters c=3, d=4"
3632+
);
36083633
}
36093634
}
36103635
}

tests/PHPCurlClass/UrlTest.php

Lines changed: 9 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -8,56 +8,15 @@ class UrlTest extends \PHPUnit\Framework\TestCase
88
{
99
public function testUrlPaths()
1010
{
11-
$tests = array(
12-
array(
13-
'args' => array(
14-
'http://www.example.com/',
15-
'/foo',
16-
),
17-
'expected' => 'http://www.example.com/foo',
18-
),
19-
array(
20-
'args' => array(
21-
'http://www.example.com/',
22-
'/foo/',
23-
),
24-
'expected' => 'http://www.example.com/foo/',
25-
),
26-
array(
27-
'args' => array(
28-
'http://www.example.com/',
29-
'/dir/page.html',
30-
),
31-
'expected' => 'http://www.example.com/dir/page.html',
32-
),
33-
array(
34-
'args' => array(
35-
'http://www.example.com/dir1/page2.html',
36-
'/dir/page.html',
37-
),
38-
'expected' => 'http://www.example.com/dir/page.html',
39-
),
40-
array(
41-
'args' => array(
42-
'http://www.example.com/dir1/page2.html',
43-
'dir/page.html',
44-
),
45-
'expected' => 'http://www.example.com/dir1/dir/page.html',
46-
),
47-
array(
48-
'args' => array(
49-
'http://www.example.com/dir1/dir3/page.html',
50-
'../dir/page.html',
51-
),
52-
'expected' => 'http://www.example.com/dir1/dir/page.html',
53-
),
54-
);
55-
foreach ($tests as $test) {
56-
$reflector = new \ReflectionClass('\Curl\Url');
57-
$url = $reflector->newInstanceArgs($test['args']);
11+
$urls_file = fopen(dirname(__FILE__) . '/urls.csv', 'r');
12+
fgetcsv($urls_file); // header
13+
while (($test = fgetcsv($urls_file)) !== false) {
14+
$url = new Url($test[0], $test[1]);
5815
$actual_url = (string)$url;
59-
$this->assertEquals($test['expected'], $actual_url);
16+
$expected_url = $test[2];
17+
$this->assertEquals($expected_url, $actual_url, "Joint URLs: '{$test[0]}', '{$test[1]}'");
6018
}
19+
fclose($urls_file);
6120
}
6221

6322
public function testUrlInstances()
@@ -84,10 +43,10 @@ public function testUrlInstances()
8443
$this->assertEquals('https://developer.mozilla.org/en-US/docs', $h);
8544

8645
$k = new Url('https://developers.mozilla.com', 'http://www.example.com');
87-
$this->assertEquals('http://www.example.com/', $k);
46+
$this->assertEquals('http://www.example.com', $k);
8847

8948
$l = new Url($b, 'http://www.example.com');
90-
$this->assertEquals('http://www.example.com/', $l);
49+
$this->assertEquals('http://www.example.com', $l);
9150
}
9251

9352
public function testRemoveDotSegments()

0 commit comments

Comments
 (0)