mindgruve/mg-reverse-proxy

简单的反向代理缓存

0.9.2 2017-04-06 18:17 UTC

README

MG-Reverse-Proxy提供了一个连接您的Web应用程序和Symfony HTTP缓存的桥梁。使用MG-Reverse-Proxy,您可以缓存像WordPress这样的应用程序,就像您缓存Symfony应用程序一样。它是通过将应用程序创建的输出缓冲区和头部转换为可以智能缓存的Symfony响应对象来工作的。这对于遗留项目和不是基于Symfony全栈框架(如WordPress、Joomla,甚至是Magento网站)构建的应用程序非常适用。

与Symfony HTTP缓存类似,MG-Reverse-Proxy将缓存设置为PUBLIC、具有正的MAX-AGE以及请求是“安全”的HTTP方法(即GET或HEAD)的响应。

由于MG-Reverse-Proxy是Symfony HTTPCache的一个简单包装,因此提供的Symfony文档将有助于理解MG-Reverse-Proxy的内部机制。有关Symfony HTTPCache的更多信息,请参阅:https://symfony.com.cn/doc/current/book/http_cache.html

使用场景

内容丰富的网站是MG-Reverse-Proxy的良好候选。您可以通过设置应用程序中的缓存头或在配置缓存适配器(如下所述)来定制响应的可缓存性。

在无法安装专用缓存解决方案(如Varnish)的情况下,您可以使用MG-Reverse-Proxy。与Varnish不同,MG-Reverse-Proxy是用PHP编写的,这使得您更容易向Web应用程序添加缓存层。

缓存的好处...

初始请求(或过期的缓存请求)

Request -> Is caching enabled?  
        -> MG-Reverse-Proxy bootstraps your application and creates a Symfony HTTPCache object and HTTPKernel.
        -> Your application generates webpage (multiple hits to database)
        -> MG-Reverse-Proxy captures the outputbuffer and transforms it into a Symfony Response object
        -> The cache adapter sets headers if applicable
        -> The Response object is returned to the Symfony HTTPCache
        -> The Symfony HTTPCache stores result in local cache 
        -> Finally, the response is returned to user

后续请求

Request -> Is caching Enabled?   
        -> Webpage respone pulled from cache
        -> Returns cached response to user
        
Note: With a cached response, your application is not bootstrapped at all!

缓存适配器

缓存适配器是您添加缓存业务逻辑的入口点。创建并提供了Symfony响应对象给您的适配器,以便您可以设置缓存头。然后,MG-Reverse-Proxy将使用该响应进行智能缓存。源代码中包含两个示例适配器 - 一个通用适配器和一个WordPress适配器。您应该为您的应用程序编写自己的适配器,无论是扩展 GenericCacheAdapter 还是实现 CacheAdapterInterface

存储

Symfony HTTPCache有一个缓存存储的概念。默认情况下,这是一个文件系统上的本地目录。如果您想使用不同的缓存策略(memcache、redis...),您可以使用自己的 Symfony\Component\HttpKernel\HttpCache\StoreInterface 实现并将其作为构造函数参数传递。

##示例用法 - WordPress index.php WordPress的index.php文件看起来像...

<?php
include_once(dirname( __FILE__ ) . '/wp-blog-header.php');

要启用WordPress应用程序的缓存,您实例化一个缓存存储(本例中是一个本地目录)。我们实例化一个新的CachedReverseProxy对象,使用WordPress适配器,传递引导文件的路径,以及默认的最大缓存时间(本例中为600秒)。

新的(缓存过的)索引页面源代码将类似...

<?php 
include_once(__DIR__ . '/../../application/vendor/autoload.php');

use Symfony\Component\HttpKernel\HttpCache\Store;
use Mindgruve\ReverseProxy\CachedReverseProxy;
use Mindgruve\ReverseProxy\Adapters\WordPressAdapter;

// Instantiate cache store
$store = new Store(dirname(__FILE__) . '/wp-content/cache');

// Instantiate Reverse Proxy
$reverseProxy = new CachedReverseProxy(
    new WordPressAdapter(
        function(){
            include_once(dirname( __FILE__ ) . '/wp-blog-header.php')
        }, 
        600, $store
    )
);
        
// Run Cached Application        
$reverseProxy->run();

修改WordPress适配器

您可以使用多个入口点来修改WordPress适配器的行为。首先扩展 WordPressAdapter 并覆盖相关方法。

以下是对您自定义适配器的重要方法的描述

isCachingEnabled (布尔值) - 如果为真,则启用缓存。如果为假,则关闭缓存,所有响应都会直接到达您的应用程序。

通用适配器的默认值为true。WordPress适配器的默认行为是在用户登录时关闭缓存。

setCacheHeaders (响应) - 此方法用于允许您为每个请求/响应设置自定义缓存头。使用此方法,您可以标记某些方法为公开,修改max-age,并设置您想要的任何缓存头。

通用适配器不会设置任何头,并会尊重您的应用程序设置的缓存头。WordPress适配器在用户登录时将其设置为私有,否则设置为公开。这意味着匿名用户的所有响应都将被缓存。

bootstrap (无返回值) - 此方法将调用构造函数参数中提供的Bootstrap函数。例如,WordPress适配器将加载Bootstrap WordPress的文件。

getRawContent (字符串) - 此方法返回一个字符串。这通常是输出缓冲区。MG-Reverse-Proxy将getRawContent的返回值转换为Symfony响应对象。

getStore (StoreInterface) - 返回HTTPCache可以用来缓存响应的存储。

getSurrogate (SurrogateInterface) - 用于与Varnish集成。有关更多信息,请参阅Symfony文档。

示例 - 更新WordPress适配器 - 将联系页面标记为私有

在此示例中,我们假设您有一个包含联系页面的WordPress网站,并且您正在使用MG-Reverse-Proxy来提高您网站的响应速度。一切工作正常,除了您在url /contact 上有一个联系表单。缓存此页面有问题,因为CSRF令牌和验证错误将被缓存。请记住,提供的示例WordPress适配器将缓存匿名用户查看的任何页面。

您可以通过扩展WordPress适配器并重写setCacheHeaders()方法来更新缓存适配器以实现自己的业务规则。setCacheHeaders()方法在您的应用程序生成响应后调用,但在将响应发送到HTTPCache之前。这允许您在不更改应用程序的情况下修改缓存逻辑。

要排除url /contact 被缓存,您的自定义适配器可以是...

use Mindgruve\ReverseProxy\Adapters\WordPressAdapter;

class CustomWordpressAdapter extends WordPressAdapter {

    /**
     * @param Request $request
     * @param Response $response
     * @return Response
     */
    public function setCacheHeaders(Request $request, Response $response)
    {
        if(preg_match('/^contact', $request->getRequestUri()){
            $response->setPrivate;
            return response;
        }
    
        return parent::setCacheHeaders($request, $response)
    }
}

请注意,如果url匹配/contact,我们返回一个带有缓存头设置为私有的Symfony响应对象(即,不缓存)。

要使用此自定义适配器,请更新您的index.php文件以在反向代理的构造中使用它。

// Instantiate Reverse Proxy
$reverseProxy = new CachedReverseProxy(
    new CustomWordpressAdapter(
        function(){
            include_once(dirname( __FILE__ ) . '/wp-blog-header.php')
        }, 
        600, $store
    )
);

注意:WordPress适配器是为了让开发者快速缓存他们的WordPress应用程序而设计的。WordPress没有提供方便的方法来设置缓存头,只有某些页面,因此setCacheHeaders()方法允许您检查请求/响应并适当地修改响应和设置头。

然而,正如您所想象的那样,如果您的业务规则来确定哪些页面应该被缓存很复杂,那么setCacheHeaders函数可能会变得非常大。在某些时候,可能需要切换到通用适配器,并将此缓存逻辑从setCacheHeaders方法中重构到您的WordPress应用程序中。

错误/补丁/功能

欢迎贡献。请随意分叉并提交拉取请求。

许可

MIT许可 版权所有(c)2016 Mindgruve

本软件及其相关文档文件(以下简称“软件”)的使用权、复制权、修改权、合并权、发布权、分发权、再许可权和/或销售副本的权利,以及允许获得软件副本的个人进行上述行为,特此免费授予,不受限制,包括但不限于以下条件:

上述版权声明和本许可声明应包含在软件的所有副本或实质性部分中。

软件按“现状”提供,不提供任何形式的保证,无论是明示的还是暗示的,包括但不限于适销性、适用于特定目的和非侵权的保证。在任何情况下,作者或版权所有者不对任何索赔、损害或其他责任承担责任,无论这些责任是基于合同、侵权或其他原因,以及与软件或软件的使用或其他相关事宜有关。