Эта статья синхронизирована в личном блогеshymean.comвверх, добро пожаловать, чтобы следовать
В этой статье разбирается метод использования nginx для перезаписи uri и прокси-функций при фронтенд-разработке в среде разработки.
Ссылаться на
- китайская документация nginx
- Необходимые знания Nginx для фронтенд-разработчиков
- Nginx и фронтенд разработка
совпадение местоположения
Ссылаться на
Когда несколько проектов используют одно и то же доменное имя, часто необходимо перенаправлять запросы в разные проекты в соответствии с URL-адресом.В этом случае необходимо настроить местоположение.
location [ = | ~ | ~* | ^~ ] uri { ... }
Между директивой местоположения и запросом uri можно добавить необязательные модификаторы. Значения четырех модификаторов следующие:
-
= означает точное совпадение. Он сработает только в том случае, если запрошенный URL-адрес точно равен следующей строке.
-
~ Указывает, что правило определено с использованием регулярных выражений и учитывает регистр.
-
~* Указывает, что правило определено с использованием регулярного выражения и не чувствительно к регистру.
-
^~ означает, что если символ, следующий за символом, является наиболее подходящим, правило применяется, и последующие поиски не выполняются.
Если модификатор не добавлен, путь к ресурсу запроса и настроенный uri используются длясовпадение префикса: если путь к ресурсу запроса начинается с настроенного uri, это означает, что правило может быть выполнено.
Следует отметить, что одни и те же правила сопоставления uri не могут существовать одновременно, т.е.
location /img/ {}
location ^~ /img/ {}
будет отображаться ошибка
nginx: [emerg] duplicate location "/img/" in /usr/local/etc/nginx/servers/test.conf:61
Обратите внимание, что uri со слэшем в конце и без слэша будут расцениваться как два совпадающих правила, и их обработка также отличается, что также упоминается в следующем примере (цитируется вышестатьяОписание в этом пункте кажется неверным).
Конкретный процесс сопоставления местоположения
- Сначала проверьте неизмененные правила и выполните сопоставление префиксов, выберите самый длинный совпадающий элемент и запишите его.
- Затем проверьте, есть ли точное совпадение местоположения (с модификатором =), если да, завершите поиск и используйте его конфигурацию.
- Затем узнайте, есть ли оптимальное совпадение, если да, выберите элемент с самым длинным результатом оптимального совпадения и используйте его конфигурацию.
- потомчтобыНайдите местоположение, определенное модификатором Regular, если оно совпадает, остановите поиск и используйте определенную им конфигурацию.
- Наконец, если нет подходящего регулярного местоположения, используется самое длинное совпадающее местоположение символа префикса, записанное ранее.
Как видно из приведенного выше процесса сопоставления, порядок сопоставления следующий:
Точное совпадение > Лучшее соответствие > Обычное регулярное совпадение по порядку > Самое длинное совпадение префикса
Далее мы напишем несколько тестов для отработки локации, которая примерно выглядит так
# uri表示location的需要匹配的规则
location uri {
# config表示某个config配置
[ config ]
}
Чтобы проверить вопрос «Какое правило сопоставления местоположения действует при наличии нескольких местоположений», мы можем перенаправить запрос в несуществующий файл, а затем использовать журнал ошибок для проверки местоположения, соответствующего запросу.
Теперь приступим к практическому тесту
server {
listen 80;
server_name test.com;
index index.html;
error_log /usr/local/etc/nginx/logs/error.log error;
location / {
root /Users/Txm/A/;
}
location /img {
root /Users/Txm/B/;
}
location /img/ {
root /Users/Txm/C/;
}
}
Затем я подготовил несколько ссылок для запросов. Посетив и просмотрев журналы, вы можете узнать, куда ушел запрос.
URL-адрес запроса | правила сопоставления | Примечание |
---|---|---|
test.com/s/img/1.png | A | Только/соответствует правилам сопоставления префиксов |
test.com/IMG212/1 С вами… | B | Только /img соответствует префиксу, /img/ не соответствует |
test.com/img/1/1.png | C | Есть разница между /img/ и /img с / в конце |
test.com/img/1.png | C | Префикс /img/ соответствует большему количеству слов, чем /img |
Затем проверьте регулярное сопоставление и добавьте следующую конфигурацию местоположения в серверный модуль выше.
location ~* /im {
root /Users/Txm/D/;
}
location ~* \.png {
root /Users/Txm/E/;
}
посетите сейчас/img212/1.png
,/img/1/1.png
а также/img/1.png
Эти три ссылки повлияют на правило D, такое как правило сопоставления выше:
- Обычное сопоставление имеет приоритет над соответствием префикса, поэтому правило ABC не будет сопоставлено.
- Обычное совпадение сопоставляется в соответствии с заданным порядком.Если оно совпадает, поиск останавливается, поэтому, хотя правило E также соответствует правилу, оно не срабатывает.
мы продолжаем тестировать^~
лучший матч
location ~ /bund {
root /Users/Txm/F/;
}
location ~ /bundle/1 {
root /Users/Txm/F1/;
}
location ^~ /bundl {
root /Users/Txm/G/;
}
location ^~ /bundle/ {
root /Users/Txm/G1/;
}
location ~ \.js$ {
root /Users/Txm/H/;
}
мы используемhttp://test.com/bundle/1.js
Эта ссылка используется для тестирования.Теоретически эта ссылка соответствует всем вышеперечисленным правилам.На самом деле запрос попадает в правила.G1
, я так понимаю:
- лучший матчимеет приоритет над обычным сопоставлением
- При наличии нескольких правил оптимального соответствия выберите правило с наибольшей длиной соответствия.
Следовательно, здесь происходит попадание в G1. Если G1 удаляется, G следует сопоставлять в соответствии с приоритетом, а G следует продолжать удалять. В это время состояние возвращается к указанному выше регулярному сопоставлению. Согласно правилам регулярного сопоставления в порядок, F должен соответствовать в это время.
Наконец, давайте проверим точное совпадение. Точное совпадение означает, что запрошенный путь должен точно совпадать с настроенным uri.
location = /img {
root /Users/Txm/I/;
}
URL-адрес запроса | правила сопоставления | Примечание |
---|---|---|
test.com/img | I | Точное совпадение имеет наивысший приоритет |
test.com/img/ | D | Точное паросочетание и оптимальное паросочетание не выполняются, но выполняется регулярное паросочетание D, чтобы |
корень и псевдоним
Ссылаться на
Синтаксис и правила сопоставления местоположения разобраны выше, но местоположение не меняет запрошенный uri, фактически запрошенный путь к файлу обрабатывается другими инструкциями.
Для указания пути к файлу можно использовать как root, так и псевдоним.Основное различие между ними заключается в том, как nginx интерпретирует uri за местоположением, что приводит к тому, что они по-разному сопоставляют запросы с файлами сервера.
- Метод обработки root: корневой путь + путь к местоположению
- Как работать с псевдонимом: замените путь местоположения на путь псевдонима
кhttp://test.com/test/index.html
Запрос, например,
server_name test.com;
location /test/ {
# 当配置为root时,实际请求的Users/Txm/nginx_test/test/index.html
# root可以放在 http、server、location、if等多个配置段下面
# root /Users/Txm/nginx_test/;
# 当配置为alias时,实际请求的是/Users/Txm/nginx_test/index.html
# alias只能放在location中
# 注意alias末尾必须跟/
alias /Users/Txm/nginx_test/;
}
Другими словами, псевдоним — это определение псевдонима каталога, а корень — это определение каталога верхнего уровня.
В сочетании с местоположением, корнем или псевдонимом можно использовать для сопоставления запрошенного URL-адреса с соответствующим реальным каталогом на диске. Но в какой-то момент недостаточно просто иметь каталог без реального файла (самый распространенный сценарий, вероятно, заключается в том, что среда разработки не генерирует кэшированное значение хэша имени файла среды и.min.
суффикс), вы можете пройтиrewrite
Перепишите путь URI запроса.
rewrite
Ссылаться на
rewrite
Модуль позволяет регулярно изменять URI запроса, инициировать внутренний переход, а затем сопоставлять местоположение или напрямую выполнять 30-кратное перенаправление для возврата к клиенту.
rewrite regex replacement [flag]
Регулярное выражение является обычным в стиле PCRE, а действующие правила перезаписи следующие:
- Если регулярное выражение совпадает с uri текущего запроса, замена будет рассматриваться как новый uri для последующей обработки.
- Если эти параметры установлены на уровне сервера, они вступят в силу до местоположения.
- Если в новых символах URI есть что-то о протоколе, например http:// или https:// и т. д., прекратите обработку и ответьте напрямую с помощью 302.
- Если существует несколько правил перезаписи, которые могут соответствовать uri в одном и том же контексте (сервер, местоположение, если), перезапись и замена будут выполняться непрерывно в соответствии с порядком, в котором появляются инструкции перезаписи, а замененная замена будет использоваться как новый uri для участия в последующих действиях.
- Если вы хотите прервать матч, вы можете использовать флаг третьего параметра, значение которого выглядит следующим образом:
-
last
Указывает на прекращение обработки любых инструкций, связанных с перезаписью, и запуск следующего раунда сопоставления местоположения с замененным uri. -
break
Указывает, что прекращает обработку любых инструкций, связанных с перезаписью, и напрямую использует uri для обработки запросов без сопоставления местоположения. -
redirect
Если он не содержит протокола и является новым uri, для обработки запроса будет использоваться местоположение, соответствующее новому uri, и 30-кратный переход не будет выполнен; однако он также может напрямую вернуть 30x и позволить браузеру перенаправить запрос сам по себе -
permanent
а такжеredirect
То же самое, разница в том, что он напрямую возвращает 301 постоянный редирект
-
должен быть в курсеlast
а такжеbreak
Если вы используете местоположение в местоположении, перенаправление будет повторно инициализировано с новым URI, и сопоставление местоположения будет выполнено снова. Если и новый uri, и старый uri снова совпадают с одним и тем же местоположением, возникнет бесконечный цикл. , когда этот цикл превышает 10 раз, nginx вернет 500. Так что имейте в виду:Использовать последний в контексте сервера и разорвать в контексте местоположения.
Далее давайте проверим правила перезаписи на нескольких примерах.
server {
listen 80;
server_name test2.com;
index index.html;
root /Users/Txm/nginx_test/;
access_log /usr/local/etc/nginx/logs/test2.access.log;
error_log /usr/local/etc/nginx/logs/error2.log error;
rewrite ^/baidu http://www.baidu.com;
rewrite ^/bai http://image.baidu.com;
return 403;
}
URL-адрес запроса | Окончательный переписать uri | Примечание |
---|---|---|
test2.com/bai | image.baidu.com | |
test2.com/baidu | www.baidu.com | Если он соответствует baidu, он вернется напрямую |
затем добавьте местоположение |
location /bundle/ {
rewrite ^/bundle/(.*?)$ /dist/$1 break;
}
location /dist/ {
rewrite ^/dist/(.*?)$ /src/$1 break;
}
URL-адрес запроса | Окончательный переписать uri | Примечание |
---|---|---|
test2.com/bundle/1.js | /Users/Txm/nginx_test/dist/1.js | break больше не выполняет сопоставление местоположения |
test2.com/dist/1.js | /Users/Txm/nginx_test/src/1.js |
потом/bundle/
идентификатор внутриbreak
превратиться вlast
,
location /bundle/ {
rewrite ^/bundle/(.*?)$ /dist/$1 break;
}
Затем вы можете увидеть окончательный uri и/dist/
то же самое, переписанное как/Users/Txm/nginx_test/src/1.js
, так что не забудьте использовать в местоположенииbreak
предупреждение.
С помощью перезаписи мы можем переписать путь и изменить некоторые несуществующие файлы на файлы, реально существующие на диске..min
суффикс и-hash
Правила перезаписи суффиксов, которые можно использовать в элементах историиgrunt
Упакованные статические ресурсы сопоставляются с соответствующими исходными файлами src.
rewrite ^(.*?)((\.min)?\-.*?)(\..*?)$ $1$4 last;
Некоторое использование прокси nginx
Обратный прокси-сервер обслуживает сторону сервера.Обратный прокси-сервер может помочь серверу получать запросы от клиента, помогать серверу выполнять переадресацию запросов, балансировку нагрузки и т. д.
Обратный прокси прозрачен для сервера и непрозрачен для нас, то есть мы не знаем, что обращаемся к прокси-серверу, а сервер знает, что его обслуживает обратный прокси.
Форвард прокси для нас, то есть для клиента.Клиент может получить доступ к ресурсам сервера, к которым он не может получить доступ по форвард прокси.Сценарий применения такой: предположим, что локальная сеть компании не разрешает доступ к внешней сети , Если клиенты в локальной сети хотят получить доступ в Интернет, им необходимо получить доступ через прокси-сервер.
Форвард-прокси прозрачен для нас и непрозрачен для сервера, то есть сервер не знает, получает ли он доступ с прокси или с реального клиента.
Ниже приведены некоторые функциональные сценарии, которые можно реализовать с помощью прокси-сервера nginx во фронтенд-разработке.
Моделирование сценариев онлайн-запросов в локальной среде разработки
Среду выполнения кода можно разделить на локальную среду разработки, тестовую среду и производственную онлайн-среду. В качестве примера возьмем веб-проект в существующем процессе разработки:
- При разработке это номер порта 3015, запускаемый локально.
- Во время теста тестовая платформа извлекает связанные сервисы в соответствии с порядком работы, развертывает их в контейнере через k8s и запускает сервис и, наконец, вводит серию списков хостов.
- Когда рабочее задание может быть подключено к сети, объедините код для разработки и освоения с помощью платформы выпуска, а затем разверните его на рабочем сервере в соответствии с шагами команды.
Предположим, что ссылка для доступа к сервисуhttp://m.xxx.com/h5/test
Чтобы добиться одинакового сценария доступа в трех средах, как правило, необходимо выполнить следующую обработку:
нужноДоступ к производственной среде, вы можете напрямую ввести текущую ссылку в браузере.Имя онлайн-домена обычно будет заранее разрешено к ip на соответствующем сервере.По умолчанию имя домена вводится для доступа к службам производственной среды.
Тестовую среду можно понимать как зеркало производственной среды, и приложение также развернуто на сервере.Доступ к тестовой среде, нам нужно указать доменное имя на ip адрес тестового сервера
При локальной разработке, если вам нужно получить к ней доступ через доменное имялокальная среда разработки, вы можете изменить хост, а затем проксировать запрос доменного имени на службу локального узла.
127.0.0.1 xxx.com
Затем измените конфигурацию nginx через nginxxxx.com
Запрос доменного имени проксируется на номер порта локальной службы
server {
listen 80;
server_name m.xxx.com;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_pass http://127.0.0.1:3015;
}
}
Вот очень простой в использовании инструмент модификации хоста:SwitchHosts, вы можете легко переключать доменные имена в локальной, тестовой и производственной среде.
Сопоставьте файлы ресурсов онлайн-запросов с локальными
Поскольку статические ресурсы в производственной среде, такие как таблицы стилей и файлы JavaScript, обычно сжимаются и упаковываются, к имени файла даже добавляется суффикс хеш для управления кешем.Если вам нужно отладить онлайн-код в какой-то момент, есть вообще два пути
Первый способ — передать запрошенный файл через инструмент захвата пакетов, такой как charlesMap LocalМетод сопоставляется с локальным диском.В это время запрошенный ресурс фактически возвращает локальный файл, и тогда цель отладки может быть достигнута путем изменения локального файла. Этот метод подходит для файлов, которые не подвергались слиянию и упаковке кода, и полезен для поддержки некоторых старых проектов, в которых для загрузки файлов используются инструменты управления модулями, такие как requirejs и seajs.
Второй — настроить доменное имя статического ресурса на локальное, а затем передать nginxlocation
,alias
а такжеrewrite
Реализовать прокси-сервер статических ресурсов
server {
listen 80;
server_name cnd.shymean.com;
location /wargame/ {
alias /Users/Txm/github/wargame/dist/;
# 移除请求如jquery.min-a2dfg.js链接上的hash值a2dfg
# http://cnd.shymean.com/wargame/jquery.min-a2dfg.js 实际返回文件为 /Users/Txm/github/wargame/dist/jquery.min.js
rewrite ^(.+)/(.+)[-.]\w+\.(\w+)$ $1/$2.$3 last;
}
location /blog/ {
# 直接映射到本地目录
alias /Users/Txm/blog/public/;
}
}
междоменная конфигурация nginx
Классический сценарий прямого прокси-сервера:Используйте nginx для обхода междоменных ограничений браузера, в процессе разработки и отладки с разделением интерфейса и сервера локальная функция интерфейса может бытьlocalhost:port
В виде доменных имен для разработки обычно используются локальные мок-данные.Если вам потребуется прямой доступ к удаленному интерфейсу для совместной отладки, вы столкнетесь с междоменными проблемами.
Этот сценарий в основном вызван несоответствием между доменным именем страницы (localhost) и доменным именем интерфейса (api.xxx.com) во время разработки.Через местоположение и proxy_pass nginx указанный запрос проксируется соответствующему поставщику услуг. С точки зрения браузера все запросы относятся к одному и тому же доменному имени, поэтому ограничений между доменами нет.
server {
listen 80;
server_name shymean.com;
location /api/ {
# 局域网中后台开发的本地服务,用于联调
proxy_pass http://192.168.132.253:7654;
}
}
Другой сценарий: в целях оптимизации производительности некоторые статические ресурсы часто используют отдельное доменное имя cdn, когда бизнесу необходимо использовать междоменные ресурсы (например, рисование сетевых изображений на холсте, вам нужно вызватьcanvas.toDataURL
), в это время также будут междоменные ограничения через nginxadd_header
Функции могут очень просто реализовать CORS.
# 静态资源
map $http_origin $imgCorsHost {
default 0;
"~http://shymean.com" http://shymean.com;
"~https://shymean.com" https://shymean.com;
}
server {
listen 80;
listen 443;
server_name cdn.shymean.com;
root /Users/Txm/Desktop/blog/static;
add_header Access-Control-Allow-Origin $imgCorsHost;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
if ($request_method = 'OPTIONS') {
return 204;
}
}
Как видно из приведенного выше примера, если вам нужно указатьAccess-Control-Allow-Origin
Для нескольких доменных имен можно использовать структуру карты nginx.
Изменить содержимое ответа через nginx
Иногда есть некоторые логики, которые действуют только в среде разработки, такие как введение фиктивного кода, добавление инструментов отладки eruda на мобильные страницы и т. д.
При локальной разработке вы можете определить, является ли это рабочей средой, указав переменную среды как разработку во время выполнения, чтобы изменить содержимое ответа.
<% if(!app.isProduction()) { %>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Mock.js/1.0.1-beta3/mock-min.js"></script>
<%- IncludeAssets('start:statics/h5/act/js/_mock.js') %>
<script>
window.isMockReuquest = true
</script>
<% } %>
В приведенном выше методе к коду добавляется дополнительный код оценки среды, а затем вводится фиктивный код.Путем перехвата и изменения содержимого ответа через nginx эта функция также может быть достигнута. Когда я впервые осознал это требование, я потратил много времени на поиск соответствующих методов реализации и обнаружил, что самый простой способ — черезopenresty
реализовать. Ссылаться на:
location ~* 1.js$ {
body_filter_by_lua_file /usr/local/etc/openresty/lua/hello.lua;
}
затем добавьтеhello.lua
Скрипт, напишите соответствующую логику
-- body_filter_by_lua, body filter模块,ngx.arg[1]代表输入的chunk,ngx.arg[2]代表当前chunk是否为last
local chunk, eof = ngx.arg[1], ngx.arg[2]
local buffered = ngx.ctx.buffered
if not buffered then
buffered = {} -- XXX we can use table.new here
ngx.ctx.buffered = buffered
end
if chunk ~= "" then
buffered[#buffered + 1] = chunk
ngx.arg[1] = nil
end
if eof then
local whole = table.concat(buffered)
ngx.ctx.buffered = nil
whole = string.gsub(whole, "console.log", "console.warn")
ngx.arg[1] = whole
end
Следует отметить, что модифицированныйwhole
Длина содержимого не может превышать длину исходного содержимого, иначе будут перехвачены следующие данные.content-length
связанные с головой. оopenresty
а такжеlua
, у меня не было большого контакта с ним раньше, и я продолжу его углубленное изучение позже.
резюме
В этой статье обобщаются несколько директив, связанных с nginx, сопоставляющих uri, в том числе
- использовать
location
соответствовать ури - использовать
root
а такжеalias
Укажите каталог ресурсов запроса - использовать
rewrite
Переписать uri и последующие правила сопоставления
Комбинируя uri и proxy, мы можем направить запрос к ресурсам, которые нам нужны для удовлетворения различных потребностей разработки в среде разработки.