food-market/deploy/nginx.conf
nns ba54155225
Some checks failed
CI / Backend (.NET 8) (push) Waiting to run
CI / Web (React + Vite) (push) Waiting to run
CI / POS (WPF, Windows) (push) Waiting to run
Docker API / Build + push API (push) Waiting to run
Docker API / Deploy API on stage (push) Blocked by required conditions
Docker Web / Build + push Web (push) Has been cancelled
Docker Web / Deploy Web on stage (push) Has been cancelled
fix(stage): rate-limit 5/min на /connect/token, nginx route /metrics+/swagger, Swagger в Production через IncludeSwagger
Verify-Sprint баги A-D:
- A: на stage docker-compose.yml был "RateLimiting__PerMinute=200" — убран,
  теперь работают дефолты (5/мин, 20/час). 6-я попытка с тем же IP/паролем → 429.
- B: web-контейнер nginx не имел location = /metrics → запрос ловился SPA
  fallback'ом (index.html, 947 байт). Добавлен proxy_pass на api:8080.
- C: web-nginx не имел location /swagger/ → swagger.json возвращал SPA HTML.
  Добавлены /swagger/ + редирект /swagger → /swagger/.
- D: Swagger подключался только в Development. Добавлен флаг IncludeSwagger
  (env IncludeSwagger=true) — Program.cs включает UseSwagger() и в Production
  если флаг выставлен. На prod admin.food-market.kz флаг не ставим.

Проверено через https://test.admin.food-market.kz:
- 6 неверных логинов подряд: 1-5 → 400, 6-7 → 429 ✓
- /metrics → 14967 байт prometheus exposition ✓
- /swagger/v1/swagger.json → 422 КБ openapi 3.0.1 ✓
- /swagger/ → swagger-ui (redirect на /swagger/index.html) ✓

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-04 01:36:42 +05:00

118 lines
4.8 KiB
Nginx Configuration File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

server {
listen 80 default_server;
root /usr/share/nginx/html;
index index.html;
# Long-running admin imports (MoySklad etc.) read from upstream for tens of
# minutes. Bump timeouts only on that path so normal API stays snappy.
location /api/admin/import/ {
proxy_pass http://api:8080;
proxy_http_version 1.1;
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-Forwarded-Proto $scheme;
proxy_read_timeout 60m;
proxy_send_timeout 60m;
proxy_request_buffering off;
proxy_buffering off;
}
# API reverse-proxy — upstream name "api" resolves in the compose network.
location /api/ {
proxy_pass http://api:8080;
proxy_http_version 1.1;
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-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /connect/ {
proxy_pass http://api:8080;
proxy_http_version 1.1;
proxy_set_header Host $host;
}
# SignalR хаб для live-уведомлений (см. NotificationsHub).
# WebSocket требует upgrade-хедеры и большой read_timeout (иначе nginx
# будет рвать idle-коннекшен каждые 60 сек). access_token приходит как
# query (?access_token=...), Authorization-хедер middleware на API его
# перекладывает в нужный вид до UseAuthentication.
location /hubs/ {
proxy_pass http://api:8080;
proxy_http_version 1.1;
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-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400; # 24h — webSocket долгоживущий
proxy_send_timeout 86400;
proxy_buffering off;
}
location /health {
proxy_pass http://api:8080;
}
# Prometheus метрики API. Без этого блока запрос ловится SPA fallback'ом и
# возвращает index.html (947 байт) вместо exposition format. На prod-домене
# имеет смысл закрыть IP-фильтром (allow 192.168.0.0/16; deny all;), на
# stage оставляем открытым — за gateway nginx уже есть auth/TLS-обвязка.
location = /metrics {
proxy_pass http://api:8080;
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-Forwarded-Proto $scheme;
}
# Swagger UI + OpenAPI-doc. На контейнере api подключается только когда
# IncludeSwagger=true (env-флаг, см. Program.cs). На prod-домене флаг не
# выставляем, /swagger вернёт 404 от api — это ожидаемо.
location /swagger/ {
proxy_pass http://api:8080;
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-Forwarded-Proto $scheme;
}
location = /swagger {
return 301 /swagger/;
}
# Статика изображений товаров — api раздаёт /uploads/... из volume.
location /uploads/ {
proxy_pass http://api:8080;
proxy_http_version 1.1;
proxy_set_header Host $host;
}
# PWA: SW и manifest должны отдаваться с правильным content-type и без
# кеша на самом ответе (внутри SW свой versioned cache). Иначе старый
# SW залипает на клиенте и не подхватывает обновления.
location = /sw.js {
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
expires off;
try_files /sw.js =404;
}
location = /manifest.webmanifest {
types { } default_type application/manifest+json;
add_header Cache-Control "public, max-age=3600";
try_files /manifest.webmanifest =404;
}
location = /offline.html {
try_files /offline.html =404;
}
# SPA fallback — all other routes return index.html
location / {
try_files $uri $uri/ /index.html;
}
}