示例#1
0
 /**
  * @param \swoole_server $serv
  * @param $fd
  * @param $from_id
  * @param $data
  */
 function onReceive($serv, $fd, $from_id, $data)
 {
     $parser = new \HttpParser();
     if (empty($this->buffers[$fd])) {
         $this->clearBuffer($fd);
     }
     $this->buffers[$fd] .= $data;
     $buffer =& $this->buffers[$fd];
     $nparsed =& $this->nparsed[$fd];
     $nparsed = $parser->execute($buffer, $nparsed);
     if ($parser->hasError()) {
         $serv->close($fd, $from_id);
     } else {
         if ($parser->isFinished()) {
             $this->clearBuffer($fd);
             $_SERVER = $parser->getEnvironment();
             $_GET = array();
             if (!empty($_SERVER['QUERY_STRING'])) {
                 parse_str($_SERVER['QUERY_STRING'], $_GET);
             }
             if (!empty($_SERVER['REQUEST_BODY'])) {
                 parse_str($_SERVER['REQUEST_BODY'], $_POST);
             }
             if (!empty($_SERVER['HTTP_COOKIE'])) {
                 $_COOKIE = self::parseCookie($_SERVER['HTTP_COOKIE']);
             }
             $this->currentFd = $fd;
             call_user_func($this->_onRequest, $this);
         }
     }
 }
 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']);
             }
         });
     }
 }
示例#3
0
文件: Server.php 项目: dhotson/kelpie
 /**
  * Start serving requests to the application
  * @param callable
  */
 public function start($app)
 {
     if (!($socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP))) {
         throw new Exception(socket_strerror(socket_last_error()));
     }
     if (!socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1)) {
         throw new Exception(socket_strerror(socket_last_error()));
     }
     if (!socket_bind($socket, $this->_host, $this->_port)) {
         throw new Exception(socket_strerror(socket_last_error()));
     }
     if (!socket_listen($socket)) {
         throw new Exception(socket_strerror(socket_last_error()));
     }
     while ($client = socket_accept($socket)) {
         $data = '';
         $nparsed = 0;
         $h = new \HttpParser();
         while ($d = socket_read($client, 1024 * 1024 * 1024)) {
             $data .= $d;
             $nparsed = $h->execute($data, $nparsed);
             if ($h->isFinished()) {
                 break;
             }
             if ($h->hasError()) {
                 socket_close($client);
                 continue 2;
                 // Skip to accept next connection..
             }
         }
         $env = $h->getEnvironment();
         global $argv;
         $env['SERVER_NAME'] = $this->_host;
         $env['SERVER_PORT'] = $this->_port;
         $env['SCRIPT_FILENAME'] = $argv[0];
         socket_getpeername($client, $address);
         $env['REMOTE_ADDR'] = $address;
         list($status, $headers, $body) = call_user_func($app, $env);
         $response = new Response();
         $response->setStatus($status);
         $response->setHeaders($headers);
         $response->setBody($body);
         foreach ($response as $chunk) {
             $len = strlen($chunk);
             $offset = 0;
             while ($offset < $len) {
                 if (false === ($n = @socket_write($client, substr($chunk, $offset), $len - $offset))) {
                     break 2;
                 }
                 $offset += $n;
             }
         }
         socket_close($client);
     }
 }
示例#4
0
 private function merge(MapInterface $http, MapInterface $html) : MapInterface
 {
     if (!$http->contains(HttpParser::key())) {
         return $html;
     }
     if (!$html->contains(HtmlParser::key())) {
         return $http;
     }
     return $http->put(self::key(), $http->get(HttpParser::key())->merge($html->get(HtmlParser::key())));
 }
示例#5
0
 private function _child($socket, $app)
 {
     while ($client = socket_accept($socket)) {
         $data = '';
         $nparsed = 0;
         $h = new HttpParser();
         while ($d = socket_read($client, 1024 * 1024)) {
             $data .= $d;
             $nparsed = $h->execute($data, $nparsed);
             if ($h->isFinished()) {
                 break;
             }
             if ($h->hasError()) {
                 socket_close($client);
                 continue 2;
                 //
             }
         }
         $env = $h->getEnvironment();
         $result = $app->call($env);
         $response = new Kelpie_Server_Response();
         $response->setStatus($result[0]);
         $response->setHeaders($result[1]);
         $response->setBody($result[2]);
         foreach ($response as $chunk) {
             $len = strlen($chunk);
             $offset = 0;
             while ($offset < $len) {
                 if (false === ($n = @socket_write($client, substr($chunk, $offset), $len - $offset))) {
                     break 2;
                 }
                 $offset += $n;
             }
         }
         socket_close($client);
     }
 }
示例#6
0
 public function readRequest($stream)
 {
     $this->stream = $stream;
     $_headers_str = stream_get_line($this->stream, 0, "\r\n\r\n");
     if (extension_loaded('httpparser')) {
         $parser = new \HttpParser();
         $parser->execute($_headers_str, 0);
         $this->headers = $parser->getEnvironment();
         unset($parser);
     } else {
         // native parsing
         // TODO: implement support for multiline headers (see http-spec for details)
         $_headers = explode("\r\n", $_headers_str);
         // getting headers
         list($http_method, $url, $http_version) = sscanf(array_shift($_headers), "%s %s %s");
         $this->headers = array();
         foreach ($_headers as $element) {
             $divider = strpos($element, ': ');
             $name = 'HTTP_' . str_replace('-', '_', strtoupper(substr($element, 0, $divider)));
             $value = substr($element, $divider + 2);
             $this->headers[$name] = $value;
         }
         unset($_headers, $first);
         $this->headers['HTTP_VERSION'] = $http_version;
         $this->headers['REQUEST_METHOD'] = $http_method;
         $this->headers['REQUEST_URI'] = $url;
         if (false === ($pos = strpos($url, '?'))) {
             $this->headers['PATH_INFO'] = $url;
             $this->headers['QUERY_STRING'] = '';
         } else {
             $this->headers['PATH_INFO'] = substr($url, 0, $pos);
             $this->headers['QUERY_STRING'] = strval(substr($url, $pos + 1));
         }
     }
     $this->headers['SERVER_SOFTWARE'] = 'appserver-in-php';
     $this->headers['GATEWAY_INTERFACE'] = 'CGI/1.1';
     $this->headers['SCRIPT_NAME'] = '';
     if (isset($this->headers['HTTP_HOST'])) {
         if (false === ($pos = strpos($this->headers['HTTP_HOST'], ':'))) {
             $host = $this->headers['HTTP_HOST'];
             $port = 80;
         } else {
             $host = substr($this->headers['HTTP_HOST'], 0, $pos);
             $port = substr($this->headers['HTTP_HOST'], $pos + 1);
         }
         $this->headers['SERVER_NAME'] = $host;
         $this->headers['SERVER_PORT'] = strval($port);
     } else {
         $this->headers['SERVER_NAME'] = 'localhost';
         $this->headers['SERVER_PORT'] = '80';
     }
     if (isset($this->headers['HTTP_CONTENT_TYPE'])) {
         $this->headers['CONTENT_TYPE'] = $this->headers['HTTP_CONTENT_TYPE'];
         unset($this->headers['HTTP_CONTENT_TYPE']);
     }
     if (isset($this->headers['HTTP_CONTENT_LENGTH'])) {
         $this->headers['CONTENT_LENGTH'] = $this->headers['HTTP_CONTENT_LENGTH'];
         unset($this->headers['HTTP_CONTENT_LENGTH']);
     } else {
         $this->headers['CONTENT_LENGTH'] = 0;
     }
     ksort($this->headers);
 }