<commit_before><?php
/**
 * Http/Client.php
 *
 * @author Jérémy 'Jejem' Desvages <<EMAIL>>
 * @copyright Jérémy 'Jejem' Desvages
 * @license The MIT License (MIT)
**/

namespace Phyrexia\Http;

class Client {
	private $request;
	private $response;
	private $options = array();

	private $errno;
	private $error;

	private $followRedirects = true;
	private $maxTries = 3;

	public function __construct($url = NULL, $method = 'GET', array $options = array()) {
		if (! is_null($url)) {
			$uri = new Uri($url);
			if ($uri->getScheme() == '')
				$url = 'http://'.$url;

			$this->request = new Request($method, $url);
			$this->request = $this->request->withHeader('Expect', '');
			$this->request = $this->request->withHeader('Connection', 'close');
			$this->request = $this->request->withHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');

			if (array_key_exists(CURLOPT_HTTPHEADER, $options) && is_array($options[CURLOPT_HTTPHEADER])) {
				foreach ($options[CURLOPT_HTTPHEADER] as $header) {
					$buf = explode(':', $header, 2);
					$this->request = $this->request->withHeader($buf[0], ltrim($buf[1]));
				}
			}
		}

		$this->options = $options;
	}

	public function getRequest() {
		return $this->request;
	}

	public function setRequest(\Psr\Http\Message\RequestInterface $request) {
		$this->request = $request;

		return $this;
	}

	public function getResponse() {
		return $this->response;
	}

	public function setResponse(\Psr\Http\Message\ResponseInterface $response) {
		$this->response = $response;

		return $this;
	}

	public function getErrno() {
		return $this->errno;
	}

	public function getError() {
		return $this->error;
	}

	public function setMethod($method) {
		$this->request = $this->request->withMethod($method);

		return $this;
	}

	public function setUri($uri) {
		$this->request = $this->request->withUri($uri);

		return $this;
	}

	public function setUrl($url) {
		return $this->setUri($url);
	}

	public function getFollowRedirects() {
		return $this->followRedirects;
	}

	public function setFollowRedirects($followRedirects) {
		$this->followRedirects = (bool)$followRedirects;

		return $this;
	}

	public function getMaxTries() {
		return $this->maxTries;
	}

	public function setMaxTries($maxTries) {
		$this->maxTries = (int)$maxTries;

		return $this;
	}

	public function send($request = NULL) {
		if (! is_null($request) && $request instanceof \Psr\Http\Message\RequestInterface)
			$this->request = $request;

		$ch = curl_init();

		curl_setopt($ch, CURLOPT_ENCODING, '');

		curl_setopt_array($ch, $this->options);

		curl_setopt($ch, CURLOPT_URL, (string)$this->request->getUri());

		$headers = array();
		foreach ($this->request->getHeaders() as $k => $v)
			$headers[] = $k.': '.$v[0];
		curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

		if ($this->request->getUri()->getUserInfo() != '')
			curl_setopt($ch, CURLOPT_USERPWD, $this->request->getUri()->getUserInfo());

		switch ($this->request->getMethod()) {
			case 'HEAD':
				curl_setopt($ch, CURLOPT_NOBODY, 1);
				break;
			case 'GET':
			default:
				curl_setopt($ch, CURLOPT_HTTPGET, 1);
				break;
			case 'POST':
				curl_setopt($ch, CURLOPT_POST, 1);
				if (array_key_exists(CURLOPT_POSTFIELDS, $this->options))
					curl_setopt($ch, CURLOPT_POSTFIELDS, $this->options[CURLOPT_POSTFIELDS]);
				if (! array_key_exists(CURLOPT_POSTFIELDS, $this->options) && (string)$this->request->getBody() != '')
					curl_setopt($ch, CURLOPT_POSTFIELDS, (string)$this->request->getBody());
				break;
		}

		curl_setopt($ch, CURLOPT_HEADER, 1);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

		$ret = curl_exec($ch);
		$this->parseOutput($ch, $ret);

		$i = 1;
		while ((curl_errno($ch) == CURLE_COULDNT_CONNECT || curl_errno($ch) == CURLE_RECV_ERROR || curl_errno($ch) == CURLE_OPERATION_TIMEOUTED || curl_errno($ch) == CURLE_GOT_NOTHING) && $i < $this->maxTries) {
			usleep(rand(1000000, 3000000));
			$ret = curl_exec($ch);
			$this->parseOutput($ch, $ret);
			$i++;
		}

		$this->errno = curl_errno($ch);
		$this->error = curl_error($ch);

		if (! is_null($this->response) && substr($this->response->getStatusCode(), 0, 1) == 3 && $this->followRedirects) {
			$this->setUri(new Uri(curl_getinfo($ch, CURLINFO_REDIRECT_URL)));
			return $this->send();
		}

		curl_close($ch);<commit_msg>Adding cURL connect and request timeout support<commit_after><?php
/**
 * Http/Client.php
 *
 * @author Jérémy '<NAME> <<EMAIL>>
 * @copyright Jérémy 'Jejem' Desvages
 * @license The MIT License (MIT)
**/

namespace Phyrexia\Http;

class Client {
	private $request;
	private $response;
	private $options = array();

	private $errno;
	private $error;

	private $followRedirects = true;
	private $maxTries = 3;
	private $connectTimeout = 5;
	private $timeout = 5;

	public function __construct($url = NULL, $method = 'GET', array $options = array()) {
		if (! is_null($url)) {
			$uri = new Uri($url);
			if ($uri->getScheme() == '')
				$url = 'http://'.$url;

			$this->request = new Request($method, $url);
			$this->request = $this->request->withHeader('Expect', '');
			$this->request = $this->request->withHeader('Connection', 'close');
			$this->request = $this->request->withHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');

			if (array_key_exists(CURLOPT_HTTPHEADER, $options) && is_array($options[CURLOPT_HTTPHEADER])) {
				foreach ($options[CURLOPT_HTTPHEADER] as $header) {
					$buf = explode(':', $header, 2);
					$this->request = $this->request->withHeader($buf[0], ltrim($buf[1]));
				}
			}
		}

		$this->options = $options;
	}

	public function getRequest() {
		return $this->request;
	}

	public function setRequest(\Psr\Http\Message\RequestInterface $request) {
		$this->request = $request;

		return $this;
	}

	public function getResponse() {
		return $this->response;
	}

	public function setResponse(\Psr\Http\Message\ResponseInterface $response) {
		$this->response = $response;

		return $this;
	}

	public function getErrno() {
		return $this->errno;
	}

	public function getError() {
		return $this->error;
	}

	public function setMethod($method) {
		$this->request = $this->request->withMethod($method);

		return $this;
	}

	public function setUri($uri) {
		$this->request = $this->request->withUri($uri);

		return $this;
	}

	public function setUrl($url) {
		return $this->setUri($url);
	}

	public function getFollowRedirects() {
		return $this->followRedirects;
	}

	public function setFollowRedirects($followRedirects) {
		$this->followRedirects = (bool)$followRedirects;

		return $this;
	}

	public function getMaxTries() {
		return $this->maxTries;
	}

	public function setMaxTries($maxTries) {
		$this->maxTries = (int)$maxTries;

		return $this;
	}

	public function getConnectTimeout() {
		return $this->connectTimeout;
	}

	public function setConnectTimeout($connectTimeout) {
		$this->connectTimeout = (int)$connectTimeout;

		return $this;
	}

	public function getTimeout() {
		return $this->timeout;
	}

	public function setTimeout($timeout) {
		$this->timeout = (int)$timeout;

		return $this;
	}

	public function send($request = NULL) {
		if (! is_null($request) && $request instanceof \Psr\Http\Message\RequestInterface)
			$this->request = $request;

		$ch = curl_init();

		curl_setopt($ch, CURLOPT_ENCODING, '');

		curl_setopt_array($ch, $this->options);

		curl_setopt($ch, CURLOPT_URL, (string)$this->request->getUri());

		$headers = array();
		foreach ($this->request->getHeaders() as $k => $v)
			$headers[] = $k.': '.$v[0];
		curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

		if ($this->request->getUri()->getUserInfo() != '')
			curl_setopt($ch, CURLOPT_USERPWD, $this->request->getUri()->getUserInfo());

		switch ($this->request->getMethod()) {
			case 'HEAD':
				curl_setopt($ch, CURLOPT_NOBODY, 1);
				break;
			case 'GET':
			default:
				curl_setopt($ch, CURLOPT_HTTPGET, 1);
				break;
			case 'POST':
				curl_setopt($ch, CURLOPT_POST, 1);
				if (array_key_exists(CURLOPT_POSTFIELDS, $this->options))
					curl_setopt($ch, CURLOPT_POSTFIELDS, $this->options[CURLOPT_POSTFIELDS]);
				if (! array_key_exists(CURLOPT_POSTFIELDS, $this->options) && (string)$this->request->getBody() != '')
					curl_setopt($ch, CURLOPT_POSTFIELDS, (string)$this->request->getBody());
				break;
		}

		curl_setopt($ch, CURLOPT_HEADER, 1);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

		curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->connectTimeout);
		curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout);

		$ret = curl_exec($ch);
		$this->parseOutput($ch, $ret);

		$i = 1;
		while ((curl_errno($ch) == CURLE_COULDNT_CONNECT || curl_errno($ch) == CURLE_RECV_ERROR || curl_errno($ch) == CURLE_OPERATION_TIMEOUTED || curl_errno($ch) == CURLE_GOT_NOTHING) && $i < $this->maxTries) {
			usleep(rand(1000000, 3000000));
			$ret = curl_exec($ch);
			$this->parseOutput($ch, $ret);
			$i++;
		}

		$this->errno = curl_errno($ch);
		$this->error = curl_error($ch);

		if (! is_null($this->response) && substr($this->response->getStatusCode(), 0, 1) == 3 && $this->followRedirects) {
			$this->setUri(new Uri(curl_getinfo($ch, CURLINFO_REDIRECT_URL)));
			return $this->send();
		}

		curl_close($ch);
{'fraction_non_alphanumeric': 0.1800891207477448, 'fraction_numerical': 0.006521030322791001, 'mean_word_length': 4.56012084592145, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 144, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2795432', 'n_tokens_mistral': 3711, 'n_tokens_neox': 3211, 'n_words': 606}