Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: fixes to webroot feature and improvements to development using it #1046

Merged
merged 4 commits into from
Jan 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,6 @@ help:
clean:
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
.PHONY: run-server
run-server:
Expand Down
23 changes: 20 additions & 3 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -1,25 +1,39 @@
# Docker compose for development purposes only.
# Edit it to fit your current development needs.
version: "3"
services:
shiori:
build:
context: .
dockerfile: Dockerfile.compose
container_name: shiori
command:
- "server"
- "--log-level"
- "debug"
ports:
- "8080:8080"
volumes:
- "./dev-data:/srv/shiori"
- ".:/src/shiori"
- "go-mod-cache:/go/pkg/mod"
restart: unless-stopped
links:
- "postgres"
- "mariadb"
environment:
SHIORI_DIR: /srv/shiori
#SHIORI_DATABASE_URL: mysql://shiori:shiori@(mariadb)/shiori?charset=utf8mb4
SHIORI_DATABASE_URL: postgres://shiori:shiori@postgres/shiori?sslmode=disable
# SHIORI_HTTP_ROOT_PATH: /shiori/
# 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:
image: postgres:15
Expand All @@ -38,3 +52,6 @@ services:
MYSQL_PASSWORD: shiori
ports:
- "3306:3306"

volumes:
go-mod-cache:
38 changes: 30 additions & 8 deletions docs/Contribute.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,10 @@

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
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

> **ℹ️ Note:** This only applies for the Rest API documentation under the `internal/http` folder, **not** the one under `internal/webserver`.
Expand Down Expand Up @@ -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.

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.
4 changes: 4 additions & 0 deletions internal/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ func initShiori(ctx context.Context, cmd *cobra.Command) (*config.Config, *depen

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)
if err != nil {
logger.WithError(err).Fatal("error creating data directory")
Expand Down
16 changes: 16 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
DBMS string `env:"DBMS"` // Deprecated
// DBMS requires more environment variables. Check the database package for more information.
Expand Down Expand Up @@ -140,6 +148,14 @@ func (c *Config) DebugConfiguration(logger *logrus.Logger) {
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
func ParseServerConfiguration(ctx context.Context, logger *logrus.Logger) *Config {
var cfg Config
Expand Down
16 changes: 16 additions & 0 deletions internal/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,19 @@ func TestConfigSetDefaults(t *testing.T) {
require.NotEmpty(t, cfg.Storage.DataDir)
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())
})
}
30 changes: 15 additions & 15 deletions internal/view/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,27 @@

<link href="assets/css/style.css" rel="stylesheet">

<script src="assets/js/vue.min.js"></script>
<script src="assets/js/url.min.js"></script>
<script src="assets/js/vue.min.js" type="text/javascript"></script>
<script src="assets/js/url.min.js" type="text/javascript"></script>
</head>

<body>
<div id="app">
<login-view v-if="isLoggedIn === false && loginRequired" @login-success="onLoginSuccess"></login-view>
<div id="main-scene" v-else-if="isLoggedIn === true">
<div id="main-sidebar">
<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>
</a>
<div class="spacer"></div>
<a title="Logout" @click="logout">
<i class="fas fa-fw fa-sign-out-alt"></i>
</a>
</div>
<keep-alive>
<component :is="activePage" :active-account="activeAccount" :app-options="appOptions" @setting-changed="saveSetting"></component>
</keep-alive>
<custom-dialog v-bind="dialog" />
<div id="main-sidebar">
<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>
</a>
<div class="spacer"></div>
<a title="Logout" @click="logout">
<i class="fas fa-fw fa-sign-out-alt"></i>
</a>
</div>
<keep-alive>
<component :is="activePage" :active-account="activeAccount" :app-options="appOptions" @setting-changed="saveSetting"></component>
</keep-alive>
<custom-dialog v-bind="dialog"></custom-dialog>
</div>
</div>

Expand Down
24 changes: 24 additions & 0 deletions testdata/nginx.conf
Original file line number Diff line number Diff line change
@@ -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