content = null; $this->content_type = null; $this->method = 'GET'; $this->headers = array(); $this->url = $url; } /** * This function could be use send array in the fetch request. Be careful * because this function verify that method of the request is not GET or * HEAD, which can not contain body. Property method must be set before. * * @param array $content Content which must be send. * @return fetch Itself to chain load. */ public function send_array(array $content): object { $content = json_encode($content); $type = 'application/json'; $this->send_raw($content, $type); return $this; } /** * This function is similar to {@link fetch::send_array()}, but work on * raw string data. Also content type must be set. Be careful, because * it check that method of the request is not GET or HEAD, which can * not contain body content. * * @param string $content Content of the body to send. * @param string $type Type of the content, like "text/plain". * @return fetch Self to chan loading. */ public function send_raw(string $content, string $type): object { if ($this->method === 'GET' or $this->method === 'HEAD') { throw new TypeError('GET or HEAD request can not contain body.'); } $this->content = $content; $this->content_type = $type; return $this; } /** * That add new header to the request. Name of the header must be full * featured header name, like 'Cache-Control'. It also had been validated * and when name had been blacklisted, it raise RuntimeException. It also * raise RuntimeException when name has any white chars. Content had been * validating, and it could not have new lines. Name and content would be * trimed before processing. * * Blacklisted headers: * Content-Type, Content-Length * * @param string $name Name of the header. * @param string $content Content of the header. * @return fetch Self to chain processing. */ public function add_header(string $name, string $content): object { $name = trim($name); $content = trim($content); if (strpos($name, ' ') !== false) { throw new RuntimeException( 'Header "'.$name.'" contains white char.' ); } $check_content = strpos($content, ' ') !== false; $check_content = $check_content || strpos($content, "\r") !== false; $check_content = $check_content || strpos($content, "\n") !== false; if ($check_content) { throw new RuntimeException( 'Header content "'.$content.'" contains invalid white char.' ); } if ($name === 'Content-Type') { throw new RuntimeException('Content-Type header is automatic.'); } if ($name === 'Content-Lenght') { throw new RuntimeException('Content-Lenght header is automatic.'); } $header = $name.': '.$content; array_push($this->headers, $header); return $this; } /** * This function set method of the request. Be careful, because it check * that any content is not set, and when content is not null, but trying * to set GET or HEAD method, it throw TypeError. * * @param string $name Name of the method. * @return fetch Self to chain loading. */ public function set_method(string $name): object { if ($this->content === null) { $this->method = $name; return $this; } if ($name === 'GET' || $name === 'HEAD') { throw new TypeError('GET or HEAD request can not contain body.'); } $this->method = $name; return $this; } /** * That function make request to the server, from fetch config, which * had been config previously. It return response in parsed form, as * instance of response class. Be careful, it raise an RuntimeException * when server does not response correctly. * * @return response Response from the server. */ public function request(): response { $headers = $this->headers; $request = curl_init($this->url); curl_setopt($request, CURLOPT_RETURNTRANSFER, true); curl_setopt($request, CURLOPT_FAILONERROR, true); curl_setopt($request, CURLOPT_HEADER, true); curl_setopt($request,CURLOPT_CUSTOMREQUEST, $this->method); if ($this->content !== null) { array_push($headers, 'Content-Type: '.$this->content_type); curl_setopt($request, CURLOPT_POSTFIELDS, $this->content); } curl_setopt($request, CURLOPT_HTTPHEADER, $headers); $result = curl_exec($request); $error = curl_error($request); $error_number = curl_errno($request); curl_close($request); if ($result !== false and $error_number === 0) { return new response($result); } throw new RuntimeException( 'Can not fetch request. Error code ' .strval($error_number) .': "'.$error.'".' ); } }