{"id":24305813,"url":"https://github.com/880831ian/nginx-upstream-set-host-header","last_synced_at":"2026-05-30T22:32:08.124Z","repository":{"id":266407958,"uuid":"705453026","full_name":"880831ian/nginx-upstream-set-host-header","owner":"880831ian","description":"想使用 Nginx Upstream Proxy 到外部服務，並帶入對應的 header 該怎麼做？","archived":false,"fork":false,"pushed_at":"2023-10-16T04:11:07.000Z","size":329,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-09T05:06:54.142Z","etag":null,"topics":["nginx","upstream"],"latest_commit_sha":null,"homepage":"https://blog.pin-yi.me/nginx-upstream-set-host-header/","language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/880831ian.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-10-16T03:11:49.000Z","updated_at":"2023-10-16T04:12:24.000Z","dependencies_parsed_at":"2024-12-04T05:37:42.674Z","dependency_job_id":"0a0994cd-5350-47fe-b368-7ff500ce186c","html_url":"https://github.com/880831ian/nginx-upstream-set-host-header","commit_stats":null,"previous_names":["880831ian/nginx-upstream-set-host-header"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/880831ian/nginx-upstream-set-host-header","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/880831ian%2Fnginx-upstream-set-host-header","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/880831ian%2Fnginx-upstream-set-host-header/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/880831ian%2Fnginx-upstream-set-host-header/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/880831ian%2Fnginx-upstream-set-host-header/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/880831ian","download_url":"https://codeload.github.com/880831ian/nginx-upstream-set-host-header/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/880831ian%2Fnginx-upstream-set-host-header/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33712579,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-30T02:00:06.278Z","response_time":92,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["nginx","upstream"],"created_at":"2025-01-17T02:16:40.438Z","updated_at":"2026-05-30T22:32:08.101Z","avatar_url":"https://github.com/880831ian.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 想使用 Nginx Upstream Proxy 到外部服務，並帶入對應的 header 該怎麼做？\n\n此文章要來記錄一下最近在公司服務入口遇到的一些小問題，以及解決的方法。簡單說明一下，我們的服務入口是用 Nginx 來當作 proxy server，將不同路徑或是 servername 導到對應的後端程式，或是外部的服務上(例如 AWS cloudfront.net)，本篇要測試的是如果使用要同時使用 upstream 到外部服務，且需要帶 host header 該怎麼做。\n\n\u003cbr\u003e\n\n- Nginx 的 upstream 是什麼？\n\n通常我們 proxy_pass 的寫法會是這樣：\n\n```nginx\nlocation /aaa {\n    proxy_pass http://aaa.example.com;\n}\n```\n\n當 Nginx 收到的 request 是 `/aaa` 時，就會將 request 轉發到 `http://aaa.example.com`。\n\n\u003cbr\u003e\n\n但假如後端有多台機器或是服務，可以處理同一種 request，這時候就可以使用 upstream 來處理：\n\n```nginx\nupstream backend_hosts {\n  server aaa.example.com;\n  server bbb.example.com;\n  server ccc.example.com;\n}\n\nlocation /aaa {\n  proxy_pass http://backend_hosts;\n}\n\n```\n\n這樣子的好處是可以有多個機器或是後端服務可以分散請求，做到負載平衡的效果。\n\n\u003cbr\u003e\n\n## 問題\n\n那如果我們使用 Nginx upstream 時，還想要同時帶 host 的 header 到後端該怎麼做呢？我們先來看一下目前的寫法：\n\n( 測試範例是使用 docker 來模擬，可以參考程式碼 \u003e [點我前往 github](https://github.com/880831ian/nginx-upstream-set-host-header)，會有三個 nginx，其中一個是負責 proxy 的 nginx 名為 proxy，另外兩台是 upstream 後的服務，名為 upstream_server1、upstream_server2 )\n\n\u003cbr\u003e\n\n```nginx\n    upstream upstream_server {\n        server upstream_server1;\n        server upstream_server2;\n    }\n\n    server {\n        listen 80;\n        server_name localhost;\n\n        location /upstream_server/ {\n            proxy_pass http://upstream_server;\n            proxy_set_header Host \"upstream_server1\";\n            proxy_set_header Host \"upstream_server2\";\n            access_log /var/log/nginx/access.log upstream_log;\n        }\n    }\n}\n```\n\n\u003cbr\u003e\n\n可以看到我們希望 Nginx 收到 request 是 `/upstream_server` 時，將 request 轉發到 `http://upstream_server`，而 `upstream_server` 後面有兩個 server，並且在 proxy 時，帶入兩個不同的 host header。但如果真的這樣寫，可以達到我們想要得效果嗎？我們實際跑看看程式 (範例可以使用 nginx-old.conf)：\n\n\u003cbr\u003e\n\n![圖片](https://raw.githubusercontent.com/880831ian/nginx-upstream-set-host-header/master/images/1.png)\n\n\u003cbr\u003e\n\n從上面的 LOG 可以發現，我們 call `/upstream_server` 時，後端的 upstream_server1、upstream_server2 收到的 host 只會收到第一個設定的 Host，且服務會出現 400 Bad Request，查了一下網路文章，發現出現 400 Bad Request，可能跟 header 送太多資訊過去，詳細可以參考 [解決網站出現 400 Bad Request 狀態的方法](https://tools.wingzero.tw/article/sn/534)。\n\n這邊推測應該是後端如果也是用 nginx 直接接收才會遇到 400 的問題，還好目前公司服務還是正常的 xDD，檢查一下後發現，其實後端根本沒有要求對應 header 才能接收(應該是對方忘記加上此限制)。\n\n\u003cbr\u003e\n\n## 解決\n\n好，不管是否需要對應 header，我們還是找看看有沒有辦法同時使用 upstream，並帶入對應 host 的方法呢？\n\n最後參考網路上的文章，似乎只能使用兩層的 proxy，才能完成這兩個需求，我們來看看要怎麼寫吧 (範例可以使用 nginx.conf)：\n\n```nginx\n    server {\n        listen 777;\n        server_name localhost;\n\n        location / {\n            proxy_pass http://upstream_server1;\n            proxy_set_header Host \"upstream_server1\";\n            access_log /var/log/nginx/access.log upstream_log;\n        }\n    }\n\n    server {\n        listen 888;\n        server_name localhost;\n\n        location / {\n            proxy_pass http://upstream_server2;\n            proxy_set_header Host \"upstream_server2\";\n            access_log /var/log/nginx/access.log upstream_log;\n        }\n    }\n\n    upstream upstream_server {\n        server 127.0.0.1:777;\n        server 127.0.0.1:888;\n    }\n\n    server {\n        listen 80;\n        server_name localhost;\n\n        location /upstream_server/ {\n            proxy_pass http://upstream_server;\n            access_log /var/log/nginx/access.log upstream_log;\n        }\n    }\n```\n\n\u003cbr\u003e\n\n可以看到上面的程式碼，我們透過兩層的 proxy，來達到我們想要的效果，這樣子就可以同時使用 upstream，並且帶入對應的 host header。\n\n首先在 28 ~ 36 行，我們一樣如果 Nginx 收到 request 是 `/upstream_server` 時，會 proxy 到 upstream_server 這個 upstream 中，而 upstream_server 有兩個 server，分別是 `127.0.0.1:777`、`127.0.0.1:888`，但實際上沒有這兩個 port，所以我們需要再寫一層一般的 proxy 設定，分別是 1 ~ 10 行、12 ~ 21 行，這樣子就可以達到我們想要的效果。\n\n\u003cbr\u003e\n\n但這個方法比較適用於 upstream 後端沒有太多個服務或是機器的情況，如果有很多個服務或是機器，就需要寫很多的 proxy，這樣子會變得很麻煩，所以如果有更好的方法，也歡迎留言跟我分享 🤣。\n\n\u003cbr\u003e\n\n最後我們來看一下實際執行的結果：\n\n\u003cbr\u003e\n\n![圖片](https://raw.githubusercontent.com/880831ian/nginx-upstream-set-host-header/master/images/2.png)\n\n\u003cbr\u003e\n\n## 參考\n\n[Make nginx to pass hostname of the upstream when reverseproxying](https://serverfault.com/questions/598202/make-nginx-to-pass-hostname-of-the-upstream-when-reverseproxying)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F880831ian%2Fnginx-upstream-set-host-header","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F880831ian%2Fnginx-upstream-set-host-header","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F880831ian%2Fnginx-upstream-set-host-header/lists"}