docs(article): добавлен раздел про base href и deploy-url для /ui/simple и рекомендации по SPA-фоллбэку
This commit is contained in:
@@ -7,7 +7,7 @@ date: 2025-09-10 18:00
|
|||||||
author: Direct-Dev (aka Антон Кузнецов)
|
author: Direct-Dev (aka Антон Кузнецов)
|
||||||
level: Средний
|
level: Средний
|
||||||
tags: #go #angular #spa #embed #static #cli #webui #devops
|
tags: #go #angular #spa #embed #static #cli #webui #devops
|
||||||
version: 1.0.1
|
version: 1.0.2
|
||||||
```
|
```
|
||||||
|
|
||||||
## Содержание
|
## Содержание
|
||||||
@@ -23,6 +23,7 @@ version: 1.0.1
|
|||||||
- [Встраивание в Go-сервис](#встраивание-в-go-сервис)
|
- [Встраивание в Go-сервис](#встраивание-в-go-сервис)
|
||||||
- [API: контракт и примеры](#api-контракт-и-примеры)
|
- [API: контракт и примеры](#api-контракт-и-примеры)
|
||||||
- [Запуск и проверка](#запуск-и-проверка)
|
- [Запуск и проверка](#запуск-и-проверка)
|
||||||
|
- [SPA под произвольным префиксом (/ui/simple): base href и deploy-url](#spa-под-произвольным-префиксом-uisimple-base-href-и-deploy-url)
|
||||||
- [FAQ и типичные ошибки](#faq-и-типичные-ошибки)
|
- [FAQ и типичные ошибки](#faq-и-типичные-ошибки)
|
||||||
|
|
||||||
## Введение
|
## Введение
|
||||||
@@ -133,13 +134,13 @@ knock-gui/
|
|||||||
|
|
||||||
## Минимальный GUI
|
## Минимальный GUI
|
||||||
|
|
||||||
Оставили только то, что реально нужно для «пнул порт — и поехали». Поля формы и кнопка запуска — никаких лишних переключателей.
|
Оставил только то, что реально нужно для «пнул порты». В main полный интерфейс ...
|
||||||
|
|
||||||
Ключевой шаблон компонента:
|
Ключевой шаблон компонента:
|
||||||
|
|
||||||
```12:60:/home/su/projects/articles/embed-gui-article/ui/src/app/knock/knock-page.component.html
|
```12:60:/home/su/projects/articles/embed-gui-article/ui/src/app/knock/knock-page.component.html
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<p-card header="Port Knocker (Минимальный UI)">
|
<p-card header="Port Knocker (Minimal UI)">
|
||||||
<form [formGroup]="form" (ngSubmit)="execute()" class="p-fluid">
|
<form [formGroup]="form" (ngSubmit)="execute()" class="p-fluid">
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
@@ -163,7 +164,7 @@ knock-gui/
|
|||||||
</div>
|
</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
Логика отправки запроса — проста как три рубля:
|
Логика отправки запроса:
|
||||||
|
|
||||||
```1:40:/home/su/projects/articles/embed-gui-article/ui/src/app/knock/knock-page.component.ts
|
```1:40:/home/su/projects/articles/embed-gui-article/ui/src/app/knock/knock-page.component.ts
|
||||||
this.http.post('/api/v1/knock-actions/execute', {
|
this.http.post('/api/v1/knock-actions/execute', {
|
||||||
@@ -173,6 +174,8 @@ this.http.post('/api/v1/knock-actions/execute', {
|
|||||||
}).subscribe(...)
|
}).subscribe(...)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> ну да, ну да надо сервис и все такое ...
|
||||||
|
|
||||||
Так как страницы GUI защищены Basic‑Auth, браузер после ввода пароля сам будет добавлять заголовок Authorization и к XHR‑запросам — отдельно в коде его прокидывать не нужно.
|
Так как страницы GUI защищены Basic‑Auth, браузер после ввода пароля сам будет добавлять заголовок Authorization и к XHR‑запросам — отдельно в коде его прокидывать не нужно.
|
||||||
|
|
||||||
## Сборка фронтенда
|
## Сборка фронтенда
|
||||||
@@ -268,6 +271,59 @@ http://localhost:8888
|
|||||||
|
|
||||||
Если что-то не так — загляните в логи терминала и сетевую вкладку DevTools.
|
Если что-то не так — загляните в логи терминала и сетевую вкладку DevTools.
|
||||||
|
|
||||||
|
## SPA под произвольным префиксом (/ui/simple): base href и deploy-url
|
||||||
|
|
||||||
|
Иногда нужно отдавать SPA не с корня `/`, а, скажем, по пути `/ui/simple`. Для Angular это значит две вещи: правильный `<base href>` в `index.html` и корректные пути к ассетам.
|
||||||
|
|
||||||
|
Вариант A: собрать с заданным base-href и deploy-url:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# пример сборки под префикс /ui/simple
|
||||||
|
npx ng build --configuration production \
|
||||||
|
--base-href /ui/simple/ \
|
||||||
|
--deploy-url /ui/simple/
|
||||||
|
```
|
||||||
|
|
||||||
|
Что это даёт:
|
||||||
|
- В `dist/.../browser/index.html` будет `<base href="/ui/simple/">`.
|
||||||
|
- Все ссылки на бандлы/ассеты будут начинаться с `/ui/simple/`.
|
||||||
|
|
||||||
|
Вариант B: поправить `index.html` вручную после сборки (минимальный вариант):
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!-- ui/dist/project-front/browser/index.html -->
|
||||||
|
<base href="/ui/simple/">
|
||||||
|
```
|
||||||
|
|
||||||
|
Важно: закрывающий слеш обязателен, иначе роутинг может «ехать».
|
||||||
|
|
||||||
|
Настройка бэкенда:
|
||||||
|
- Сервируйте содержимое собранной папки по маршруту `/ui/simple` (или скопируйте артефакты в `back/cmd/public/ui/simple/`).
|
||||||
|
- SPA‑фоллбэк должен отдавать `index.html` при запросах внутри префикса, если это не файловые ресурсы.
|
||||||
|
|
||||||
|
Если у вас универсальный обработчик (как в `setupStaticRoutes`) на корне, два простых подхода:
|
||||||
|
- Хранить файлы в `public/ui/simple/...` — тогда запросы к `/ui/simple/...` будут удовлетворены корректно.
|
||||||
|
- Либо сделать отдельный хендлер, который для путей с префиксом `/ui/simple` читает файлы из подкаталога, а на несуществующие файлы отвечает содержимым `public/ui/simple/index.html`.
|
||||||
|
|
||||||
|
Пример маппинга структуры в `public/`:
|
||||||
|
|
||||||
|
```text
|
||||||
|
public/
|
||||||
|
├── ui/
|
||||||
|
│ └── simple/
|
||||||
|
│ ├── index.html # с <base href="/ui/simple/">
|
||||||
|
│ ├── main-*.js
|
||||||
|
│ ├── styles-*.css
|
||||||
|
│ └── assets/...
|
||||||
|
└── ...
|
||||||
|
```
|
||||||
|
|
||||||
|
Проверка:
|
||||||
|
```text
|
||||||
|
http://localhost:8888/ui/simple
|
||||||
|
```
|
||||||
|
Если при прямом заходе на вложенный роут `/ui/simple/some/child` видите 404 — значит фоллбэк не отрабатывает. Проверьте, что при отсутствии файла по этому пути сервер возвращает `public/ui/simple/index.html`.
|
||||||
|
|
||||||
## FAQ и типичные ошибки
|
## FAQ и типичные ошибки
|
||||||
|
|
||||||
- «Сервер ругается на пароль»: не задали `GO_KNOCKER_SERVE_PASS` или запустили в другой сессии. Экспортните переменную и перезапустите.
|
- «Сервер ругается на пароль»: не задали `GO_KNOCKER_SERVE_PASS` или запустили в другой сессии. Экспортните переменную и перезапустите.
|
||||||
|
Reference in New Issue
Block a user