public function run(Promise &$promise) { $urlInfo = parse_url($this->url); $timeout = $this->timeout; if (!isset($urlInfo['port'])) { $urlInfo['port'] = 80; } $cli = new \swoole_http_client($urlInfo['host'], $urlInfo['port']); $cli->set(array('timeout' => $timeout, 'keepalive' => 0)); $cli->on("error", function ($cli) use(&$promise) { Timer::del($cli->sock); $promise->accept(['http_data' => null, 'http_error' => 'Connect error']); }); $cli->on("close", function ($cli) use(&$promise) { }); $cli->execute($this->url, function ($cli) use(&$promise) { Timer::del($cli->sock); $cli->isDone = true; $promise->accept(['http_data' => $cli->body]); }); $cli->isConnected = false; if (!$cli->errCode) { Timer::add($cli->sock, $this->timeout, function () use($cli, &$promise) { @$cli->close(); if ($cli->isConnected) { $promise->accept(['http_data' => null, 'http_error' => 'Http client read timeout']); } else { $promise->accept(['http_data' => null, 'http_error' => 'Http client connect timeout']); } }); } }
public function run(Promise &$promise) { $cli = new \swoole_client(SWOOLE_TCP, SWOOLE_SOCK_ASYNC); $urlInfo = parse_url($this->url); $timeout = $this->timeout; if (!isset($urlInfo['port'])) { $urlInfo['port'] = 80; } $httpParser = new \HttpParser(); $cli->on("connect", function ($cli) use($urlInfo, &$timeout, &$promise) { $cli->isConnected = true; $host = $urlInfo['host']; if ($urlInfo['port']) { $host .= ':' . $urlInfo['port']; } $req = array(); $req[] = "GET {$this->url} HTTP/1.1\r\n"; $req[] = "User-Agent: PHP swAsync\r\n"; $req[] = "Host:{$host}\r\n"; $req[] = "Connection:close\r\n"; $req[] = "\r\n"; $req = implode('', $req); $cli->send($req); }); $cli->on("receive", function ($cli, $data = "") use(&$httpParser, &$promise) { $ret = $httpParser->execute($data); if ($ret !== false) { Timer::del($cli->sock); $cli->isDone = true; if ($cli->isConnected()) { $cli->close(); } $promise->accept(['http_data' => $ret]); } }); $cli->on("error", function ($cli) use(&$promise) { Timer::del($cli->sock); $promise->accept(['http_data' => null, 'http_error' => 'Connect error']); }); $cli->on("close", function ($cli) use(&$promise) { }); if ($this->proxy) { $cli->connect($this->proxy['host'], $this->proxy['port'], 0.05); } else { $cli->connect($urlInfo['host'], $urlInfo['port'], 0.05); } $cli->isConnected = false; if (!$cli->errCode) { Timer::add($cli->sock, $this->timeout, function () use($cli, &$promise) { @$cli->close(); if ($cli->isConnected) { $promise->accept(['http_data' => null, 'http_error' => 'Http client read timeout']); } else { $promise->accept(['http_data' => null, 'http_error' => 'Http client connect timeout']); } }); } }
public function send(callable $callback) { $client = new \swoole_client(SWOOLE_SOCK_UDP, SWOOLE_SOCK_ASYNC); $client->on("connect", function ($cli) { $cli->send($this->data); }); $client->on('close', function ($cli) { }); $client->on('error', function ($cli) use($callback) { $cli->close(); call_user_func_array($callback, array('r' => 1, 'key' => $this->key, 'calltime' => $this->calltime, 'error_msg' => 'conncet error')); }); $client->on("receive", function ($cli, $data) use($callback) { //临时方案 Timer::del($this->key); $cli->close(); $this->calltime = microtime(true) - $this->calltime; //swoole_timer_clear($this ->timer); call_user_func_array($callback, array('r' => 0, 'key' => $this->key, 'calltime' => $this->calltime, 'data' => $data)); }); if ($client->connect($this->ip, $this->port, $this->timeout)) { $this->calltime = microtime(true); if (floatval($this->timeout) > 0) { //临时方案 Timer::add($this->key, $this->timeout, $client, $callback, array('r' => 2, 'key' => $this->key, 'calltime' => $this->calltime, 'error_msg' => 'timeout')); /* $this ->timer = swoole_timer_after(floatval($this ->timeout) * 1000, function() use($client,$callback){ $client ->close(); \SysLog::error(__METHOD__." TIMEOUT ", __CLASS__); $this ->calltime = microtime(true) - $this ->calltime; call_user_func_array($callback, array('r' => 2 ,'key' => '', 'calltime' => $this ->calltime, 'error_msg' => 'timeout')); }); */ } } }
/** * [packRsp 组包合包,函数回调] * @param [type] $cli [description] * @param [type] $data [description] * @return [type] [description] */ private function packRsp($cli, $data) { /* 1.设置标记位,开始时,解析头部信息 2.合并boty,两种头部协议 3.特殊处理 重定向+超时 */ $this->buffer .= $data; //cookie 保持 if ($this->persistCookies && isset($this->rspHeaders['set-cookie'])) { //TODO support } if ($this->trunk_length > 0 and strlen($this->buffer) < $this->trunk_length) { return; } if (empty($this->rspHeaders)) { $ret = $this->parseHeader($this->buffer); if ($ret === false) { return; } else { if ($this->handleRedirects && $this->rspHeaders['status'] >= 300 && $this->rspHeaders['status'] < 400) { //超出最大循环 if (++$this->redirectCount >= $this->maxRedirects) { $cli->close(); Timer::del($this->key); \SysLog::error(__METHOD__ . " redirectCount over limit ", __CLASS__); call_user_func_array($this->callback, array('r' => 1, 'key' => $this->key, 'calltime' => $this->calltime, 'data' => "redirectCount over limit")); return false; } $location = isset($this->rspHeaders['location']) ? $this->rspHeaders['location'] : ''; $location .= isset($this->rspHeaders['uri']) ? $this->rspHeaders['uri'] : ''; if (!empty($location)) { \SysLog::debug(__METHOD__ . " redirect location ", __CLASS__); //TODO 尝试client内部重定 $url = parse_url($location); $this->host = isset($url['host']) ? $url['host'] : $this->host; $this->body = ''; $this->buffer = ''; $this->rspHeaders = array(); $this->isFinish = false; $cli->close(); $http = $this->get($location); $http->send($this->callback); return; } else { $cli->close(); Timer::del($this->key); \SysLog::error(__METHOD__ . " redirect location error ", __CLASS__); call_user_func_array($this->callback, array('r' => 1, 'key' => $this->key, 'calltime' => $this->calltime, 'data' => "redirect location error ")); return false; } } //header + CRLF + body if (strlen($this->buffer) > 0) { $parsebody = $this->parseBody(); } } } else { $parsebody = $this->parseBody(); } if ($parsebody === true and $this->isFinish) { $compress_type = empty($this->rspHeaders['content-encoding']) ? '' : $this->rspHeaders['content-encoding']; $this->body = self::gz_decode($this->body, $compress_type); $data = array('head' => $this->rspHeaders, 'body' => $this->body); $cli->close(); $this->calltime = microtime(true) - $this->calltime; Timer::del($this->key); call_user_func_array($this->callback, array('r' => 0, 'key' => $this->key, 'calltime' => $this->calltime, 'data' => $data)); } }