mirror of
https://github.com/go-shiori/shiori.git
synced 2025-09-12 07:55:35 +08:00
feat: fixes to webroot feature and improvements to development using it (#1046)
* feat: Add nginx service to test shiori webroot configuration chore: Update nginx configuration to resolve 502 gateway error fix: Update SHIORI_WEBROOT to SHIORI_HTTP_ROOT_PATH in docker-compose feat: Add debug log level flag to shiori service refactor: Update docker-compose with simplified command and log configuration fix: Change nginx port mapping from 80 to 8081 feat: Add volume for Go module cache in docker-compose style: Add type attribute to script tags in index.html feat: Update import statements to use RootPath variable in index.html * docs: Update contribution guide with server and docker instructions * docs: Add Docker and nginx documentation for local development * test: IsValid()
This commit is contained in:
parent
d75de89701
commit
45bd4d693f
8 changed files with 125 additions and 31 deletions
5
Makefile
5
Makefile
|
@ -57,11 +57,6 @@ help:
|
||||||
clean:
|
clean:
|
||||||
rm -rf dist
|
rm -rf dist
|
||||||
|
|
||||||
## Runs the legacy http API for local development
|
|
||||||
.PHONY: serve
|
|
||||||
serve:
|
|
||||||
SHIORI_DEVELOPMENT=$(SHIORI_DEVELOPMENT) SHIORI_DIR=$(SHIORI_DIR) go run main.go serve
|
|
||||||
|
|
||||||
## Runs server for local development
|
## Runs server for local development
|
||||||
.PHONY: run-server
|
.PHONY: run-server
|
||||||
run-server:
|
run-server:
|
||||||
|
|
|
@ -1,25 +1,39 @@
|
||||||
# Docker compose for development purposes only.
|
# Docker compose for development purposes only.
|
||||||
# Edit it to fit your current development needs.
|
# Edit it to fit your current development needs.
|
||||||
version: "3"
|
|
||||||
services:
|
services:
|
||||||
shiori:
|
shiori:
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: Dockerfile.compose
|
dockerfile: Dockerfile.compose
|
||||||
container_name: shiori
|
container_name: shiori
|
||||||
|
command:
|
||||||
|
- "server"
|
||||||
|
- "--log-level"
|
||||||
|
- "debug"
|
||||||
ports:
|
ports:
|
||||||
- "8080:8080"
|
- "8080:8080"
|
||||||
volumes:
|
volumes:
|
||||||
- "./dev-data:/srv/shiori"
|
- "./dev-data:/srv/shiori"
|
||||||
- ".:/src/shiori"
|
- ".:/src/shiori"
|
||||||
|
- "go-mod-cache:/go/pkg/mod"
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
links:
|
links:
|
||||||
- "postgres"
|
- "postgres"
|
||||||
- "mariadb"
|
- "mariadb"
|
||||||
environment:
|
environment:
|
||||||
SHIORI_DIR: /srv/shiori
|
SHIORI_DIR: /srv/shiori
|
||||||
#SHIORI_DATABASE_URL: mysql://shiori:shiori@(mariadb)/shiori?charset=utf8mb4
|
# SHIORI_HTTP_ROOT_PATH: /shiori/
|
||||||
SHIORI_DATABASE_URL: postgres://shiori:shiori@postgres/shiori?sslmode=disable
|
# SHIORI_DATABASE_URL: mysql://shiori:shiori@(mariadb)/shiori?charset=utf8mb4
|
||||||
|
# SHIORI_DATABASE_URL: postgres://shiori:shiori@postgres/shiori?sslmode=disable
|
||||||
|
|
||||||
|
nginx:
|
||||||
|
image: nginx:alpine
|
||||||
|
ports:
|
||||||
|
- "8081:8081"
|
||||||
|
volumes:
|
||||||
|
- "./testdata/nginx.conf:/etc/nginx/nginx.conf:ro"
|
||||||
|
depends_on:
|
||||||
|
- shiori
|
||||||
|
|
||||||
postgres:
|
postgres:
|
||||||
image: postgres:15
|
image: postgres:15
|
||||||
|
@ -38,3 +52,6 @@ services:
|
||||||
MYSQL_PASSWORD: shiori
|
MYSQL_PASSWORD: shiori
|
||||||
ports:
|
ports:
|
||||||
- "3306:3306"
|
- "3306:3306"
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
go-mod-cache:
|
||||||
|
|
|
@ -9,18 +9,10 @@
|
||||||
|
|
||||||
To run the current development server with the defaults you can run the following command:
|
To run the current development server with the defaults you can run the following command:
|
||||||
|
|
||||||
```bash
|
|
||||||
make serve
|
|
||||||
```
|
|
||||||
|
|
||||||
If you want to run the refactored server, you can run the following command:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
make run-server
|
make run-server
|
||||||
```
|
```
|
||||||
|
|
||||||
> **ℹ️ Note:** For more information into what the _refactored server_ means, please check this issue: https://github.com/go-shiori/shiori/issues/640
|
|
||||||
|
|
||||||
## Updating the API documentation
|
## Updating the API documentation
|
||||||
|
|
||||||
> **ℹ️ Note:** This only applies for the Rest API documentation under the `internal/http` folder, **not** the one under `internal/webserver`.
|
> **ℹ️ Note:** This only applies for the Rest API documentation under the `internal/http` folder, **not** the one under `internal/webserver`.
|
||||||
|
@ -94,3 +86,33 @@ mkdocs serve
|
||||||
This will start a local server at `http://127.0.0.1:8000` where you can preview your changes in real-time.
|
This will start a local server at `http://127.0.0.1:8000` where you can preview your changes in real-time.
|
||||||
|
|
||||||
Documentation for production is generated automatically on every release and published using github pages.
|
Documentation for production is generated automatically on every release and published using github pages.
|
||||||
|
|
||||||
|
## Running the server with docker
|
||||||
|
|
||||||
|
To run the development server using Docker, you can use the provided `docker-compose.yaml` file which includes both PostgreSQL and MariaDB databases:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose up shiori
|
||||||
|
```
|
||||||
|
|
||||||
|
This will start the Shiori server on port 8080 with hot-reload enabled. Any changes you make to the code will automatically rebuild and restart the server.
|
||||||
|
|
||||||
|
By default, it uses SQLite mounting the local `dev-data` folder in the source code path. To use MariaDB or PostgreSQL instead, uncomment the `SHIORI_DATABASE_URL` line for the appropriate engine in the `docker-compose.yaml` file.
|
||||||
|
|
||||||
|
## Running the server using an nginx reverse proxy and a custom webroot
|
||||||
|
|
||||||
|
To test Shiori behind an nginx reverse proxy with a custom webroot (e.g., `/shiori/`), you can use the provided nginx configuration:
|
||||||
|
|
||||||
|
1. First, ensure the `SHIORI_HTTP_ROOT_PATH` environment variable is uncommented in `docker-compose.yaml`:
|
||||||
|
```yaml
|
||||||
|
SHIORI_HTTP_ROOT_PATH: /shiori/
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Then start both Shiori and nginx services:
|
||||||
|
```bash
|
||||||
|
docker compose up shiori nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
This will start the shiori service along with nginx. You can access Shiori using [http://localhost:8081/shiori](http://localhost:8081/shiori).
|
||||||
|
|
||||||
|
The nginx configuration in `testdata/nginx.conf` handles all the necessary configuration.
|
||||||
|
|
|
@ -80,6 +80,10 @@ func initShiori(ctx context.Context, cmd *cobra.Command) (*config.Config, *depen
|
||||||
|
|
||||||
cfg.SetDefaults(logger, portableMode)
|
cfg.SetDefaults(logger, portableMode)
|
||||||
|
|
||||||
|
if err := cfg.IsValid(); err != nil {
|
||||||
|
logger.WithError(err).Fatal("invalid configuration detected")
|
||||||
|
}
|
||||||
|
|
||||||
err := os.MkdirAll(cfg.Storage.DataDir, model.DataDirPerm)
|
err := os.MkdirAll(cfg.Storage.DataDir, model.DataDirPerm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.WithError(err).Fatal("error creating data directory")
|
logger.WithError(err).Fatal("error creating data directory")
|
||||||
|
|
|
@ -79,6 +79,14 @@ func (c *HttpConfig) SetDefaults(logger *logrus.Logger) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *HttpConfig) IsValid() error {
|
||||||
|
if !strings.HasSuffix(c.RootPath, "/") {
|
||||||
|
return fmt.Errorf("root path should end with a slash")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type DatabaseConfig struct {
|
type DatabaseConfig struct {
|
||||||
DBMS string `env:"DBMS"` // Deprecated
|
DBMS string `env:"DBMS"` // Deprecated
|
||||||
// DBMS requires more environment variables. Check the database package for more information.
|
// DBMS requires more environment variables. Check the database package for more information.
|
||||||
|
@ -140,6 +148,14 @@ func (c *Config) DebugConfiguration(logger *logrus.Logger) {
|
||||||
logger.Debugf(" SHIORI_HTTP_DISABLE_PARSE_MULTIPART_FORM: %t", c.Http.DisablePreParseMultipartForm)
|
logger.Debugf(" SHIORI_HTTP_DISABLE_PARSE_MULTIPART_FORM: %t", c.Http.DisablePreParseMultipartForm)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Config) IsValid() error {
|
||||||
|
if err := c.Http.IsValid(); err != nil {
|
||||||
|
return fmt.Errorf("http configuration is invalid: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// ParseServerConfiguration parses the configuration from the enabled lookupers
|
// ParseServerConfiguration parses the configuration from the enabled lookupers
|
||||||
func ParseServerConfiguration(ctx context.Context, logger *logrus.Logger) *Config {
|
func ParseServerConfiguration(ctx context.Context, logger *logrus.Logger) *Config {
|
||||||
var cfg Config
|
var cfg Config
|
||||||
|
|
|
@ -101,3 +101,19 @@ func TestConfigSetDefaults(t *testing.T) {
|
||||||
require.NotEmpty(t, cfg.Storage.DataDir)
|
require.NotEmpty(t, cfg.Storage.DataDir)
|
||||||
require.NotEmpty(t, cfg.Database.URL)
|
require.NotEmpty(t, cfg.Database.URL)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestConfigIsValid(t *testing.T) {
|
||||||
|
log := logrus.New()
|
||||||
|
|
||||||
|
t.Run("valid configuration", func(t *testing.T) {
|
||||||
|
cfg := ParseServerConfiguration(context.TODO(), log)
|
||||||
|
cfg.SetDefaults(log, false)
|
||||||
|
require.NoError(t, cfg.IsValid())
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("invalid http root path", func(t *testing.T) {
|
||||||
|
cfg := ParseServerConfiguration(context.TODO(), log)
|
||||||
|
cfg.Http.RootPath = "/invalid"
|
||||||
|
require.Error(t, cfg.IsValid())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -16,27 +16,27 @@
|
||||||
|
|
||||||
<link href="assets/css/style.css" rel="stylesheet">
|
<link href="assets/css/style.css" rel="stylesheet">
|
||||||
|
|
||||||
<script src="assets/js/vue.min.js"></script>
|
<script src="assets/js/vue.min.js" type="text/javascript"></script>
|
||||||
<script src="assets/js/url.min.js"></script>
|
<script src="assets/js/url.min.js" type="text/javascript"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="app">
|
<div id="app">
|
||||||
<login-view v-if="isLoggedIn === false && loginRequired" @login-success="onLoginSuccess"></login-view>
|
<login-view v-if="isLoggedIn === false && loginRequired" @login-success="onLoginSuccess"></login-view>
|
||||||
<div id="main-scene" v-else-if="isLoggedIn === true">
|
<div id="main-scene" v-else-if="isLoggedIn === true">
|
||||||
<div id="main-sidebar">
|
<div id="main-sidebar">
|
||||||
<a v-for="item in sidebarItems" :title="item.title" :class="{active: activePage === item.page}" @click="switchPage(item.page)">
|
<a v-for="item in sidebarItems" :title="item.title" :class="{active: activePage === item.page}" @click="switchPage(item.page)">
|
||||||
<i class="fas fa-fw" :class="item.icon"></i>
|
<i class="fas fa-fw" :class="item.icon"></i>
|
||||||
</a>
|
</a>
|
||||||
<div class="spacer"></div>
|
<div class="spacer"></div>
|
||||||
<a title="Logout" @click="logout">
|
<a title="Logout" @click="logout">
|
||||||
<i class="fas fa-fw fa-sign-out-alt"></i>
|
<i class="fas fa-fw fa-sign-out-alt"></i>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<keep-alive>
|
<keep-alive>
|
||||||
<component :is="activePage" :active-account="activeAccount" :app-options="appOptions" @setting-changed="saveSetting"></component>
|
<component :is="activePage" :active-account="activeAccount" :app-options="appOptions" @setting-changed="saveSetting"></component>
|
||||||
</keep-alive>
|
</keep-alive>
|
||||||
<custom-dialog v-bind="dialog" />
|
<custom-dialog v-bind="dialog"></custom-dialog>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
24
testdata/nginx.conf
vendored
Normal file
24
testdata/nginx.conf
vendored
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
events {
|
||||||
|
worker_connections 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
include /etc/nginx/mime.types;
|
||||||
|
default_type application/octet-stream;
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 8081;
|
||||||
|
server_name localhost;
|
||||||
|
|
||||||
|
location /shiori/ {
|
||||||
|
proxy_pass http://shiori: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;
|
||||||
|
proxy_read_timeout 300;
|
||||||
|
proxy_connect_timeout 300;
|
||||||
|
proxy_send_timeout 300;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue