我目前在尝试使用 Apache 作为我们应用程序前端和后端 API 的反向代理时遇到问题。
例如,如果用户点击 URL,https://my.app.com/
他们将被带到我们由 S3 提供的前端应用程序。如果您点击 URL,https://my.app.com/api/hello
您将收到来自我们后端 API 的 JSON 响应。
理想的行为是https://my.app.com/
反向代理http://s3app.private
。
同样,我们希望https://my.app.com/api/hello
反向代理http://myapi.private/api/hello
我们当前的 apache 配置如下所示:
Listen 443
<VirtualHost *:443>
ServerName my.app.com
ErrorDocument 404 /index.html
ProxyErrorOverride On
RequestHeader set X-Forwarded-Proto https
SSLEngine on
SSLCertificateFile "/usr/local/apache2/certs/certificate.crt"
SSLCertificateKeyFile "/usr/local/apache2/certs/private.key"
SSLProtocol TLSv1.2
ProxyAddHeaders On
<Location "/">
ProxyPass "http://s3app.private/" retry=0
</Location>
<Location "/api">
ProxyPreserveHost On
ProxyPass "http://myapi.private/api" retry=0
</Location>
</VirtualHost>
当前的行为是,当我们点击时,https://my.app.com/
我们会看到我们的前端应用程序。然而,当我们点击时,https://my.app.com/api/hello
我们会收到503
来自服务器的错误。
Apache 的日志显示以下几行:
[proxy:error] The timeout specified has expired: AH00957: HTTP: attempt to connect to <internal_ip>:80 (api.private) failed
[proxy_http:error] AH01114: HTTP: failed to make connection to backend: myapi.private, referer: https://my.app.com/
"GET /api/hello HTTP/1.1" 503 299
我们已经验证了我们的 API 确实正在通过这种机制进行监听,方法是将 Apache 单独指向 API,如下所示:
Listen 443
<VirtualHost *:443>
ServerName my.app.com
ErrorDocument 404 /index.html
ProxyErrorOverride On
RequestHeader set X-Forwarded-Proto https
SSLEngine on
SSLCertificateFile "/usr/local/apache2/certs/certificate.crt"
SSLCertificateKeyFile "/usr/local/apache2/certs/private.key"
SSLProtocol TLSv1.2
ProxyAddHeaders On
<Location "/api">
ProxyPreserveHost On
ProxyPass "http://myapi.private/api" retry=0
</Location>
</VirtualHost>
这样我们就可以点击https://my.app.com/api/hello
并查看预期的 JSON 响应。但这仅在没有其他位置块存在时才会成功。
值得一提的是,我们的内部 DNS 由 Route53 提供,我们的 API 托管在 ECS 中。
非常感谢您的帮助!
答案1
使用两个虚拟主机可能会有所帮助,但可能不是最理想的解决方案。
Listen 443
<VirtualHost *:443>
ServerName my.app.com
ErrorDocument 404 /index.html
ProxyErrorOverride On
RequestHeader set X-Forwarded-Proto https
SSLEngine on
SSLCertificateFile "/usr/local/apache2/certs/certificate.crt"
SSLCertificateKeyFile "/usr/local/apache2/certs/private.key"
SSLProtocol TLSv1.2
ProxyAddHeaders On
<Location "/">
ProxyPass "http://s3app.private/" retry=0
</Location>
<Location "/api">
ProxyPreserveHost On
ProxyPass "http://localhost:8443/api" retry=0
</Location>
</VirtualHost>
Listen 8443
<VirtualHost *:8443>
ServerName localhost
<Location "/api">
ProxyPreserveHost On
ProxyPass "http://myapi.private/api" retry=0
</Location>
</VirtualHost>
我不知道从技术角度上为什么这能解决你的问题,但也许值得一试。