| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284 |
- <?php
- /**
- * This file is part of workerman.
- *
- * Licensed under The MIT License
- * For full copyright and license information, please see the MIT-LICENSE.txt
- * Redistributions of files must retain the above copyright notice.
- *
- * @author walkor<walkor@workerman.net>
- * @copyright walkor<walkor@workerman.net>
- * @link http://www.workerman.net/
- * @license http://www.opensource.org/licenses/mit-license.php MIT License
- */
- namespace Workerman\Protocols;
- use Workerman\Connection\TcpConnection;
- use Workerman\Protocols\Http\Request;
- use Workerman\Protocols\Http\Response;
- use Workerman\Protocols\Websocket;
- use Workerman\Worker;
- /**
- * Class Http.
- * @package Workerman\Protocols
- */
- class Http
- {
- /**
- * Request class name.
- *
- * @var string
- */
- protected static $_requestClass = 'Workerman\Protocols\Http\Request';
- /**
- * Session name.
- *
- * @var string
- */
- protected static $_sessionName = 'PHPSID';
- /**
- * Upload tmp dir.
- *
- * @var string
- */
- protected static $_uploadTmpDir = '';
- /**
- * Cache.
- *
- * @var array
- */
- protected static $_cache = array();
- /**
- * Open cache.
- *
- * @var bool.
- */
- public static $_enableCache = true;
- /**
- * Get or set session name.
- *
- * @param null $name
- * @return string
- */
- public static function sessionName($name = null)
- {
- if ($name !== null && $name !== '') {
- static::$_sessionName = (string)$name;
- }
- return static::$_sessionName;
- }
- /**
- * Get or set the request class name.
- *
- * @param null $class_name
- * @return string
- */
- public static function requestClass($class_name = null)
- {
- if ($class_name) {
- static::$_requestClass = $class_name;
- }
- return static::$_requestClass;
- }
- /**
- * Enable or disable Cache.
- *
- * @param $value
- */
- public static function enableCache($value)
- {
- static::$_enableCache = (bool)$value;
- }
- /**
- * Check the integrity of the package.
- *
- * @param string $recv_buffer
- * @param TcpConnection $connection
- * @return int
- */
- public static function input($recv_buffer, TcpConnection $connection)
- {
- $crlf_pos = \strpos($recv_buffer, "\r\n\r\n");
- if (false === $crlf_pos) {
- // Judge whether the package length exceeds the limit.
- if ($recv_len = \strlen($recv_buffer) >= 16384) {
- $connection->send("HTTP/1.1 413 Request Entity Too Large\r\n\r\n");
- $connection->consumeRecvBuffer($recv_len);
- return 0;
- }
- return 0;
- }
- $head_len = $crlf_pos + 4;
- $method = \strstr($recv_buffer, ' ', true);
- if ($method === 'GET' || $method === 'OPTIONS' || $method === 'HEAD') {
- return $head_len;
- } else if ($method !== 'POST' && $method !== 'PUT' && $method !== 'DELETE') {
- $connection->send("HTTP/1.1 400 Bad Request\r\n\r\n", true);
- $connection->consumeRecvBuffer(\strlen($recv_buffer));
- return 0;
- }
- $header = \substr($recv_buffer, 0, $crlf_pos);
- if ($pos = \strpos($header, "\r\nContent-Length: ")) {
- return $head_len + (int)\substr($header, $pos + 18, 10);
- } else if (\preg_match("/\r\ncontent-length: ?(\d+)/i", $header, $match)) {
- return $head_len + $match[1];
- }
- return $method === 'DELETE' ? $head_len : 0;
- }
- /**
- * Http decode.
- *
- * @param string $recv_buffer
- * @param TcpConnection $connection
- * @return \Workerman\Protocols\Http\Request
- */
- public static function decode($recv_buffer, TcpConnection $connection)
- {
- $cacheable = static::$_enableCache && !isset($recv_buffer[512]);
- if (true === $cacheable && isset(static::$_cache[$recv_buffer])) {
- $request = static::$_cache[$recv_buffer];
- $request->connection = $connection;
- $connection->__request = $request;
- $request->properties = array();
- return $request;
- }
- $request = new static::$_requestClass($recv_buffer);
- $request->connection = $connection;
- $connection->__request = $request;
- if (true === $cacheable) {
- static::$_cache[$recv_buffer] = $request;
- if (\count(static::$_cache) > 512) {
- unset(static::$_cache[key(static::$_cache)]);
- }
- }
- return $request;
- }
- /**
- * Http encode.
- *
- * @param string|Response $response
- * @param TcpConnection $connection
- * @return string
- */
- public static function encode($response, TcpConnection $connection)
- {
- if (isset($connection->__request)) {
- $connection->__request->session = null;
- $connection->__request->connection = null;
- $connection->__request = null;
- }
- if (\is_scalar($response) || null === $response) {
- $ext_header = '';
- if (isset($connection->__header)) {
- foreach ($connection->__header as $name => $value) {
- if (\is_array($value)) {
- foreach ($value as $item) {
- $ext_header = "$name: $item\r\n";
- }
- } else {
- $ext_header = "$name: $value\r\n";
- }
- }
- unset($connection->__header);
- }
- $body_len = \strlen($response);
- return "HTTP/1.1 200 OK\r\nServer: workerman\r\n{$ext_header}Connection: keep-alive\r\nContent-Type: text/html;charset=utf-8\r\nContent-Length: $body_len\r\n\r\n$response";
- }
- if (isset($connection->__header)) {
- $response->withHeaders($connection->__header);
- unset($connection->__header);
- }
- if (isset($response->file)) {
- $file = $response->file;
- $body_len = (int)\filesize($file);
- $response->header('Content-Length', $body_len);
- if ($body_len < 1024 * 1024) {
- $connection->send((string)$response . file_get_contents($file, false, null, -1, $body_len), true);
- return '';
- }
- $handler = \fopen($file, 'r');
- if (false === $handler) {
- $connection->close(new Response(403, null, '403 Forbidden'));
- return '';
- }
- $connection->send((string)$response, true);
- static::sendStream($connection, $handler);
- return '';
- }
- return (string)$response;
- }
- /**
- * Send remainder of a stream to client.
- *
- * @param TcpConnection $connection
- * @param $handler
- */
- protected static function sendStream(TcpConnection $connection, $handler)
- {
- $connection->bufferFull = false;
- // Read file content from disk piece by piece and send to client.
- $do_write = function () use ($connection, $handler) {
- // Send buffer not full.
- while ($connection->bufferFull === false) {
- // Read from disk.
- $buffer = \fread($handler, 8192);
- // Read eof.
- if ($buffer === '' || $buffer === false) {
- fclose($handler);
- $connection->onBufferDrain = null;
- return;
- }
- $connection->send($buffer, true);
- }
- };
- // Send buffer full.
- $connection->onBufferFull = function ($connection) {
- $connection->bufferFull = true;
- };
- // Send buffer drain.
- $connection->onBufferDrain = function ($connection) use ($do_write) {
- $connection->bufferFull = false;
- $do_write();
- };
- $do_write();
- }
- /**
- * Set or get uploadTmpDir.
- *
- * @return bool|string
- */
- public static function uploadTmpDir($dir = null)
- {
- if (null !== $dir) {
- static::$_uploadTmpDir = $dir;
- }
- if (static::$_uploadTmpDir === '') {
- if ($upload_tmp_dir = \ini_get('upload_tmp_dir')) {
- static::$_uploadTmpDir = $upload_tmp_dir;
- } else if ($upload_tmp_dir = \sys_get_temp_dir()) {
- static::$_uploadTmpDir = $upload_tmp_dir;
- }
- }
- static::$_uploadTmpDir;
- }
- }
|