UriFactory.php 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. <?php
  2. namespace OAuth\Common\Http\Uri;
  3. use RuntimeException;
  4. /**
  5. * Factory class for uniform resource indicators
  6. */
  7. class UriFactory implements UriFactoryInterface
  8. {
  9. /**
  10. * Factory method to build a URI from a super-global $_SERVER array.
  11. *
  12. * @param array $_server
  13. *
  14. * @return UriInterface
  15. */
  16. public function createFromSuperGlobalArray(array $_server)
  17. {
  18. if ($uri = $this->attemptProxyStyleParse($_server)) {
  19. return $uri;
  20. }
  21. $scheme = $this->detectScheme($_server);
  22. $host = $this->detectHost($_server);
  23. $port = $this->detectPort($_server);
  24. $path = $this->detectPath($_server);
  25. $query = $this->detectQuery($_server);
  26. return $this->createFromParts($scheme, '', $host, $port, $path, $query);
  27. }
  28. /**
  29. * @param string $absoluteUri
  30. *
  31. * @return UriInterface
  32. */
  33. public function createFromAbsolute($absoluteUri)
  34. {
  35. return new Uri($absoluteUri);
  36. }
  37. /**
  38. * Factory method to build a URI from parts
  39. *
  40. * @param string $scheme
  41. * @param string $userInfo
  42. * @param string $host
  43. * @param string $port
  44. * @param string $path
  45. * @param string $query
  46. * @param string $fragment
  47. *
  48. * @return UriInterface
  49. */
  50. public function createFromParts($scheme, $userInfo, $host, $port, $path = '', $query = '', $fragment = '')
  51. {
  52. $uri = new Uri();
  53. $uri->setScheme($scheme);
  54. $uri->setUserInfo($userInfo);
  55. $uri->setHost($host);
  56. $uri->setPort($port);
  57. $uri->setPath($path);
  58. $uri->setQuery($query);
  59. $uri->setFragment($fragment);
  60. return $uri;
  61. }
  62. /**
  63. * @param array $_server
  64. *
  65. * @return UriInterface|null
  66. */
  67. private function attemptProxyStyleParse($_server)
  68. {
  69. // If the raw HTTP request message arrives with a proxy-style absolute URI in the
  70. // initial request line, the absolute URI is stored in $_SERVER['REQUEST_URI'] and
  71. // we only need to parse that.
  72. if (isset($_server['REQUEST_URI']) && parse_url($_server['REQUEST_URI'], PHP_URL_SCHEME)) {
  73. return new Uri($_server['REQUEST_URI']);
  74. }
  75. return null;
  76. }
  77. /**
  78. * @param array $_server
  79. *
  80. * @return string
  81. *
  82. * @throws RuntimeException
  83. */
  84. private function detectPath($_server)
  85. {
  86. if (isset($_server['REQUEST_URI'])) {
  87. $uri = $_server['REQUEST_URI'];
  88. } elseif (isset($_server['REDIRECT_URL'])) {
  89. $uri = $_server['REDIRECT_URL'];
  90. } else {
  91. throw new RuntimeException('Could not detect URI path from superglobal');
  92. }
  93. $queryStr = strpos($uri, '?');
  94. if ($queryStr !== false) {
  95. $uri = substr($uri, 0, $queryStr);
  96. }
  97. return $uri;
  98. }
  99. /**
  100. * @param array $_server
  101. *
  102. * @return string
  103. */
  104. private function detectHost(array $_server)
  105. {
  106. $host = isset($_server['HTTP_HOST']) ? $_server['HTTP_HOST'] : '';
  107. if (strstr($host, ':')) {
  108. $host = parse_url($host, PHP_URL_HOST);
  109. }
  110. return $host;
  111. }
  112. /**
  113. * @param array $_server
  114. *
  115. * @return string
  116. */
  117. private function detectPort(array $_server)
  118. {
  119. return isset($_server['SERVER_PORT']) ? $_server['SERVER_PORT'] : 80;
  120. }
  121. /**
  122. * @param array $_server
  123. *
  124. * @return string
  125. */
  126. private function detectQuery(array $_server)
  127. {
  128. return isset($_server['QUERY_STRING']) ? $_server['QUERY_STRING'] : '';
  129. }
  130. /**
  131. * Determine URI scheme component from superglobal array
  132. *
  133. * When using ISAPI with IIS, the value will be "off" if the request was
  134. * not made through the HTTPS protocol. As a result, we filter the
  135. * value to a bool.
  136. *
  137. * @param array $_server A super-global $_SERVER array
  138. *
  139. * @return string Returns http or https depending on the URI scheme
  140. */
  141. private function detectScheme(array $_server)
  142. {
  143. if (isset($_server['HTTPS']) && filter_var($_server['HTTPS'], FILTER_VALIDATE_BOOLEAN)) {
  144. return 'https';
  145. } else {
  146. return 'http';
  147. }
  148. }
  149. }