jjzjj

php - 如何处理来自代理的额外 HTTP header ?

coder 2023-12-31 原文

我们的环境需要使用出站代理来提供异地服务。通常这不是问题。在这种使用 Twilio 的情况下,返回的额外 header 会破坏客户端。

传出 header :

POST /2010-04-01/Accounts/FOO/SMS/Messages.json HTTP/1.1
Authorization: Basic FOO==
User-Agent: twilio-php/3.10.0
Host: api.twilio.com
Accept: */*
Accept-Charset: utf-8
Content-Type: application/x-www-form-urlencoded
Content-Length: 108

响应头:

HTTP/1.0 200 Connection established

HTTP/1.1 201 Created
Server: nginx
Date: Thu, 06 Jun 2013 14:39:24 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 551
Connection: close
X-Powered-By: PHP/5.3.11

我只能假设代理正在添加额外的 HTTP header 。

Twilio 客户端会检查:

list($head, $body) = ($parts[0] == 'HTTP/1.1 100 Continue') 

据我了解,有些时候或版本的 curl 会自动在请求中添加 Expect header ,并且会在响应中返回 HTTP 100,但在这种情况下不是,响应是 200连接已建立。添加一个空的 Expect: 或 Expect:bacon 并没有改变结果是值得的。

我真的不想在这里过多地攻击 Twilio 客户端,我特别想避免只添加一个 || $parts[0] == 'HTTP/1.0 200 Connection established' 因为看起来很乱。

是否可以发送一个请求头来抑制/隐藏额外的头?或者,我没有看到忽略它的 curl 选项?

出站代理是Linux/Squid

最佳答案

代理问题是很多脚本都面临的问题。我可以在 Internet 上找到的首选解决方案是简单地添加以下代码行。

<?php
// cURL automatically handles Proxy rewrites, remove the "HTTP/1.0 200 Connection established" string
if (false !== stripos($response, "HTTP/1.0 200 Connection established\r\n\r\n")) {
  $response = str_ireplace("HTTP/1.0 200 Connection established\r\n\r\n", '', $response);
}
?>

现在将其添加到 twilio 客户端确实有点困惑。幸运的是,您可以使用 namespace 来重新创建 native 函数。请参阅以下示例。

<?php
namespace FakeCurl;

//create curl_exec function with same name, but its created in the FakeCurl namespace now.
function curl_exec($ch) {
  //execute the actual curl_exec function in the main namespace
  $response =  \curl_exec($ch);

  // cURL automatically handles Proxy rewrites, remove the "HTTP/1.0 200 Connection established" string
  if (false !== stripos($response, "HTTP/1.0 200 Connection established\r\n\r\n")) {
    $response = str_ireplace("HTTP/1.0 200 Connection established\r\n\r\n", '', $response);
  } 

  return "ADDED TO RESPONSE\r\n\r\n".$response;
}

//make a regular curl request, no alterations.

$curl = curl_init();
curl_setopt_array( $curl, array(
    CURLOPT_HEADER => true,
    CURLOPT_NOBODY => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_URL => 'http://stackoverflow.com' ) );
$response = curl_exec( $curl );
curl_close( $curl );

echo '<pre>'.$response.'</pre>';

?>

输出

ADDED TO RESPONSE

HTTP/1.1 200 OK
Cache-Control: public, max-age=11
Content-Length: 191951
Content-Type: text/html; charset=utf-8
Expires: Wed, 12 Jun 2013 07:09:02 GMT
Last-Modified: Wed, 12 Jun 2013 07:08:02 GMT
Vary: *
X-Frame-Options: SAMEORIGIN
Date: Wed, 12 Jun 2013 07:08:49 GMT

所以要与 twilio 客户端一起使用,您需要在脚本的最顶部放置以下内容:

<?php
namespace FakeCurl;
function curl_exec($ch) {
  $response =  \curl_exec($ch);

  // cURL automatically handles Proxy rewrites, remove the "HTTP/1.0 200 Connection established" string
  if (false !== stripos($response, "HTTP/1.0 200 Connection established\r\n\r\n")) {
    $response = str_ireplace("HTTP/1.0 200 Connection established\r\n\r\n", '', $response);
  } 

  return $response;
}

include("twilio.php");
?>

如果命名空间选项由于某种原因失败,我会在 twilio 客户端之外添加一个简单的函数,例如。

<?php
function fixProxyResponse($response) {
  // cURL automatically handles Proxy rewrites, remove the "HTTP/1.0 200 Connection established" string
  if (false !== stripos($response, "HTTP/1.0 200 Connection established\r\n\r\n")) {
    $response = str_ireplace("HTTP/1.0 200 Connection established\r\n\r\n", '', $response);
  } 

  return $response;
}

然后更改 twilio 脚本 TinyHttp.php 并仅更改以下行 (~linenr 63)

if ($response = curl_exec($curl)) {
  $parts = explode("\r\n\r\n", $response, 3);
  list($head, $body) = ($parts[0] == 'HTTP/1.1 100 Continue')

if ($response = curl_exec($curl)) {
  $parts = explode("\r\n\r\n", fixProxyResponse($response), 3);
  list($head, $body) = ($parts[0] == 'HTTP/1.1 100 Continue')

关于php - 如何处理来自代理的额外 HTTP header ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16965530/

有关php - 如何处理来自代理的额外 HTTP header ?的更多相关文章

  1. ruby-on-rails - Enumerator.new 如何处理已通过的 block ? - 2

    我在理解Enumerator.new方法的工作原理时遇到了一些困难。假设文档中的示例:fib=Enumerator.newdo|y|a=b=1loopdoy[1,1,2,3,5,8,13,21,34,55]循环中断条件在哪里,它如何知道循环应该迭代多少次(因为它没有任何明确的中断条件并且看起来像无限循环)? 最佳答案 Enumerator使用Fibers在内部。您的示例等效于:require'fiber'fiber=Fiber.newdoa=b=1loopdoFiber.yieldaa,b=b,a+bendend10.times.m

  2. ruby-on-rails - 如何处理 Grape 中特定操作的过滤器之前? - 2

    我正在我的Rails项目中安装Grape以构建RESTfulAPI。现在一些端点的操作需要身份验证,而另一些则不需要身份验证。例如,我有users端点,看起来像这样:moduleBackendmoduleV1classUsers现在如您所见,除了password/forget之外的所有操作都需要用户登录/验证。创建一个新的端点也没有意义,比如passwords并且只是删除password/forget从逻辑上讲,这个端点应该与用户资源。问题是Grapebefore过滤器没有像except,only这样的选项,我可以在其中说对某些操作应用过滤器。您通常如何干净利落地处理这种情况?

  3. Ruby - 如何处理子类意外覆盖父类(super class)私有(private)字段的问题? - 2

    假设您编写了一个类Sup,我决定将其扩展为SubSup。我不仅需要了解你发布的接口(interface),还需要了解你的私有(private)字段。见证这次失败:classSupdefinitialize@privateField="fromsup"enddefgetXreturn@privateFieldendendclassSub问题是,解决这个问题的正确方法是什么?看起来子类应该能够使用它想要的任何字段而不会弄乱父类(superclass)。编辑:equivalentexampleinJava返回"fromSup",这也是它应该产生的答案。 最佳答案

  4. ruby - HTTP 请求中的用户代理,Ruby - 2

    我是Ruby的新手。我试过查看在线文档,但没有找到任何有效的方法。我想在以下HTTP请求botget_response()和get()中包含一个用户代理。有人可以指出我正确的方向吗?#PreliminarycheckthatProggitisupcheck=Net::HTTP.get_response(URI.parse(proggit_url))ifcheck.code!="200"puts"ErrorcontactingProggit"returnend#Attempttogetthejsonresponse=Net::HTTP.get(URI.parse(proggit_url)

  5. ruby-on-rails - capybara poltergeist - 覆盖用户代理 - 2

    有人知道如何将capybarapoltergeist的用户代理覆盖到移动用户代理以进行测试吗?我发现了一些有关为seleniumwebdriver配置它的信息:http://blog.plataformatec.com.br/2011/03/configuring-user-agents-with-capybara-selenium-webdriver/这在capybara闹鬼中怎么可能? 最佳答案 请参阅poltergeistgithub页面上的链接:https://github.com/teampoltergeist/polte

  6. ruby - 如何配置 Ruby Mechanize 代理以通过 Charles Web 代理工作? - 2

    我正在使用Ruby/Mechanize编写一个“自动填写表格”应用程序。它几乎可以工作。我可以使用精彩CharlesWeb代理以查看服务器和我的Firefox浏览器之间的交换。现在我想使用Charles查看服务器和我的应用程序之间的交换。Charles在端口8888上代理。假设服务器位于https://my.host.com。.一件不起作用的事情是:@agent||=Mechanize.newdo|agent|agent.set_proxy("my.host.com",8888)end这会导致Net::HTTP::Persistent::Error:...lib/net/http/pe

  7. ruby - 可以正常中断的来自 Rake 的长时间运行的 shell 命令? - 2

    在几个项目中,我希望有一个类似rakeserver的rake任务,它将通过任何需要的方式开始为该应用程序提供服务。这是一个示例:task:serverdo%x{bundleexecrackup-p1234}end这行得通,但是当我准备停止它时,按Ctrl+c并没有正常关闭;它中断了Rake任务本身,它说rakeaborted!并给出堆栈跟踪。在某些情况下,我必须执行Ctrl+c两次。我可能可以用Signal.trap写一些东西来更优雅地中断它。有没有更简单的方法? 最佳答案 trap('SIGINT'){puts"Yourmessa

  8. ruby - 如何捕获所有 HTTP 流量(本地代理) - 2

    我希望访问我机器上的所有HTTP流量(我的Windows机器-不是服务器)。据我了解,拥有一个本地代理是所有流量路线的必经之路。我一直在谷歌搜索但未能找到任何资源(关于Ruby)来帮助我。非常感谢任何提示或链接。 最佳答案 WEBrick中有一个HTTP代理(Rubystdlib的一部分)和here's一个实现示例。如果你喜欢生活在边缘,还有em-proxy伊利亚·格里戈里克。这postIlya暗示它似乎确实需要一些调整来解决您的问题。 关于ruby-如何捕获所有HTTP流量(本地代理)

  9. ruby - ruby 中的同一个程序如何接受来自用户的输入以及命令行参数 - 2

    我的ruby​​脚本从命令行参数获取某些输入。它检查是否缺少任何命令行参数,然后提示用户输入。但是我无法使用gets从用户那里获得输入。示例代码:test.rbname=""ARGV.eachdo|a|ifa.include?('-n')name=aputs"Argument:#{a}"endendifname==""puts"entername:"name=getsputsnameend运行脚本:rubytest.rbraghav-k错误结果:test.rb:6:in`gets':Nosuchfileordirectory-raghav-k(Errno::ENOENT)fromtes

  10. ruby-on-rails - Rails 3,在RAILS_ROOT上方显示来自本地文件系统的jpg图片 - 2

    我正在尝试找出一种方法来显示来自不在RAILS_ROOT下(在RedHat或Ubuntu环境中)的已安装文件系统的图像。我不想使用符号链接(symboliclink),因为这个应用程序实际上是通过Tomcat部署的,而当我关闭Tomcat时,Tomcat会尝试跟随符号链接(symboliclink)并删除挂载中的所有图像。由于这些文件的数量和大小,将图像放在public/images下也不是一种选择。我查看了send_file,但它只会显示一张图片。我需要在一个格式良好的页面中显示6个请求的图像。由于膨胀,我宁愿不使用Base64编码,但我不知道如何将图像数据与呈现的页面一起传递下去。

随机推荐