3

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

是否可以 ?

4

4 回答 4

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 }};
  }

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

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

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

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

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

于 2019-12-04T05:34:28.877 回答
0

看看这个问题和答案:

如何在 Ruby on Rails 中获取当前绝对 URL?

这应该是诀窍:

"#{request.protocol}#{request.host_with_port}#{request.fullpath}"
"#{request.protocol}#{request.host}:#{request.port+request.fullpath}"
于 2013-05-28T10:06:45.463 回答
0

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

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

于 2013-06-06T03:10:00.533 回答
0

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

于 2021-02-25T12:16:21.107 回答