response.php 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. <?php
  2. /**
  3. * This file contain class, which is responsible for prarsing raw content
  4. * from the server, which would be provided by fetch class.
  5. *
  6. * @package phpnotify
  7. * @author Cixo (Cixo Electronic)
  8. */
  9. namespace phpnotify;
  10. /**
  11. * This class contain response from the server. It is responsible for
  12. * parsing raw content from server. It would not being used by apps,
  13. * only {@link fetch} class would use it.
  14. */
  15. class response {
  16. /**
  17. * This contain result code of the response.
  18. * @var int
  19. */
  20. private int $code;
  21. /**
  22. * This contain parsed respone, when it had been returned in object
  23. * form, like JSON. When RAW content had been received, then that array
  24. * is empty.
  25. * @var array
  26. */
  27. private array $parsed;
  28. /**
  29. * This contain headers of the response. Key in that array is header name,
  30. * value for that is header content. Key must be lower case, but
  31. * {@link response::get_header()} also handle it, thanks to it end user
  32. * doesn't need to remember about it.
  33. * @var array
  34. */
  35. private array $headers;
  36. /**
  37. * This contain HTTP protocol version, in which response had been
  38. * received, for example "HTTP/2".
  39. * @var string
  40. */
  41. private string $version;
  42. /**
  43. * That store RAW content of the response body.
  44. * @var string
  45. */
  46. private string $content;
  47. /**
  48. * That create new response from all content received from string. It is
  49. * also responsible for starts of the parsing. That would be used only by
  50. * {@link fetch} on raw content received from server.
  51. *
  52. * @param string $content Content of the response from the server.
  53. */
  54. public function __construct(string $content) {
  55. $parts = explode("\r\n\r\n", $content);
  56. $head = array_shift($parts);
  57. $body = join("\r\n\r\n", $parts);
  58. $this->parse_head($head);
  59. $this->parse_body($body);
  60. }
  61. /**
  62. * That return status code of the response.
  63. *
  64. * @return int Number status of the response.
  65. */
  66. public function get_code(): int {
  67. return $this->code;
  68. }
  69. /**
  70. * That return HTTP protocol version of the response, like "HTTP/2"
  71. * for example.
  72. *
  73. * @return string HTTP protocol version, like "HTTP/2".
  74. */
  75. public function get_version(): string {
  76. return $this->version;
  77. }
  78. /**
  79. * That function return selected header of the response. When header did
  80. * not being received, then it return content given to fallback parameter.
  81. *
  82. * @param string $name Name of the header.
  83. * @param ?string $fallback Value to return when header not exists.
  84. * @return ?string Content of the header or fallback.
  85. */
  86. public function get_header(
  87. string $name,
  88. ?string $fallback = null
  89. ): ?string {
  90. $name = strtolower($name);
  91. if (array_key_exists($name, $this->headers)) {
  92. return $this->headers[$name];
  93. }
  94. return $fallback;
  95. }
  96. /**
  97. * That function return RAW content of the response body.
  98. *
  99. * @return string RAW content of the body.
  100. */
  101. public function receive_raw(): string {
  102. return $this->content;
  103. }
  104. /**
  105. * That return parsed content of the body, when content type of the
  106. * response had been json. When content had been received in other form,
  107. * then empty array had been returned.
  108. *
  109. * @return array Parsed content of the body of empty array.
  110. */
  111. public function receive_array(): array {
  112. return $this->parsed;
  113. }
  114. /**
  115. * That function parse body section of the response.
  116. *
  117. * @param string $body Body part of the response.
  118. */
  119. private function parse_body(string $body): void {
  120. $type = $this->get_header('Content-Type', 'text/plain');
  121. $is_json = strpos($type, 'json') !== false;
  122. $this->content = $body;
  123. $result = array();
  124. if ($is_json) {
  125. $result = json_decode($body, true);
  126. }
  127. /* Because json_decode could fail, when response had bad syntax. */
  128. if (gettype($result) !== 'array') {
  129. $result = array();
  130. }
  131. $this->parsed = $result;
  132. }
  133. /**
  134. * That function is responsible for parsing head of the response.
  135. *
  136. * @param string $head RAW head content of the response.
  137. */
  138. private function parse_head(string $head): void {
  139. $lines = explode("\r\n", $head);
  140. $first = array_shift($lines);
  141. $this->parse_first_line($first);
  142. $this->parse_headers($lines);
  143. }
  144. /**
  145. * That function parse first line, with status and HTTP version, of
  146. * the response.
  147. *
  148. * @param string $line First line of the response.
  149. */
  150. private function parse_first_line(string $line): void {
  151. $parts = explode(' ', $line);
  152. $this->version = array_shift($parts);
  153. $this->code = intval(array_shift($parts));
  154. }
  155. /**
  156. * That parse headers section of the response.
  157. *
  158. * @param array $lines Lines from headers section.
  159. */
  160. private function parse_headers(array $lines): void {
  161. $this->headers = array();
  162. foreach ($lines as $line) {
  163. $parts = explode(':', $line);
  164. if (count($parts) < 2) {
  165. continue;
  166. }
  167. $name = array_shift($parts);
  168. $name= strtolower($name);
  169. $content = ltrim(join(':', $parts));
  170. $this->headers[$name] = $content;
  171. }
  172. }
  173. }