Recently, I've been dabbling with PocketBase as a backend solution, and I must say it's a fantastic tool to have on your belt. For a small web app with mostly CRUDy logic it's just insanely productive - you can expose a complete REST(ish) API in a matter of minutes.
Deploying PocketBase services is also stupid simple. Just ship the binary to a VM, write a simple systemd unit, start it, and you're done. It even comes with SSL out of the box, thanks to Caddy.
On my server I'm using the following config:
[Unit]
Description = service_name
[Service]
Type = simple
User = malick
Group = malick
LimitNOFILE = 4096
Restart = always
RestartSec = 5s
StandardOutput = append:/home/malick/service_name/errors.log
StandardError = append:/home/malick/service_name/errors.log
ExecStart = /home/malick/service_name/pocketbase serve --http 127.0.0.1:8090 --origins "https://spa.com"
[Install]
WantedBy = multi-user.target
Then I proxy requests into the app through my Caddy service:
spa.com {
request_body {
max_size 10MB
}
reverse_proxy 127.0.0.1:8090
encode zstd gzip
}
As you can see above, we can configure the PocketBase binary to specify where our SPA is accessible so it correctly handles CORS.
Browsers fire an OPTIONS request to the server to verify if they can proceed with the original request from the current origin. This happens every time a request is made from the browser. Sounds awful, right? Every request is essentially two.
Luckily. we can instruct the browser to cache the CORS settings so it doesn't keep firing OPTIONS requests unnecessarily needlessly.
This is possible thanks to the Access-Control-Max-Age
header.
I looked around and it seems like PocketBase cannot set such header natively, at least not without extending the app with custom Go code. So my solution was to handle it direclty at my web server, before it even reaches the app. A quick look at Caddy's documentation led me to this configuration:
spa.com {
request_body {
max_size 10MB
}
@cors_preflight {
method OPTIONS
header Origin *
}
handle @cors_preflight {
header Access-Control-Max-Age "86400"
}
reverse_proxy 127.0.0.1:8090
encode zstd gzip
}
Our browsers will now cache the CORS settings for 24 hours.