如何避免nginx“上游发送过大的标题”错误?

时间:2010-02-21 19:52:53

标签: ruby-on-rails nginx passenger

我正在运行nginx,Phusion Passenger和Rails。

我遇到了以下错误:

upstream sent too big header while reading response header from upstream, client: 87.194.2.18, server: xyz.com, request: "POST /user_session HTTP/1.1", upstream: "passenger://unix:/tmp/passenger.3322/master/helper_server.sock

从对Facebook Connect的身份验证调用的回调中发生。

谷歌搜索后,尝试更改包含proxy_buffer_size和large_client_header_buffers的nginx设置无效。

我该如何调试?

6 个答案:

答案 0 :(得分:31)

最近遇到了这个错误。

Passenger 3.0.8开始,现在有一个设置允许您设置缓冲区和缓冲区大小。所以现在你可以做到

http {
    ...
    passenger_buffers 8 16k;
    passenger_buffer_size 32k;
}

这解决了我的问题。

答案 1 :(得分:28)

尝试将其添加到配置中:

http {
    ...
    proxy_buffers 8 16k;
    proxy_buffer_size 32k;
    }

答案 2 :(得分:24)

也许添加它会使它工作,你如何连接到上游? http,fastcgi还是别的什么?

http {
    ...
    fastcgi_buffers 8 16k;
    fastcgi_buffer_size 32k;
}

答案 3 :(得分:6)

fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;

答案 4 :(得分:1)

这是我在过去两年中对此错误所了解的一切:

upstream sent too big header while reading response header from upstream是nginx的通用方式,说“我不喜欢我所看到的”

  1. 您的上游服务器线程崩溃
  2. 上游服务器发回无效标头
  3. 从STDERR发回的通知/警告打破了他们的缓冲区,并且它和STDOUT都已关闭
  4. 3:查看消息上方的错误日志,是否在消息前面记录了行? PHP message: PHP Notice: Undefined index: 我的日志文件循环中的示例代码段:

    2015/11/23 10:30:02 [error] 32451#0: *580927 FastCGI sent in stderr: "PHP message: PHP Notice:  Undefined index: Firstname in /srv/www/classes/data_convert.php on line 1090
    PHP message: PHP Notice:  Undefined index: Lastname in /srv/www/classes/data_convert.php on line 1090
    ... // 20 lines of same
    PHP message: PHP Notice:  Undefined index: Firstname in /srv/www/classes/data_convert.php on line 1090
    PHP message: PHP Notice:  Undefined index: Lastname in /srv/www/classes/data_convert.php on line 1090
    PHP message: PHP Notice:
    2015/11/23 10:30:02 [error] 32451#0: *580927 FastCGI sent in stderr: "ta_convert.php on line 1090
    PHP message: PHP Notice:  Undefined index: Firstname
    

    你可以在第3行(从之前的20个错误中)看到缓冲区限制被击中,破坏,并且下一个线程在其中写入。 Nginx然后关闭连接并将502返回给客户端。

    2:记录每个请求发送的所有标头,检查它们并确保它们符合标准(nginx不允许任何超过24小时的内容删除/过期cookie,发送无效内容长度,因为错误消息在内容计算...)

    示例包括:

    <?php
    //expire cookie
    setcookie ( 'bookmark', '', strtotime('2012-01-01 00:00:00') );
    // nginx will refuse this header response, too far past to accept
    ....
    ?>
    

    和此:

    <?php
    header('Content-type: image/jpg');
    ?>
    
    <?php   //a space was injected into the output above this line
    header('Content-length: ' . filesize('image.jpg') );
    echo file_get_contents('image.jpg');
    // error! the response is now 1-byte longer than header!!
    ?>
    

    1:验证或制作脚本日志,以确保您的线程到达正确的终点并且在完成之前不退出。

答案 5 :(得分:0)

我以为我会使用我的解决方案,因为我没有看到它目前列出。结果我无意中将一个大对象放入会话中,如下所示。

session["devise.#{provider}_data"] = env["omniauth.auth"]

只有当某人首次使用GitHub OAuth进行身份验证并随后尝试使用另一个使用相同电子邮件的社交个人资料进行身份验证时才会发生这种情况(为什么我原本无法找到问题)。

以下是上下文参考的完整OmniauthCallbacksController

class OmniauthCallbacksController < Devise::OmniauthCallbacksController

  def self.provides_callback_for(provider)
    class_eval %Q{
      def #{provider}
        @user = User.from_omniauth(request.env["omniauth.auth"])
        if @user.persisted?
          sign_in_and_redirect @user, event: :authentication
          set_flash_message(:notice, :success, kind: "#{provider}".capitalize) if is_navigational_format?
        else
          auth = request.env["omniauth.auth"]
          if User.exists?(email: auth.info.email)
            set_flash_message(:notice, :failure, kind: "#{provider}".capitalize, reason: "email " + auth.info.email + " already exists") if is_navigational_format?
          else
            set_flash_message(:notice, :error, kind: "#{provider}".capitalize) if is_navigational_format?
          end
          session["devise.#{provider}_data"] = env["omniauth.auth"] <----- Remove this line
          redirect_to new_user_registration_path
        end
      end
    }
  end

  [:github, :linkedin, :google_oauth2].each do |provider|
    provides_callback_for provider
  end
end

一旦我删除违规行,一切都很顺利。我猜我在那里用于调试目的。