Skip to content

Commit

Permalink
Merge pull request #5 from imgix/5-fully-qualified-urls
Browse files Browse the repository at this point in the history
UrlBuilder does not CGI-encode fully-qualified URLs
  • Loading branch information
kellysutton committed May 30, 2015
2 parents 516bae0 + 44aaa64 commit f021569
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 50 deletions.
5 changes: 3 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"imgix"
],
"require": {
"php": ">=5.3"
"php": ">=5.3",
"jakeasmith/http_build_url": "^1.0"
},
"require-dev": {
"phpunit/phpunit": "*"
Expand All @@ -16,4 +17,4 @@
"Imgix\\": "src/"
}
}
}
}
41 changes: 39 additions & 2 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 11 additions & 39 deletions src/Imgix/UrlHelper.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?php

namespace Imgix;

class UrlHelper {

private $domain;
Expand All @@ -12,7 +12,8 @@ class UrlHelper {

public function __construct($domain, $path, $scheme = "http", $signKey = "", $params = array()) {
$this->domain = $domain;
$this->path = substr($path, 0, 1) !== "/" ? ("/" . $path) : $path;
$this->path = substr($path, 0, 4) === "http" ? urlencode($path) : $path;
$this->path = substr($this->path, 0, 1) !== "/" ? ("/" . $this->path) : $this->path;
$this->scheme = $scheme;
$this->signKey = $signKey;
$this->params = $params;
Expand Down Expand Up @@ -42,7 +43,7 @@ public function getURL() {
$query = join("&", $queryPairs);

if ($this->signKey) {
$delim = $query === "" ? "" : "?";
$delim = "?";
$toSign = $this->signKey . $this->path . $delim . $query;
$sig = md5($toSign);
if ($query) {
Expand All @@ -54,50 +55,21 @@ public function getURL() {

$url_parts = array('scheme' => $this->scheme, 'host' => $this->domain, 'path' => $this->path, 'query' => $query);

return self::join_url($url_parts);
return self::joinURL($url_parts);
}

public static function encodeURIComponent($str) {
$revert = array('%21'=>'!', '%2A'=>'*', '%27'=>"'", '%28'=>'(', '%29'=>')');
return strtr(rawurlencode($str), $revert);
}

public static function join_url($parts, $encode=true) {
$url = '';
if (!empty($parts['scheme'])) {
$url .= $parts['scheme'] . ':';
}
if (isset($parts['host'])) {
$url .= '//';
if (isset($parts['user'])) {
$url .= $parts['user'];
if (isset($parts['pass']))
$url .= ':' . $parts['pass'];
$url .= '@';
}
if (preg_match('!^[\da-f]*:[\da-f.:]+$!ui', $parts['host'])) {
$url .= '[' . $parts['host'] . ']';
} else {
$url .= $parts['host'];
}
if (isset($parts['port'])) {
$url .= ':' . $parts['port'];
}
if (!empty($parts['path']) && $parts['path'][0] != '/') {
$url .= '/';
}
}
if (!empty($parts['path'])) {
$url .= $parts['path'];
}
if (isset($parts['query']) && strlen($parts['query']) > 0) {
$url .= '?' . $parts['query'];
}
if (isset($parts['fragment'])) {
$url .= '#' . $parts['fragment'];
public static function joinURL($parts) {

// imgix idiosyncracy for signing URLs when only the signature exists. Our query string must begin with '?&s='
if (substr($parts['query'], 0, 2) === "s=") {
$parts['query'] = "&" . $parts['query'];
}

return $url;
return http_build_url($parts);
}

}
30 changes: 27 additions & 3 deletions tests/Imgix/Tests/UrlBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public function testExamplePlain() {
$params = array("w" => 100, "h" => 100);
$url = $builder->createURL("bridge.png", $params);

$this->assertEquals($url, "http://demos.imgix.net/bridge.png?h=100&w=100");
$this->assertEquals("http://demos.imgix.net/bridge.png?h=100&w=100", $url);
}

public function testExamplePlainHttps() {
Expand All @@ -49,7 +49,7 @@ public function testExamplePlainHttps() {
$params = array("w" => 100, "h" => 100);
$url = $builder->createURL("bridge.png", $params);

$this->assertEquals($url, "https://demos.imgix.net/bridge.png?h=100&w=100");
$this->assertEquals("https://demos.imgix.net/bridge.png?h=100&w=100", $url);
}

public function testExamplePlainSecure() {
Expand All @@ -58,7 +58,31 @@ public function testExamplePlainSecure() {
$params = array("w" => 100, "h" => 100);
$url = $builder->createURL("bridge.png", $params);

$this->assertEquals($url, "http://demos.imgix.net/bridge.png?h=100&w=100&s=bb8f3a2ab832e35997456823272103a4");
$this->assertEquals("http://demos.imgix.net/bridge.png?h=100&w=100&s=bb8f3a2ab832e35997456823272103a4", $url);
}

public function testWithFullyQualifiedUrl() {
$builder = new UrlBuilder("demos.imgix.net", true);
$builder->setSignKey("test1234");
$url = $builder->createUrl("http://media.giphy.com/media/jCMq0p94fgBIk/giphy.gif");

$this->assertEquals("https://demos.imgix.net/http%3A%2F%2Fmedia.giphy.com%2Fmedia%2FjCMq0p94fgBIk%2Fgiphy.gif?&s=ffc3359566fe1dc6445ad17d17b98951", $url);
}

public function testWithFullyQualifiedUrlWithSpaces() {
$builder = new UrlBuilder("demos.imgix.net", true);
$builder->setSignKey("test1234");
$url = $builder->createUrl("https://my-demo-site.com/files/133467012/avatar icon.png");

$this->assertEquals("https://demos.imgix.net/https%3A%2F%2Fmy-demo-site.com%2Ffiles%2F133467012%2Favatar+icon.png?&s=f6a4e1504af365564014564f1d7e13de", $url);
}

public function testWithFullyQualifiedUrlWithParams() {
$builder = new UrlBuilder("demos.imgix.net", true);
$builder->setSignKey("test1234");
$url = $builder->createUrl("https://my-demo-site.com/files/133467012/avatar icon.png?some=chill&params=1");

$this->assertEquals("https://demos.imgix.net/https%3A%2F%2Fmy-demo-site.com%2Ffiles%2F133467012%2Favatar+icon.png%3Fsome%3Dchill%26params%3D1?&s=259b9ca6206721752ad7a3ce50f08dd2", $url);
}
}
?>
8 changes: 4 additions & 4 deletions tests/Imgix/Tests/UrlHelperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,26 @@ public function testHelperBuildSignedURLWithHashMapParams() {
$params = array("w" => 500);
$uh = new URLHelper("securejackangers.imgix.net", "chester.png", "http", "Q61NvXIy", $params);

$this->assertEquals($uh->getURL(), "http://securejackangers.imgix.net/chester.png?w=500&s=0ddf97bf1a266a1da6c30c6ce327f917");
$this->assertEquals("http://securejackangers.imgix.net/chester.png?w=500&s=0ddf97bf1a266a1da6c30c6ce327f917", $uh->getURL());
}

public function testHelperBuildSignedURLWithHashMapAndNoParams() {
$params = array();
$uh = new URLHelper("securejackangers.imgix.net", "chester.png", "http", "Q61NvXIy", $params);

$this->assertEquals($uh->getURL(), "http://securejackangers.imgix.net/chester.png?s=cff7bdfd1b32d82e6b516f7fd3b4f1f4");
$this->assertEquals("http://securejackangers.imgix.net/chester.png?&s=711dfe95b041008a3c6f460a40052282", $uh->getURL());
}

public function testHelperBuildSignedURLWithHashSetterParams() {
$uh = new URLHelper("securejackangers.imgix.net", "chester.png", "http", "Q61NvXIy");
$uh->setParameter("w", 500);
$this->assertEquals($uh->getURL(), "http://securejackangers.imgix.net/chester.png?w=500&s=0ddf97bf1a266a1da6c30c6ce327f917");
$this->assertEquals("http://securejackangers.imgix.net/chester.png?w=500&s=0ddf97bf1a266a1da6c30c6ce327f917", $uh->getURL());
}

public function testHelperBuildSignedURLWithHashSetterParamsHttps() {
$uh = new URLHelper("securejackangers.imgix.net", "chester.png", "https", "Q61NvXIy");
$uh->setParameter("w", 500);
$this->assertEquals($uh->getURL(), "https://securejackangers.imgix.net/chester.png?w=500&s=0ddf97bf1a266a1da6c30c6ce327f917");
$this->assertEquals("https://securejackangers.imgix.net/chester.png?w=500&s=0ddf97bf1a266a1da6c30c6ce327f917", $uh->getURL());
}
}

Expand Down

0 comments on commit f021569

Please sign in to comment.