浏览代码

Http cookie Session

walkor 12 年之前
父节点
当前提交
e71e6e20d4
共有 4 个文件被更改,包括 306 次插入222 次删除
  1. 282 211
      applications/Common/Protocols/Http.php
  2. 2 2
      conf/conf.d/Monitor.conf
  3. 3 3
      conf/workerman.conf
  4. 19 6
      workers/WorkerManAdmin.php

+ 282 - 211
applications/Common/Protocols/Http.php

@@ -1,245 +1,316 @@
 <?php 
 namespace  App\Common\Protocols;
-/**
- * http 协议解析 相关
- * @author walkor <worker-man@qq.com>
- * */
-class Http
+
+class HttpCache 
 {
-    
-    /**
-     * 构造函数
-     */
-    private  function __construct(){}
-    
-    /**
-     * http头
-     * @var array
-     */
+    public static $instance = null;
     public static $header = array();
+    public static $sessionPath = '';
+    public static $sessionName = '';
+    public $sessionStarted = false;
+    public $sessionFile = '';
+
+
+
+    public static function init()
+    {   
+       self::$sessionName = ini_get('session.name');
+       self::$sessionPath = session_save_path();
+       if(!self::$sessionPath)
+       {
+          self::$sessionPath = sys_get_temp_dir();
+       }
+    }
+
+
+}
+
+/**
+ * 设置http头
+ * @return bool
+ */
+function header($content)
+{
+    if(strpos($content, 'HTTP') === 0)
+    {
+        $key = 'Http-Code';
+    }
+    else
+    {
+        $key = strstr($content, ":", true);
+        if(empty($key))
+        {
+            return false;
+        }
+    }
+    HttpCache::$header[$key] = $content;
+    if('location' == strtolower($key))
+    {
+        header("HTTP/1.1 302 Moved Temporarily");
+    }
+    return true;
+}
+
+function http_deal_input($data)
+{
+    // 查找\r\n\r\n
+    $data_length = strlen($data);
     
-    /**
-     * cookie 
-     * @var array
-     */
-    protected static $cookie = array();
+    if(!strpos($data, "\r\n\r\n"))
+    {
+        return 1;
+    }
     
-    /**
-     * 判断数据包是否全部接收完成
-     * 
-     * @param string $data
-     * @return int 0:完成 1:还要接收数据
-     */
-    public static function input($data)
-    {
-        // 查找\r\n\r\n
-        $data_length = strlen($data);
-        
-        if(!strpos($data, "\r\n\r\n"))
+    // POST请求还要读包体
+    if(strpos($data, "POST"))
+    {
+        // 找Content-Length
+        $match = array();
+        if(preg_match("/\r\nContent-Length: ?(\d?)\r\n/", $data, $match))
         {
-            return 1;
+            $content_lenght = $match[1];
         }
-        
-        // POST请求还要读包体
-        if(strpos($data, "POST"))
+        else
         {
-            // 找Content-Length
-            $match = array();
-            if(preg_match("/\r\nContent-Length: ?(\d?)\r\n/", $data, $match))
-            {
-                $content_lenght = $match[1];
-            }
-            else
-            {
-                return 0;
-            }
-            
-            // 看包体长度是否符合
-            $tmp = explode("\r\n\r\n", $data);
-            if(strlen($tmp[1]) >= $content_lenght)
-            {
-                return 0;
-            }
-            return 1;
+            return 0;
         }
-        else 
+    
+        // 看包体长度是否符合
+        $tmp = explode("\r\n\r\n", $data);
+        if(strlen($tmp[1]) >= $content_lenght)
         {
             return 0;
         }
-        
-        // var_export($header_data);
+        return 1;
+    }
+    else
+    {
         return 0;
-    }    
+    }
     
-    /**
-     * 解析http协议包,并设置相应环境变量
-     * 
-     * @param string $data
-     * @return array
-     */
-    public static function decode($data)
-    {
-        $_SERVER = array(
-                'REQUEST_URI'    => '/',
-                'HTTP_HOST'      => '127.0.0.1',
-                'HTTP_COOKIE'    => '',
-                );
-        
-        $_POST = $_GET = $_COOKIE = $REQUEST = $GLOBALS['HTTP_RAW_POST_DATA'] = array();
-        
-        // 将header分割成数组
-        $header_data = explode("\r\n", $data);
-        
-        // 需要解析$_POST
-        if(strpos($data, "POST") === 0)
-        {
-            $tmp = explode("\r\n\r\n", $data);
-            parse_str($tmp[1], $_POST);
-            
-            // $GLOBALS['HTTP_RAW_POST_DATA']
-            $GLOBALS['HTTP_RAW_POST_DATA'] = $tmp[1];
-        }
-        
-        // REQUEST_URI
-        $tmp = explode(' ', $header_data[0]);
-        $_SERVER['REQUEST_URI'] = isset($tmp[1]) ? $tmp[1] : '/';
-        
-        // PHP_SELF
-        $base_name = basename($_SERVER['REQUEST_URI']);
-        $_SERVER['PHP_SELF'] = empty($base_name) ? 'index.php' : $base_name;
-        
-        unset($header_data[0]);
-        foreach($header_data as $content)
+    return 0;
+}
+
+function http_response_begin()
+{
+    $_POST = $_GET = $_COOKIE = $_REQUEST = $_SESSION = $GLOBALS['HTTP_RAW_POST_DATA'] = array();
+    HttpCache::$header = array();
+    HttpCache::$instance = new HttpCache();
+}
+
+function http_requset_parse($data)
+{
+    $_SERVER = array(
+            'REQUEST_URI'    => '/',
+            'HTTP_HOST'      => '127.0.0.1',
+            'HTTP_COOKIE'    => '',
+    );
+    
+    
+    // 将header分割成数组
+    $header_data = explode("\r\n", $data);
+    
+    // 需要解析$_POST
+    if(strpos($data, "POST") === 0)
+    {
+        $tmp = explode("\r\n\r\n", $data);
+        parse_str($tmp[1], $_POST);
+    
+        // $GLOBALS['HTTP_RAW_POST_DATA']
+        $GLOBALS['HTTP_RAW_POST_DATA'] = $tmp[1];
+    }
+    
+    // REQUEST_URI
+    $tmp = explode(' ', $header_data[0]);
+    $_SERVER['REQUEST_URI'] = isset($tmp[1]) ? $tmp[1] : '/';
+    
+    // PHP_SELF
+    $base_name = basename($_SERVER['REQUEST_URI']);
+    $_SERVER['PHP_SELF'] = empty($base_name) ? 'index.php' : $base_name;
+    
+    unset($header_data[0]);
+    foreach($header_data as $content)
+    {
+        // 解析HTTP_HOST
+        if(strpos($content, 'Host') === 0)
         {
-            // 解析HTTP_HOST
-            if(strpos($content, 'Host') === 0)
+            $tmp = explode(':', $content);
+            if(isset($tmp[1]))
             {
-                $tmp = explode(':', $content);
-                if(isset($tmp[1]))
-                {
-                    $_SERVER['HTTP_HOST'] = $tmp[1];
-                }
-                if(isset($tmp[2]))
-                {
-                    $_SERVER['SERVER_PORT'] = $tmp[2];
-                }
+                $_SERVER['HTTP_HOST'] = $tmp[1];
             }
-            // 解析Cookie
-            elseif(strpos($content, 'Cookie') === 0)
+            if(isset($tmp[2]))
             {
-                $tmp = explode(' ', $content);
-                if(isset($tmp[1]))
-                {
-                    $_SERVER['HTTP_COOKIE'] = $tmp[1];
-                }
-                if($_SERVER['HTTP_COOKIE'])
-                {
-                    parse_str(str_replace('; ', '&', $_SERVER['HTTP_COOKIE']), $_COOKIE);
-                }
+                $_SERVER['SERVER_PORT'] = $tmp[2];
             }
         }
-        
-        // 'REQUEST_TIME_FLOAT' => 1375774613.237,
-        $_SERVER['REQUEST_TIME_FLOAT'] = microtime(true);
-        $_SERVER['REQUEST_TIME'] = intval($_SERVER['REQUEST_TIME_FLOAT']);
-        
-        // GET
-        parse_str(preg_replace('/^\/.*?\?/', '', $_SERVER['REQUEST_URI']), $_GET);
-        unset($_GET['/']);
-        
-    }
-    
-    /**
-     * 设置http头
-     * @return bool
-     */
-    public static function header($content)
-    {
-        if(strpos($content, 'HTTP') === 0)
+        // 解析Cookie
+        elseif(stripos($content, 'Cookie') === 0)
         {
-            $key = 'Http-Code';
-        }
-        else
-        {
-            $key = strstr($content, ":", true);
-            if(empty($key))
+            $_SERVER['HTTP_COOKIE'] = trim(substr($content, strlen('Cookie:')));
+            if($_SERVER['HTTP_COOKIE'])
             {
-                return false;
+                parse_str(str_replace('; ', '&', $_SERVER['HTTP_COOKIE']), $_COOKIE);
             }
         }
-        self::$header[$key] = $content;
-        return true;
     }
+    // 'REQUEST_TIME_FLOAT' => 1375774613.237,
+    $_SERVER['REQUEST_TIME_FLOAT'] = microtime(true);
+    $_SERVER['REQUEST_TIME'] = intval($_SERVER['REQUEST_TIME_FLOAT']);
     
-    /**
-	 * Set the cookie
-	 * @param string $name         Name of cookie
-	 * @param string $value        Value
-	 * @param integer $maxage      . Optional. Max-Age. Default is 0.
-	 * @param string $path         . Optional. Path. Default is empty string.
-	 * @param bool|string $domain  . Optional. Secure. Default is false.
-	 * @param boolean $secure      . Optional. HTTPOnly. Default is false.
-	 * @param bool $HTTPOnly
-	 * @return void
-	 */
-	public static function setcookie($name, $value = '', $maxage = 0, $path = '', $domain = '', $secure = false, $HTTPOnly = false) {
-		self::header(
-			'Set-Cookie: ' . $name . '=' . rawurlencode($value)
-			. (empty($domain) ? '' : '; Domain=' . $domain)
-			. (empty($maxage) ? '' : '; Max-Age=' . $maxage)
-			. (empty($path) ? '' : '; Path=' . $path)
-			. (!$secure ? '' : '; Secure')
-			. (!$HTTPOnly ? '' : '; HttpOnly'), false);
-	}
-    
-    /**
-     * 清除header
-     * @return void
-     */
-    public static function clear()
+    // GET
+    parse_str(preg_replace('/^\/.*?\?/', '', $_SERVER['REQUEST_URI']), $_GET);
+    unset($_GET['/']);
+}
+
+function http_encode($content)
+{
+    // 没有http-code默认给个
+    if(!isset(HttpCache::$header['Http-Code']))
     {
-        self::$header = array();
+        $header = "HTTP/1.1 200 OK\r\n";
     }
+    else
+    {
+        $header = HttpCache::$header['Http-Code']."\r\n";
+        unset(Header::$header['Http-Code']);
+    }
+
+    // 没有Content-Type默认给个
+    if(!isset(HttpCache::$header['Content-Type']))
+    {
+        $header .= "Content-Type: text/html;charset=utf-8\r\n";
+    }
+
+    // 其它header
+    foreach(HttpCache::$header as $item)
+    {
+        $header .= $item."\r\n";
+    }
+   
+    // header
+    $header .= "Server: WorkerMan/2.1\r\nContent-Length: ".strlen($content)."\r\n";
+ 
+    $header .= "\r\n";
     
-    /**
-     * 打包http协议,用于返回数据
-     * 
-     * @param string $data
-     * @return string
-     */
-    public static function encode($data)
-    {
-        // header
-        $header = "Server: WorkerMan/1.0\r\nContent-Length: ".strlen($data)."\r\n";
-        
-        // 没有Content-Type默认给个
-        if(!isset(self::$header['Content-Type']))
-        {
-            $header = "Content-Type: text/html;charset=utf-8\r\n".$header;
-        }
-        
-        // 没有http-code默认给个
-        if(!isset(self::$header['Http-Code']))
+    HttpCache::$header = array();
+    
+    // 整个http包
+    return $header.$content;
+}
+
+function http_response_finish()
+{
+    // 保存cookie
+    session_write_close(); 
+    $_POST = $_GET = $_COOKIE = $_REQUEST = $_SESSION = array();
+    $GLOBALS['HTTP_RAW_POST_DATA'] = '';
+    HttpCache::$instance = null;
+}
+
+function setcookie($name, $value = '', $maxage = 0, $path = '', $domain = '', $secure = false, $HTTPOnly = false) {
+    header(
+            'Set-Cookie: ' . $name . '=' . rawurlencode($value)
+            . (empty($domain) ? '' : '; Domain=' . $domain)
+            . (empty($maxage) ? '' : '; Max-Age=' . $maxage)
+            . (empty($path) ? '' : '; Path=' . $path)
+            . (!$secure ? '' : '; Secure')
+            . (!$HTTPOnly ? '' : '; HttpOnly'), false);
+}
+
+
+/**
+ * http session 相关
+ * @author walkor <worker-man@qq.com>
+ * */
+
+function session_start()
+{
+    if(HttpCache::$instance->sessionStarted)
+    {
+        echo "already sessionStarted\nn";
+        return true;
+    }
+    HttpCache::$instance->sessionStarted = true;
+    // 没有sid,则创建一个session文件,生成一个sid
+    if(!isset($_COOKIE[HttpCache::$sessionName]) || !is_file(HttpCache::$sessionPath . '/sess_' . $_COOKIE[HttpCache::$sessionName]))
+    {
+        $file_name = tempnam(HttpCache::$sessionPath, 'sess_');
+        if(!$file_name)
         {
-            $header = "HTTP/1.1 200 OK\r\n".$header;
+            return false;
         }
-        else
-        {
-            $header = self::$header['Http-Code']."\r\n".$header;
-            unset(self::$header['Http-Code']);
+        HttpCache::$instance->sessionFile = $file_name;
+        $session_id = substr(basename($file_name), strlen('sess_'));
+        return setcookie(
+                HttpCache::$sessionName
+                , $session_id
+                , ini_get('session.cookie_lifetime')
+                , ini_get('session.cookie_path')
+                , ini_get('session.cookie_domain')
+                , ini_get('session.cookie_secure')
+                , ini_get('session.cookie_httponly')
+        );
+    }
+    if(!HttpCache::$instance->sessionFile)
+    {
+        HttpCache::$instance->sessionFile = HttpCache::$sessionPath . '/sess_' . $_COOKIE[HttpCache::$sessionName];
+    }
+    // 有sid则打开文件,读取session值
+    if(HttpCache::$instance->sessionFile)
+    {
+        $raw = file_get_contents(HttpCache::$instance->sessionFile);
+        if($raw)
+        { 
+            $_SESSION = session_unserialize($raw);
         }
-        
-        // 其它header
-        foreach(self::$header as $content)
-        {
-            $header .= $content."\r\n";
+    }
+}
+
+function session_unserialize($raw) {
+    $return_data = array();
+    $offset     = 0;
+
+    while ($offset < strlen($raw)) {
+        if (!strstr(substr($raw, $offset), "|")) {
+            return false;
         }
-        
-        $header .= "\r\n";
-        
-        self::clear();
-        
-        // 整个http包
-        return $header.$data;
-    }
-}
+
+        $pos     = strpos($raw, "|", $offset);
+        $num     = $pos - $offset;
+        $varname = substr($raw, $offset, $num);
+        $offset += $num + 1;
+        $data    = unserialize(substr($raw, $offset));
+
+        $return_data[$varname] = $data;
+        $offset += strlen(serialize($data));
+    }
+
+    return $return_data;
+}
+
+function session_serialize($session)
+{ 
+  $session_str = '';
+  if(is_array($session))
+  {
+    foreach($session as $key => $value)
+    {
+        $session_str .= "$key|".serialize($value);
+    }
+  }
+  return $session_str;
+}
+
+function session_write_close()
+{
+    if(HttpCache::$instance->sessionStarted && !empty($_SESSION))
+    {
+       $session_str = session_serialize($_SESSION);
+       if($session_str && HttpCache::$instance->sessionFile)
+       {
+           return file_put_contents(HttpCache::$instance->sessionFile, $session_str);
+       }
+    }
+    return empty($_SESSION);
+}

+ 2 - 2
conf/conf.d/Monitor.conf

@@ -5,7 +5,7 @@
 ;④监控每个worker进程内存是否大于设定值,大于设定值则安全重启对应进程
 
 ;监听ip及端口
-listen = tcp://0.0.0.0:2000
+listen = tcp://0.0.0.0:2001
 ;telnet需要长连接
 persistent_connection = 1
 ;启动多少进程,1个就够
@@ -21,4 +21,4 @@ max_worker_exit_count=2000
 ;每个worker进程最大内存阈值,超过这个值安全重启这个进程
 max_mem_limit=124000
 ;telnet密码
-password=yourpassword
+password=yourpassword

+ 3 - 3
conf/workerman.conf

@@ -1,11 +1,11 @@
 ;debug=1则var_dump、echo、php notcie等会在终端上打印出来
 debug=1
 ;保存主进程pid的文件
-pid_file=/var/run/php-server.pid
+pid_file=/var/run/php-server2.pid
 ;日志文件目录
 log_dir=./logs/
 ;共享内存及消息队列用到的key
-ipc_key=0x70010a2e
+ipc_key=0x70010a2f
 ;开启共享内存大小
 shm_size=393216
-indlue=conf.d/*.conf
+indlue=conf.d/*.conf

+ 19 - 6
workers/WorkerManAdmin.php

@@ -1,7 +1,6 @@
 <?php
 require_once WORKERMAN_ROOT_DIR . 'man/Core/SocketWorker.php';
 require_once WORKERMAN_ROOT_DIR . 'applications/Common/Protocols/Http.php';
-require_once WORKERMAN_ROOT_DIR . 'applications/Common/Protocols/Session.php';
 
 /**
  * 
@@ -12,13 +11,19 @@ require_once WORKERMAN_ROOT_DIR . 'applications/Common/Protocols/Session.php';
  */
 class WorkerManAdmin extends Man\Core\SocketWorker
 {
+    
+    public function onStart()
+    {
+        App\Common\Protocols\HttpCache::init();
+    }
+
     /**
      * 确定数据是否接收完整
      * @see Man\Core.SocketWorker::dealInput()
      */
     public function dealInput($recv_str)
     {
-        return App\Common\Protocols\Http::dealInput($recv_str); 
+        return App\Common\Protocols\http_deal_input($recv_str); 
     }
 
     /**
@@ -30,9 +35,17 @@ class WorkerManAdmin extends Man\Core\SocketWorker
         /**
          * 解析http协议,生成$_POST $_GET $_COOKIE
          */
-        App\Common\Protocols\Http::decode($recv_str);
-        
-        var_dump($_GET,$_POST,$_COOKIE);
-        $this->sendToClient(App\Common\Protocols\Http::encode(var_export($_COOKIE, true)));
+        App\Common\Protocols\http_response_begin();
+        App\Common\Protocols\http_requset_parse($recv_str);
+        App\Common\Protocols\session_start();
+        ob_start();
+        echo 'cookie';var_export($_COOKIE);
+        echo 'session';var_export($_SESSION);
+        $_SESSION['abc'] = 1333;
+        $_SESSION['ddd'] = array('a'=>2,3=>0);
+        $content = ob_get_clean();
+        App\Common\Protocols\http_response_finish();
+        $buffer = App\Common\Protocols\http_encode($content);
+        $this->sendToClient($buffer);
     }
 }