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
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>
118 lines
4.8 KiB
Nginx Configuration File
118 lines
4.8 KiB
Nginx Configuration File
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;
|
||
}
|
||
}
|