【问题标题】:php - send HTTP status BEFORE the code executesphp - 在代码执行之前发送 HTTP 状态
【发布时间】:2012-12-04 18:24:28
【问题描述】:

我想在其余代码在 php 脚本中执行之前将 http 状态(200 OK)发送到调用脚本。对于发送状态码,我使用的是 HTTP/1.1 200 OK,但它在整个脚本执行完成后发送状态,这使得调用脚本等待。我不确定这是否可能。有什么帮助吗?

详细:假设我有两个脚本,a.php 和 b.php。 a.php 正在调用 b.php 并等待 http 状态,如果是 200 则继续执行其他操作。我希望 b.php 脚本在被调用后立即发送回 200 响应,然后继续使用自己的代码。

谢谢!

编辑: 在阅读了 cmets 之后,我明白我想做的是一个坏主意。但是,让我说一下我为什么这么想,并且可以做这样的事情。

a.php 将有一个网络界面,人们可以在其中上传他们的图像,上传完成后 a.php 调用 b.php 使用这些图像进行一些处理。我希望 a.php 继续而不是挂起/等待 b.php 完成,以防 b.php 失败,我想我可能能够“推送”一个错误,以便 a.php 可以提示用户失败.应该使用不同的线程吗?

【问题讨论】:

  • 在你做任何事情之前,你怎么知道状态是否正常?如果状态为always OK 并且您并不真正关心结果,则您的其他脚本可以在后台执行请求。那么响应何时到来并不重要。
  • 采用这种设计,如果 B 失败,那么 A 仍会收到 200 并继续进行,就好像没有发生错误一样。这使得检查状态变得毫无意义。
  • 请看已编辑的问题,我想我应该使用线程,有什么建议吗?
  • 如果您确实选择使用 NodeJS,请随时联系我。我非常乐意帮助您入门。

标签: php http http-headers


【解决方案1】:

PHP 确实可以做到,但是有点棘手。

ignore_user_abort(true);
header("Content-Length: 0");
header("Connection: Close");
flush();
session_write_close();

// do something that takes very long

这是您需要的最少代码。如果您没有会话,您可以停止最后一次通话。

一旦你关闭了连接,你就不能发送更新,所以如果你想通过错误报告做一些事情,你必须找到另一种方法。

【讨论】:

    【解决方案2】:

    我正在考虑 AJAX 或 XMLRPC,但正如@Andrew 所说,php 不能那样工作。NodeJS 确实是一个不错的选择...

    【讨论】:

      【解决方案3】:

      a.php 正在调用 b.php 并等待 http 状态,如果是 200 则继续执行其他操作

      简短的回答是您无法控制网络服务器何时刷新它的缓冲区。因此,您需要绕过网络服务器来调用 b.php。问题是,如果您通过 exec / system / etc 调用它,那么 b.hpp 将成为 a.php 的子进程 - which is a really bad idea 如果 b.php 需要花费任何时间才能完成。

      鉴于您需要采取完全不同的策略来解决问题,了解为什么您希望它在之前发出无条件的 200 状态非常重要> 它做任何有用的工作(当它最有可能失败时它正在做有用的工作)。

      根据您提供的信息(这不是很多),实现这一点的唯一可靠方法是通过消息队列(以及在守护程序中运行的自定义订阅者) - 假设您可以替换成功的入队返回状态码的操作。但这有它自己的复杂性。

      【讨论】:

        【解决方案4】:

        嗯,听起来您最好使用允许基于套接字的连接的东西。查看 NodeJS。我认为 PHP 也可能支持某种形式的基于套接字的连接。您尝试使用“flush”执行的操作实际上是非常糟糕的做法。 PHP 不是为多负载设计的,如果你使用 AJAX,你会遇到很多问题。

        【讨论】:

          【解决方案5】:

          如果您的 a.php 希望 b.php 异步运行,您可以考虑使用 cURL POST 方法来启动脚本。 a.php 可以设置超时时间为 1 秒,cURL 会话将停止。 b.php 会继续运行,而 a.php 也会继续运行。

          【讨论】:

          • 我在这里看到了一些关于 gzip 和 flush 的 cmets。这些似乎适用于浏览器输出,而不是标题;不考虑缓冲的情况下立即发送标头。而且 cURL 完全能够处理 GZIP。
          • 如果您将超时设置为一秒,则甚至不能保证脚本会开始运行,更不用说在请求中止时继续运行了。
          • 而且 headers 不会立即发送,它们通常在第一次输出发生时发送,不会更早。
          【解决方案6】:

          您拥有像 flush() 这样的功能,可以满足您的需求,但有一些注意事项。阅读更多:http://php.net/manual/en/function.flush.php

          由于您是在代码中调用 PHP 脚本,因此您不必担心列出的浏览器问题。但是如果启用了 mod_gzip 之类的东西,就不可能了。

          【讨论】:

            猜你喜欢
            • 2019-03-26
            • 1970-01-01
            • 2023-03-06
            • 2011-03-23
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-12-25
            • 2016-11-18
            相关资源
            最近更新 更多