【问题标题】:Is there a way to get client's actual port in a rails web application?有没有办法在 Rails Web 应用程序中获取客户端的实际端口?
【发布时间】:2013-05-22 21:32:15
【问题描述】:

我想在 Rails Web 应用程序中获取客户端的实际端口号(路由器提供给客户端计算机的端口)。

有可能吗?

【问题讨论】:

    标签: ruby-on-rails ruby apache2


    【解决方案1】:

    至少在 Rails 5.2+ 中,request.env["REMOTE_PORT"] 是空白的,所以我否决了另一个答案。

    经过一番挖掘,我设法获取此信息的方式是在 nginx 中设置自定义标头。

    你的 nginx 配置中可能有这样的东西:

    
    upstream {{ param_app_name }} {
      server unix:///var/www/{{ param_app_name }}/shared/tmp/sockets/puma-{{ param_app_name }}.sock;
    }
    
    ...
    
    
    location / {
        try_files $uri @app;
      }
    
      location @app {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Host $http_host;
        proxy_set_header X-Client-Request-Port $remote_port; # << -- Add this to your nginx conf
        proxy_redirect off;
        proxy_pass http://{{ param_app_name }};
      }
    

    如您所见,您可以在使用 proxy_pass 调用后端的同一服务器块中使用 proxy_set_header 将自定义标头从 nginx 传递到 Rails 后端。

    标题名称X-Client-Request-Port 是任意的,您可以选择任何您喜欢的名称,但有一个旧的约定是使用X-... 来自定义标题。

    在设置好这个并重新加载你的 nginx 之后,你可以在 Rails 中使用 request.headers["X-Client-Request-Port"] 访问这个值。

    顺便说一句,我假设您是出于记录目的而询问此问题。如果是这种情况,我建议您看一下 Lograge gem,它将使您的日志条目仅在每个请求中显示一行,从而减少 Rails 默认记录器在生产中的混乱。我按照 Ankane 的指南 here 进行了这样的配置:

    In ApplicationController:
    
    def append_info_to_payload(payload)
        super
    
        payload[:remote_ip] = request.remote_ip
        payload[:remote_port] = request.headers["X-Client-Request-Port"]
        payload[:user_id] = current_user.id     if current_user
        # You can add more custom stuff here, just whitelist it in production.rb below.
      end
    
    Then, in config/environments/production.rb:
    
    config.lograge.enabled = true
    
      config.lograge.custom_options = lambda do |event|
        options = event.payload.slice(
          :request_id,
          :user_id,
          :remote_ip,
          :remote_port,
        )
        options[:params] = event.payload[:params].except("controller", "action")
        options
      end
    
    

    【讨论】:

      【解决方案2】:

      看看这个问题和答案:

      How do I get the current absolute URL in Ruby on Rails?

      这应该是诀窍:

      "#{request.protocol}#{request.host_with_port}#{request.fullpath}"
      "#{request.protocol}#{request.host}:#{request.port+request.fullpath}"
      

      【讨论】:

      • 我正在寻找的是远程端口。这是客户端的端口号。不是我自己的服务器端口号。
      【解决方案3】:

      我一直在寻找类似request.remote_port 的东西,因为有request.remote_ip

      这就是我想出的request.env["REMOTE_PORT"]

      【讨论】:

      • 这对我不起作用。没有 env["REMOTE_PORT"] 变量。
      • 但是有request.env["REMOTE_PORT"]。我已经修改了答案。
      • 我试图检查 request.env["REMOTE_PORT"] 但它不存在(至少对于 Rails 4.2)
      【解决方案4】:

      在 Rails 6.1 上工作:request.headers['REMOTE_PORT'] 使用 nginx + 乘客

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-08-27
        • 2022-09-29
        • 2016-11-06
        • 2018-05-28
        • 2016-03-04
        • 1970-01-01
        • 2012-01-20
        • 1970-01-01
        相关资源
        最近更新 更多