svelte-api-hybrid-proxy
v2.0.1
Published
A self-signed HTTPS reverse proxy for Svelte/Vite dev servers that routes /api/* requests to a configurable local or staging backend while preserving cookies, headers, and SPA fallback, with built-in body/response logging and x-app-environment injection.
Maintainers
Readme
svelte-api-proxy
A self-signed HTTPS reverse proxy for Svelte/Vite dev servers that routes /api/* requests to a configurable local or staging backend while preserving cookies, headers, and SPA fallback.
Features
- HTTPS support - Self-signed certificates for local HTTPS development
- API routing - Routes
/api/*requests to local or remote API - Cookie preservation - Maintains cookies between proxy and API
- WebSocket support - Full WebSocket proxying for HMR and live reload
- SPA fallback - Client-side routing support for single-page applications
- Environment injection - Adds
x-app-environment: localheader to staging requests - Configurable logging - Toggle request/response logs on/off
- Host header management - Properly handles Host header for remote APIs
Installation
npm install --save-dev svelte-api-proxy concurrentlyQuick Start
See QUICK_START.md for a complete installation and configuration guide.
How It Works
Architecture
Browser (https://dev-example.com:8443)
↓
HTTPS Proxy Server (port 8443)
↓
├── /api/* requests → Remote/Local API (e.g., https://api.example.com)
└── All other requests → Vite Dev Server (http://localhost:5173)Request Flow
- Browser makes request to
https://dev-example.com:8443 - Proxy receives request and inspects the URL path
- Routing decision:
- If path starts with
/api/→ Forward to configured API - If path is
/,/@vite/*, or contains.→ Forward to Vite - Otherwise → SPA fallback (serve
/)
- If path starts with
- Header management:
- Strips
Hostheader to avoid routing conflicts - Adds
x-app-environment: localfor non-local APIs - Preserves all cookies and custom headers
- Strips
- Response forwarding back to browser with all headers intact
WebSocket Handling
The proxy automatically upgrades WebSocket connections:
/api/*WebSockets → Forwarded to API- Other WebSockets → Forwarded to Vite (for HMR)
Configuration
All configuration is done via environment variables with the PROXY_ prefix.
Environment Variables
| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| PROXY_APP_PORT | Yes | - | Port where your Vite dev server runs (e.g., 5173) |
| PROXY_PORT | Yes | - | Port where the HTTPS proxy listens (e.g., 8443) |
| PROXY_DEV_DOMAIN | Yes | - | Domain alias for local dev. Must match SSL certificate common name |
| PROXY_API_LOCAL | No | false | When true, disables SSL verification for local self-signed API certs |
| PROXY_API_BASE_URL | Yes | - | Full base URL of the API (e.g., https://api.example.com) |
| PROXY_CERTS_PATH | Yes | - | Relative or absolute path to directory containing SSL certificates |
| PROXY_SHOW_LOGS | No | true | When true, logs all proxy requests and responses to console |
Example .env File
Create a .env file in your project root:
# Proxy Configuration
PROXY_APP_PORT=5173
PROXY_PORT=8443
PROXY_DEV_DOMAIN=dev-example.com
PROXY_API_LOCAL=false
PROXY_API_BASE_URL=https://api.example.com
PROXY_CERTS_PATH=./certs
PROXY_SHOW_LOGS=trueLoading Environment Variables
This package expects environment variables to be set before the CLI runs. Use one of these approaches:
Option 1: dotenv with node -r flag
{
"scripts": {
"dev:proxy": "node -r dotenv/config ./node_modules/.bin/svelte-api-proxy"
}
}Option 2: dotenv-cli
npm install --save-dev dotenv-cli{
"scripts": {
"dev:proxy": "dotenv -- svelte-api-proxy"
}
}Option 3: Shell export
export PROXY_APP_PORT=5173
export PROXY_PORT=8443
# ... etc
svelte-api-proxyImportant: Add .env to your .gitignore:
echo ".env" >> .gitignoreSSL Certificates
Certificate Requirements
The proxy requires two files in your certsPath directory:
{devDomain}-key.pem- Private key{devDomain}.pem- Certificate
Example: If devDomain is dev-example.com:
dev-example.com-key.pemdev-example.com.pem
Generating Certificates with mkcert
Install mkcert:
# macOS
brew install mkcert
# Linux
sudo apt install mkcert
# Windows
choco install mkcertGenerate certificates:
cd certs
mkcert -install
mkcert dev-example.comThis creates:
dev-example.com.pem(certificate)dev-example.com-key.pem(private key)
Important: Add ./certs to your .gitignore to avoid committing certificates.
API Reference
DevProxy Class
The main proxy server class.
Constructor
import { DevProxy } from "svelte-api-proxy";
const proxy = new DevProxy(config);Parameters:
config(object) - Configuration object with required fields:appPort(number)proxyPort(number)devDomain(string)apiBaseUrl(string)certsPath(string)apiLocal(boolean, optional, default:false)showLogs(boolean, optional, default:true)
Throws:
- Error if any required field is missing
- Error if SSL certificates are not found
Methods
start()
Starts the HTTPS proxy server.
proxy.start();Output:
[PROXY] Starting HTTPS dev proxy...
[PROXY] API target → REMOTE (https://api.example.com)
[PROXY] HTTPS server → https://dev-example.com:8443
[PROXY] App → http://localhost:5173
[PROXY] API → https://api.example.comstop()
Stops the proxy server.
proxy.stop();Header Management
Host Header
The proxy automatically strips the Host header from forwarded requests to prevent routing conflicts. When you access https://dev-example.com:8443, the browser sends:
Host: dev-example.com:8443If forwarded as-is to api.example.com, the remote server would reject it. The proxy strips this header and lets http-proxy's changeOrigin: true set the correct Host header.
x-app-environment Header
When apiLocal is false (staging/production API), the proxy adds:
x-app-environment: localThis allows your API to differentiate between requests from local development vs deployed apps.
Logging
When showLogs is true, the proxy logs:
Request:
[PROXY] GET /api/users → https://api.example.com/api/usersResponse:
[PROXY] Response: 200 GET /api/usersSet showLogs: false to disable logging.
Programmatic Usage
For advanced use cases, you can use the proxy programmatically:
import { DevProxy } from "svelte-api-proxy";
const proxy = new DevProxy({
appPort: 5173,
proxyPort: 8443,
devDomain: "dev-example.com",
apiLocal: false,
apiBaseUrl: "https://api.example.com",
certsPath: "./certs",
showLogs: true,
});
proxy.start();
// Later...
proxy.stop();Troubleshooting
"PROXY_APP_PORT environment variable is required"
Cause: Required environment variables are not set.
Solution:
- Create a
.envfile in your project root with all requiredPROXY_*variables - Ensure dotenv is loading before the CLI runs (see Configuration section)
- Verify your npm script uses
node -r dotenv/configordotenv --
"SSL key not found at: ..."
Cause: SSL certificates are missing or incorrectly named.
Solution:
- Verify
certsPathpoints to the correct directory - Ensure certificate files match the pattern:
{devDomain}-key.pemand{devDomain}.pem - Regenerate certificates if needed
503 Service Unavailable
Cause: The remote API is not responding.
Solution:
- Verify
apiBaseUrlis correct - Test API directly:
curl https://api.example.com/api/health - Check API server logs
- Ensure your network allows outbound HTTPS
Certificate Warnings in Browser
Cause: Browser doesn't trust self-signed certificate.
Solution: Run mkcert -install to install the local CA in your browser's trust store.
CORS Errors
Cause: API is rejecting requests due to CORS policy.
Solution: Since the proxy forwards requests from localhost, your API must allow requests from your dev domain origin. Configure CORS on your API to allow https://dev-example.com:8443.
WebSocket Connection Failed
Cause: WebSocket upgrade not being handled correctly.
Solution:
- Verify Vite's WebSocket port matches
appPort - Check browser console for WebSocket errors
- Ensure no firewall is blocking WebSocket connections
Advanced Topics
Using with Multiple Svelte Apps
You can run multiple Svelte apps with different domain aliases using separate .env files:
App 1 (.env.app1):
PROXY_APP_PORT=5173
PROXY_PORT=8443
PROXY_DEV_DOMAIN=app1.dev-example.com
PROXY_API_BASE_URL=https://api.example.com
PROXY_CERTS_PATH=./certsApp 2 (.env.app2):
PROXY_APP_PORT=5174
PROXY_PORT=8444
PROXY_DEV_DOMAIN=app2.dev-example.com
PROXY_API_BASE_URL=https://api.example.com
PROXY_CERTS_PATH=./certsRun with specific env file:
{
"scripts": {
"dev:app1": "dotenv -e .env.app1 -- svelte-api-proxy",
"dev:app2": "dotenv -e .env.app2 -- svelte-api-proxy"
}
}Cookie Sharing Between Apps
Use a common parent domain for cookie sharing:
# /etc/hosts
127.0.0.1 dev-example.com
127.0.0.1 app1.dev-example.com
127.0.0.1 app2.dev-example.com
127.0.0.1 api.dev-example.comSet cookies with domain=.dev-example.com to share across all subdomains.
Migrating from v1.x to v2.x
Version 2.0 changes configuration from package.json to environment variables.
Step 1: Create .env file
Move your proxyConfig values to a .env file:
Before (package.json):
{
"proxyConfig": {
"appPort": 5173,
"proxyPort": 8443,
"devDomain": "dev-example.com",
"apiLocal": false,
"apiBaseUrl": "https://api.example.com",
"certsPath": "./certs",
"showLogs": true
}
}After (.env):
PROXY_APP_PORT=5173
PROXY_PORT=8443
PROXY_DEV_DOMAIN=dev-example.com
PROXY_API_LOCAL=false
PROXY_API_BASE_URL=https://api.example.com
PROXY_CERTS_PATH=./certs
PROXY_SHOW_LOGS=trueStep 2: Install dotenv
npm install --save-dev dotenvStep 3: Update npm scripts
{
"scripts": {
"dev:proxy": "node -r dotenv/config ./node_modules/.bin/svelte-api-proxy"
}
}Step 4: Remove proxyConfig from package.json
Delete the proxyConfig section from your package.json.
Step 5: Add .env to .gitignore
echo ".env" >> .gitignoreLicense
MIT
Contributing
Issues and PRs welcome at https://github.com/eduardocgarza/svelte-api-proxy
