修改了下webman的请求和响应类,使得可以在中间件中更新Cookie

LEO_D86

我修改的目的主要是为了使用中间件能对cookie进行透明的加解密,在这里分享一下,同时如果有大佬发现有什么问题也欢迎指出。

修改 Webman\Http\Request

添加updateCookie方法用来刷新请求实例中的cookie,目的是为了使用中间件来对请求Cookie进行解密。不过需要注意的是,webman会对request对象进行缓存,就是满足一定条件的两个请求,后面的请求webman会直接取出缓存而不再构造新的request对象。还没有具体看怎么判断当前request对象是缓存对象还是新建对象。

public function updateCookie($name, $value)
{
    if (!isset($this->_data['cookie'])) {
        $this->_data['cookie'] = array();
    }

    $this->_data['cookie'][$name] = $value;
}

修改 Webman\Http\Response

添加若干方法用于在发送响应之前修改cookie,需要先调用cookiesToJar将响应中的Cookie解析出来,然后使用updateCookie来更新,我这里主要用来在中间件中加密,这个方法不支持添加不存在的cookie,最后使用saveCookie将cookie重新写入到响应中。

...

protected $cookieJar = [];

...

public function cookiesToJar()
{
    if (isset($this->_header['Set-Cookie'])) {
        foreach ($this->_header['Set-Cookie'] as $cookie) {
            $setcookie = [];

            \parse_str(\preg_replace('/; ?/', '&', $cookie), $setcookie);

            $name = array_key_first($setcookie);

            if (!isset($this->cookieJar[$name])) {
                $this->cookieJar[$name] = [];
            }

            if (isset($setcookie['path'])) {
                $this->cookieJar[$name][$setcookie['path']] = array_merge($setcookie, [
                    'value' => $setcookie[$name],
                ]);
            } else {
                $this->cookieJar[$name][] = array_merge($setcookie, [
                    'value' => $setcookie[$name],
                ]);
            }
        }
    }

    return $this->cookieJar;
}

public function updateCookie($name, $value, $path = null)
{
    if (empty($this->cookieJar)) {
        return $this;
    }

    if (isset($this->cookieJar[$name])) {
        if ($path !== null && isset($this->cookieJar[$name][$path])) {
            $this->cookieJar[$name][$path]['value'] = $value;
            return $this;
        }

        $last_key = array_key_last($this->cookieJar[$name]);

        $this->cookieJar[$name][$last_key]['value'] = $value;
    }

    return $this;
}

public function saveCookie()
{
    if (isset($this->_header['Set-Cookie'])) {
        unset($this->_header['Set-Cookie']);
    }

    foreach ($this->cookieJar as $name => $name_cookies) {
        foreach ($name_cookies as $cookie) {var_dump($cookie);
            $this->cookie(
                $name, $cookie['value'], $cookie['max_age'] ?? 0, $cookie['path'] ?? '', $cookie['domain'] ?? '',
                $cookie['secure'] ?? false, $cookie['http_only'] ?? false, $cookie['same_site'] ?? false
            );
        }
    }
}
1232 1 0
1个评论

Tinywan

这样子不好吧!

  • LEO_D86 2022-03-16

    我主要是能够透明加解密Cookie的方法,目前找不到比较好的办法,同时还实现了一个Cookie服务,然后使用中间件来通过Cookie服务添加新cookie。
    我原来用laravel的,发现有些比较实用的功能webman并没有提供,但是谁叫webman快啊。另外,在webman中处理服务类(单例类)的时候需要格外小心处理上下文属性,在同一个worker中不同请求是共享服务的,服务端这方面经验不多,有点反PHP的使用直觉(每个请求都是隔离的)。

年代过于久远,无法发表评论

LEO_D86

200
积分
0
获赞数
0
粉丝数
2022-03-14 加入
🔝