当 Hunchentoot 在反向代理后面时如何重定向到 HTTPS

How to redirect to HTTPS when Hunchentoot is behind a reverse proxy

我在 http://localhost:4242 上有一个 Hunchentoot 应用程序 运行。此应用程序使用 non-SSL 接受器(即 hunchentoot:easy-acceptor 而不是 hunchentoot:easy-ssl-acceptor)。我将 Nginx 设置为反向代理以使用 SSL 为该应用程序提供服务。这是 Nginx 配置:

server {
    listen 443 ssl;
    server_name example.test;

    ssl_certificate /etc/my-ssl/certs/example.pem;
    ssl_certificate_key /etc/my-ssl/private/example.key;

    location / {
        include /etc/nginx/proxy_params;
        proxy_pass http://localhost:4242;
    }
}

其中 /etc/nginx/proxy_params

proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

问题是 Hunchentoot 不知道反向代理(即 Nginx)实际上是使用 HTTPS 服务客户端。因此,(hunchentoot:redirect "/some-page/") 将重定向到 http://example.test/some-page/ 而不是 https://example.test/some-page/。 Hunchentoot 没有考虑 X-Forwarded-Proto header.

为了解决这个问题,我写了一个替代的重定向函数,我用它来代替 #'hunchentoot:redirect:

(defun my-redirect (target
                    &rest args
                    &key (protocol
                           (if (string= (hunchentoot:header-in* :x-forwarded-proto)
                                        "https")
                             :https
                             :http))
                    &allow-other-keys)
  (apply #'hunchentoot:redirect target :protocol protocol args))

这是解决问题的正确方法吗?有没有更好的方法?

(Hunchentoot 1.3.0;SBCL 2.2.2;Nginx 1.18.0;Ubuntu 20.04)

编辑: 在 Hunchentoot 的问题跟踪器中:Incorrect redirection to HTTP when application is served using HTTPS reverse proxy

一个选项是继承 hunchentoot:easy-acceptor 并为您的接受器专门化 acceptor-ssl-p 方法。这将使您能够调用 hunchentoot:redirect 并在幕后进行协议决策。

(defclass my-easy-acceptor (hunchentoot:easy-acceptor)
  ())

(defmethod hunchentoot:acceptor-ssl-p ((acceptor my-easy-acceptor))
  (string= (hunchentoot:header-in* :x-forwarded-proto) "https"))

但是,在我看来(从 nginx 配置来看)您始终提供 HTTPS - 因此您可以省略逻辑并始终 return t.