草庐IT

php - Apache 模块 : Implementing 100-Continue

coder 2024-04-07 原文

Supporting HTTP 100 Continue with PHP早在 2010 年就提出了这个问题,重点略有不同(它寻求 PHP 解决方案而不是 Apache 解决方案),但从未得到解决。

上下文

HTTP/1.1 规范创建了具有一个定义值的请求 header “Expect”;即“100-Continue”。 2014 年 6 月发布的修订版 HTTP/1.1 RFC(参见 RFC 7231 Section 5.1.1)声明如下:

A 100-continue expectation informs recipients that the client is about to send a (presumably large) message body in this request and wishes to receive a 100 (Continue) interim response if the request-line and header fields are not sufficient to cause an immediate success, redirect, or error response. This allows the client to wait for an indication that it is worthwhile to send the message body before actually doing so, which can improve efficiency when the message body is huge or when the client anticipates that an error is likely (e.g., when sending a state-changing method, for the first time, without previously verified authentication credentials).

这也是一个普遍接受的说法,即规范的这一部分在服务器和客户端都没有完全实现。修订后的规范甚至暗示了这一点:

...However, the extension mechanism has not been used by clients and the must-understand requirements have not been implemented by many servers...

重点是我的,不是来自规范

即使排除此 header 的扩展机制,100-continue 值似乎也没有得到很好的实现。如果我们考虑一个标准的 PHP/Apache 堆栈,Apache 会在客户端请求时提供 100-continue 临时响应。

但是,它仅根据自己对请求的处理来执行此操作,即不咨询 PHP 资源。这似乎违背了 header 的目的,因为大多数请求都会因无效的请求参数或权限而失败;不是由于格式错误的 HTTP 请求。因此,即使客户端声明了 100-continue 期望并收到 100-continue 响应,也不意味着请求头有效。

意图

作为更全面地实现 HTTP 规范的更广泛意图的一部分(为了提高网络效率、安全性和清晰度),我打算在发送 100-continue 响应之前更正确地验证请求 header 。

这意味着在发送 100-continue 响应之前,请求必须传递到我的 PHP 资源 Controller 以进行验证。这允许在客户端浪​​费时间和资源发送大消息正文之前识别无效参数和不正确的权限。

我希望交换看起来像这样:

Client                    Apache                      Resource
->|                         |                            |
  |------Request Head------>|                            |
  |                         |-[Parse]                    |
  |<-----400 bad request----|                            |
  |                         |-[Route]                    |
  |                         |-------Request Head-------->|
  |                         |                            |-[Validate]
  |                         |<---Error / 100 Continue----|
  |<--Error / 100 Continue--|                            |
<-|[End or...]              |                            |
  |------Request Body------>|                            |
  |                         |--------Full Request------->|
  |                         |                            |-[Process]
  |                         |<---------Response----------|
  |<--------Response--------|                            |
<-|                         |                            |

显然,这需要 PHP 应用程序和 apache 网络服务器之间更好的互操作。

策略

由于所需的集成程度,唯一的解决方案似乎是一个 Apache 模块/扩展,旨在在发送 100-continue 响应之前立即连接到请求,并执行将请求头传递给用于解析的 PHP 资源。

从那里,正常的 Apache 处理可以恢复,发送 100-continue 响应,Apache 等待消息正文,然后将完成的请求传递给 PHP 资源。

问题

  1. 如上所述的 Apache 模块是否会改进当前的实现?

  2. 过去是否有任何模块试图解决这个问题?

此外,关于开发 Apache 模块的技术细节:

  1. 有哪些 Apache Hook 可用?我找不到标识可用 Hook 及其处理顺序的资源。 找到了 Apache2: Apache Hooks

  2. Apache 模块应如何与 PHP 交互?我知道这取决于安装方法(例如 Apache 进程中的多个线程或每次执行的单个进程等)。但是我不确定 Apache 究竟是如何管理它与 PHP 进程的其他交互的。

最佳答案

您所描述的不适用于大多数处理程序,包括 PHP。 HTTP 是一种基于消息的协议(protocol),通常它是一种请求-回复方法——唯一的异常(exception)是连接请求、Web 套接字和 expect/100 响应。因此实现这一点将需要重新设计网络服务器的内部结构、处理程序的接口(interface)和处理程序本身:对于 CGI、fastcgi 和 isapi 模块,PHP 在请求被编码到网络服务器之前不会看到请求。

而且您还必须实现自己的客户端(至少作为 AJAX/SJAX JavaScript)。

考虑预先发送您的请求:

 Client: can I send a really big file?
 Server: 204
 Client: here's a really big file

只有一组额外的 header ,与 expect/100 方法相比没有额外的 RTT。花一些时间来计算每个请求的最终成本。它很小。它适用于今天的所有服务器。并且不需要花费数月的时间来开发。 不想在问题的替代解决方案的细节中陷入困境,显然我们希望两个客户端请求中的 URL 相同,因此需要在其他地方表达 2 个客户端请求的意图差异,例如通过在第一个请求中使用 OPTIONS 动词,在第二个请求中使用 PUT/POST/GET/DELETE。

为此,客户端代码几乎没有区别。

但假设您有一大群开发人员和测试人员,除了开发您提议的模块之外别无他法,并且不需要对处理程序进行大量更改,或者上述处理程序的维护者自己构建对 expect/100 的支持。 .. 作为 Web 服务器管理员,当我无需安装额外模块即可获得相同结果时,我为什么要安装这样的模块,增加我的 Web 服务器的攻击面并调整我已经使用的任何代码?

关于php - Apache 模块 : Implementing 100-Continue,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35456122/

有关php - Apache 模块 : Implementing 100-Continue的更多相关文章

  1. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  2. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  3. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  4. ruby - 当使用::指定模块时,为什么 Ruby 不在更高范围内查找类? - 2

    我刚刚被困在这个问题上一段时间了。以这个基地为例:moduleTopclassTestendmoduleFooendend稍后,我可以通过这样做在Foo中定义扩展Test的类:moduleTopmoduleFooclassSomeTest但是,如果我尝试通过使用::指定模块来最小化缩进:moduleTop::FooclassFailure这失败了:NameError:uninitializedconstantTop::Foo::Test这是一个错误,还是仅仅是Ruby解析变量名的方式的逻辑结果? 最佳答案 Isthisabug,or

  5. ruby - 获取模块中定义的所有常量的值 - 2

    我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c

  6. ruby - 模块嵌套代码风格偏好 - 2

    我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的

  7. ruby-on-rails - 使用 config.threadsafe 时从 lib/加载模块/类的正确方法是什么!选项? - 2

    我一直致力于让我们的Rails2.3.8应用程序在JRuby下正确运行。一切正常,直到我启用config.threadsafe!以实现JRuby提供的并发性。这导致lib/中的模块和类不再自动加载。使用config.threadsafe!启用:$rubyscript/runner-eproduction'pSim::Sim200Provisioner'/Users/amchale/.rvm/gems/jruby-1.5.1@web-services/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:105:in`co

  8. 叮咚买菜基于 Apache Doris 统一 OLAP 引擎的应用实践 - 2

    导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵

  9. ruby-on-rails - Controller 中的 Rails 辅助模块 - 2

    我有一个Controller,我想为这个Controller创建一个助手,我可以在不包含它的情况下使用它。我尝试像这样创建一个与Controller同名的助手classCars::EnginesController我创建的助手是moduleCars::EnginesHelperdefcheck_fuellogger.debug("chekingfuel")endend我得到的错误是undefinedlocalvariableormethod`check_fuel'for#有没有我遗漏的约定? 最佳答案 如果你真的想在Controll

  10. ruby-on-rails - 具有同名的模块和类 - 2

    我有一个模块stat存在于目录结构中:lib/stat_creator/stat/在lib/stat_creator/stat.rb中,我在lib/stat_creator/stat/目录中有我需要的文件,以及:moduleStatCreatormoduleStatendend当我使用该模块时,我将这些类称为StatCreator::Stat::Foo.new现在我想要一个存在于应用程序中的根Stat类。我在app/models中制作了我的Stat类,并在routes.rb中进行了设置。但是,如果我转到Rails控制台并尝试在应用程序/模型中使用Stat类,例如:Stat.by_use

随机推荐