Switched to a new config file format, switched to a custom error handling screen instead of 404 Page Not Found, switched to per-route static file service, added proxying (in beta), reduced the cyclomatic complexity of main() function, broke up the compression handlers into different functions, added HTTPS functionality (beta), made the global router not special, use a custom http handler to automatically switch between compression schemes based on per-route compression settings, support comments in the configuration file.

Signed-off-by: arzumify <jliwin98@danwin1210.de>
This commit is contained in:
Tracker-Friendly 2024-11-01 13:09:35 +00:00
parent 3fe89adee8
commit cf5dbe7946
6 changed files with 996 additions and 564 deletions

2
.gitignore vendored
View File

@ -5,5 +5,5 @@
/resources /resources
/services /services
/services-src/eternity-web /services-src/eternity-web
/config.json /config.conf
fulgens.log fulgens.log

120
config.conf.example Normal file
View File

@ -0,0 +1,120 @@
// NOTE: This is NOT a valid JSON file.
// Comments are added here, which are stripped out by fulgens. This is not standard behavior for JSON and will only work with fulgens.
{
// Global configuration
"global": {
// IP defines the IP address to bind to.
"ip": "0.0.0.0",
// httpPort defines the port to bind to for HTTP.
"httpPort": "8080",
// httpsPort defines the port to bind to for HTTPS (TLS).
"httpsPort": "8443",
// serviceDirectory defines the directory to look for services in.
"serviceDirectory": "./services",
// resourceDirectory defines the directory to look for resources in.
"resourceDirectory": "./resources",
// compression defines the compression settings on a global level - per-route settings override these.
"compression": {
// algorithm defines the compression algorithm to use, possible values are "gzip", "brotli" and "zstd".
"algorithm": "gzip",
// level defines the compression level to use, possible values are 1-9 for gzip, 0-11 for brotli and 1-22 for zstd.
"level": 5
},
// logging defines the logging settings.
"logging": {
// enabled defines whether logging is enabled.
"enabled": true,
// file defines the file to log to, relative to the working directory.
"file": "fulgens.log"
},
// database defines the database settings.
"database": {
// type defines the type of database to use, possible values are "sqlite" and "postgres".
"type": "sqlite",
// path defines the path to the directory to store database files in (sqlite only).
"path": "./databases",
// connectionString defines the connection string to use for the database (postgres only).
"connectionString": "postgres://user:password@localhost:5432/database"
}
},
// Routes define per-subdomain routing settings.
"routes": [
{
// none is a special subdomain that matches all requests without a subdomain (Host header).
"subdomain": "none",
// services defines the services to use for this route. Services must be defined on a per-subdomain basis.
// Each service may not be used more than once globally. The server will fail to start if this is violated.
"services": ["authentication"]
},
{
// any subdomain value that isn't "none" will match that specific subdomain.
"subdomain": "www.localhost",
// https defines the HTTPS settings for this route.
"https": {
// certificate defines the path to the certificate file.
"certificate": "./certs/localhost.crt",
// key defines the path to the key file.
"key": "./certs/localhost.key"
},
// paths defines per-path settings (NOT for services, which MUST be defined on a per-subdomain basis).
"paths": [
{
// path defines the path to match. They can contain wildcards.
"path": "/static/*",
// static defines the static file serving settings for this path. This conflicts with proxy.
// If both proxy and static are defined, static will take precedence.
"static": {
// root defines the root directory to serve static files from.
"root": "./static",
// directoryListing defines whether to show a directory listing when a directory is requested.
// if it is false or unset, a 403 Forbidden will be returned instead.
"directoryListing": true
}
},
{
// path defines the path to match. They can contain wildcards.
"path": "/proxy/*",
// proxy defines the proxy settings for this path. This conflicts with static.
// If both proxy and static are defined, static will take precedence.
"proxy": {
// url defines the URL to proxy requests to.
"url": "http://localhost:8000",
// stripPrefix defines whether to strip the prefix from the path before proxying.
"stripPrefix": true
// TODO: In a future update, passing X-Forwarded-For and X-Forwarded-Proto headers will be supported.
// TODO: In a future update, forbidding certain headers from being passed will be supported.
// TODO: In a future update, passing X-Powered-By and Server headers will be supported.
// TODO: In a future update, passing Host header will be supported.
}
}
]
}
],
// Services define the settings for services.
"services": {
// authentication defines the settings for the authentication service, which is built-in.
"authentication": {
// privacyPolicy defines the URL to the privacy policy.
"privacyPolicy": "https://git.ailur.dev/Paperwork/nucleus/src/commit/5d191eea87cffae8bdca42017ac26dc19e6cb3de/Privacy.md",
// url defines the publicly-facing URL of the service, in case of it being behind a reverse proxy.
"url": "http://localhost:8000",
// identifier defines the identifier for the service, in the form of [Identifier] Accounts.
"identifier": "Authenticator",
// adminKey defines the key to use for administrative operations, such as listing all users.
"adminKey": "supersecretkey",
// testAppIsInternalApp defines whether the test app is an internal app, which allows it to bypass the user consent screen.
"testAppIsInternalApp": true,
// testAppEnabled defines whether the test app is enabled, which is recommended for testing purposes.
"testAppEnabled": true
},
// storage defines the settings for the storage service, which is built-in.
"storage": {
// path defines the path to store blobs in.
"path": "./blob",
// defaultQuota defines the default quota for users in bytes.
"defaultQuota": 50000000
},
}
}

View File

@ -1,30 +0,0 @@
{
"global": {
"ip": "0.0.0.0",
"port": "8000",
"serviceDirectory": "./services",
"resourceDirectory": "./resources"
},
"logging": {
"enabled": true,
"file": "fulgens.log"
},
"database": {
"databaseType": "sqlite",
"databasePath": "./databases"
},
"services": {
"storage": {
"path": "./blob",
"defaultQuota": 50000000
},
"authentication": {
"privacyPolicy": "https://git.ailur.dev/Paperwork/nucleus/src/commit/5d191eea87cffae8bdca42017ac26dc19e6cb3de/Privacy.md",
"url": "http://localhost:8000",
"identifier": "Authenticator",
"adminKey": "supersecretkey",
"testAppIsInternalApp": true,
"testAppEnabled": true
}
}
}

2
go.mod
View File

@ -6,10 +6,10 @@ require (
git.ailur.dev/ailur/fg-library/v2 v2.1.1 git.ailur.dev/ailur/fg-library/v2 v2.1.1
git.ailur.dev/ailur/fg-nucleus-library v1.0.3 git.ailur.dev/ailur/fg-nucleus-library v1.0.3
git.ailur.dev/ailur/pow v1.0.2 git.ailur.dev/ailur/pow v1.0.2
github.com/BurntSushi/toml v1.4.0
github.com/andybalholm/brotli v1.1.1 github.com/andybalholm/brotli v1.1.1
github.com/cespare/xxhash/v2 v2.3.0 github.com/cespare/xxhash/v2 v2.3.0
github.com/go-chi/chi/v5 v5.1.0 github.com/go-chi/chi/v5 v5.1.0
github.com/go-chi/hostrouter v0.2.0
github.com/go-playground/validator/v10 v10.22.1 github.com/go-playground/validator/v10 v10.22.1
github.com/golang-jwt/jwt/v5 v5.2.1 github.com/golang-jwt/jwt/v5 v5.2.1
github.com/google/uuid v1.6.0 github.com/google/uuid v1.6.0

10
go.sum
View File

@ -4,8 +4,8 @@ git.ailur.dev/ailur/fg-nucleus-library v1.0.3 h1:C0xgfZg7bkULhh9Ci7ZoAcx4QIqxLh+
git.ailur.dev/ailur/fg-nucleus-library v1.0.3/go.mod h1:RbBVFRwtQgYvCWoru1mC3vUJ1dMftkNbvd7hVFtREFw= git.ailur.dev/ailur/fg-nucleus-library v1.0.3/go.mod h1:RbBVFRwtQgYvCWoru1mC3vUJ1dMftkNbvd7hVFtREFw=
git.ailur.dev/ailur/pow v1.0.2 h1:8tb6mXZdyQYjrKRW+AUmWMi5wJoHh9Ch3oRqiJr/ivs= git.ailur.dev/ailur/pow v1.0.2 h1:8tb6mXZdyQYjrKRW+AUmWMi5wJoHh9Ch3oRqiJr/ivs=
git.ailur.dev/ailur/pow v1.0.2/go.mod h1:fjFb1z5KtF6V14HRhGWiDmmJKggO8KyAP20Lr5OJI/g= git.ailur.dev/ailur/pow v1.0.2/go.mod h1:fjFb1z5KtF6V14HRhGWiDmmJKggO8KyAP20Lr5OJI/g=
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA= github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA=
github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA= github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
@ -14,11 +14,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gabriel-vasile/mimetype v1.4.6 h1:3+PzJTKLkvgjeTbts6msPJt4DixhT4YtFNf1gtGe3zc= github.com/gabriel-vasile/mimetype v1.4.6 h1:3+PzJTKLkvgjeTbts6msPJt4DixhT4YtFNf1gtGe3zc=
github.com/gabriel-vasile/mimetype v1.4.6/go.mod h1:JX1qVKqZd40hUPpAfiNTe0Sne7hdfKSbOqqmkq8GCXc= github.com/gabriel-vasile/mimetype v1.4.6/go.mod h1:JX1qVKqZd40hUPpAfiNTe0Sne7hdfKSbOqqmkq8GCXc=
github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs=
github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw= github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw=
github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-chi/hostrouter v0.2.0 h1:GwC7TZz8+SlJN/tV/aeJgx4F+mI5+sp+5H1PelQUjHM=
github.com/go-chi/hostrouter v0.2.0/go.mod h1:pJ49vWVmtsKRKZivQx0YMYv4h0aX+Gcn6V23Np9Wf1s=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
@ -31,8 +28,6 @@ github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17w
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
@ -45,6 +40,7 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=

972
main.go

File diff suppressed because it is too large Load Diff