Подкаталог обратного прокси-сервера Nginx переписывает для sourcegraph
Я пытаюсь, чтобы сервер исходного графа обслуживался в подкаталоге моего домена с использованием обратного прокси-сервера для добавления сертификата SSL.
Цель состоит в том, чтобы http://example.org/source обслуживал сервер sourcegraph.
Мои переписанные и обратные прокси выглядят так:
location /source {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Scheme $scheme;
rewrite ^/source/?(.*) /$1 break;
proxy_pass http://localhost:8108;
}
У меня проблема в том, что после вызова http://example.org/source меня перенаправляют на http://example.org/sign-in?returnTo=%2F
Есть ли способ переписать ответ sourcegraph в правильный подкаталог?
Кроме того, где я могу отладить директиву rewrite? Я хотел бы следить за изменениями, которые он делает, чтобы понять это лучше.
-- Редактировать:
Я знаю, что мой подход, вероятно, неправильно с использованием перезаписи, и я пытаюсь модуль sub_filter прямо сейчас.
Я захватил ответ sourcegraph с помощью tcpdump и проанализировал с помощью wireshark, поэтому я нахожусь на:
GET /sourcegraph/ HTTP/1.0
Host: 127.0.0.1:8108
Connection: close
Upgrade-Insecure-Requests: 1
DNT: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: https://example.org/
Accept-Encoding: gzip, deflate, br
Accept-Language: de,en-US;q=0.9,en;q=0.8
Cookie: sidebar_collapsed=false;
HTTP/1.0 302 Found
Cache-Control: no-cache, max-age=0
Content-Type: text/html; charset=utf-8
Location: /sign-in?returnTo=%2Fsourcegraph%2F
Strict-Transport-Security: max-age=31536000
Vary: Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-Trace: #tracer-not-enabled
X-Xss-Protection: 1; mode=block
Date: Sat, 07 Jul 2018 13:59:06 GMT
Content-Length: 58
<a href="/sign-in?returnTo=%2Fsourcegraph%2F">Found</a>.
1 ответ
Использование перезаписи здесь приводит к дополнительным издержкам обработки и совершенно не требуется.
proxy_pass
работает так:
proxy_pass
к голому URL, т.е. вообще ничего после домена /ip/ порта и полного клиентского запроса uri добавляется в конец и передается прокси.
Добавьте что угодно, даже косую черту proxy_pass
и все, что вы добавляете, заменяет ту часть URI запроса клиента, которая соответствует URI этого блока местоположения.
так что если вы хотите потерять исходную часть вашего клиентского запроса, она должна выглядеть так:
location /source/ {
proxy_pass http://localhost:8108/;
.....
}
Теперь запросы будут проксироваться так:
example.com/source/
-> localhost:8108/
example.com/source/files/file.txt
-> localhost:8108/files/file.txt
Важно отметить, что Nginx не просто /source/
из запроса, он заменяет весь мой proxy_pass
Ури, это не так ясно, когда это просто косая черта, поэтому лучше проиллюстрировать, если мы изменим proxy_pass
к этому:
proxy_pass http://localhost:8108/graph/;
тогда запросы теперь обрабатываются так:
example.com/source/
-> localhost:8108/graph/
example.com/source/files/file.txt
-> localhost:8108/graph/files/file.txt
Если вам интересно, что haooens, если кто-то просит example.com/source
это работает, если вы не установили merge_slashes
директива off, так как Nginx добавит завершающие / к прокси-запросам.
Если у вас есть Nginx перед другим веб-сервером, работающим на порту 8108, и обслуживающий его контент proxy_pass
всего из подкаталога, например /subdir
, тогда у вас может возникнуть проблема, связанная с тем, что служба на порту 8108 обслуживает HTML-страницу, которая включает ресурсы, вызывает собственные API-интерфейсы и т. д. на основе абсолютных URL-адресов. Эти вызовы будут опускать/subdir
префикс, поэтому они не будут перенаправлены на службу на порт 8108 с помощью nginx.
Одно из решений - заставить веб-сервер на порту 8108 обслуживать HTML, который включает базовый атрибут href, например
<head>
<base href="https://example.com/subdir">
</head>
который сообщает клиенту, что все ссылки относятся к этому пути (см. https://www.w3schools.com/tags/att_base_href.asp)
Иногда это не вариант - возможно, вы просто запускаете веб-сервер, предоставляемый внешним образом докера, или, может быть, вы просто не видите причину, по которой вам нужно вмешиваться в службу, которая отлично работает как автономная. Решение, которое требует изменений только в nginx впереди, - это использоватьReferer
заголовок, чтобы определить, был ли запрос инициирован ресурсом, расположенным в /subdir
. Если это так, вы можете переписать запрос с префиксом/subdir
а затем перенаправить клиента в это место:
location / {
if ($http_referer = "https://example.com/subdir/") {
rewrite ^/(.*) https://example.com/subdir/$1 redirect;
}
...
}
location /subdir/ {
proxy_pass http://localhost:8108/;
}
Или что-то вроде этого, если вы предпочитаете регулярное выражение, позволяющее опускать имя хоста:
if ($http_referer ~ "^https?://[^/]+/subdir/") {
rewrite ^/(.*) https://$http_host/subdir/$1 redirect;
}