Vite plugin that provides HTTP/2 proxy support with full feature parity to Vite's built-in proxy.
- 🚀 Native HTTP/2 Support - Uses Node's native
http2module, no intermediate proxy module. - 🔄 Connection Pooling - Efficient HTTP/2 connection reuse with automatic cleanup.
- 🔌 WebSocket Support - Full WebSocket proxying with HTTP/2 upgrade handling.
- 🍪 Cookie Management - Advanced cookie rewriting with domain and path support.
- đź”’ Security Features - SSL validation, authentication, and X-Forwarded headers.
- 📡 SSE Support - Server-Sent Events with buffering control.
- 🛣️ Advanced Routing - Dynamic routing with function support.
- 📊 Comprehensive Logging - Detailed request logging with timing information.
- 🎯 Full Vite Compatibility - Supports Vite standard proxy configuration options.
npm install vite-plugin-proxy-http2
# or
yarn add vite-plugin-proxy-http2
# or
pnpm add vite-plugin-proxy-http2// vite.config.ts
import { defineConfig } from 'vite'
import http2ProxyPlugin from 'vite-plugin-proxy-http2'
export default defineConfig({
plugins: [
http2ProxyPlugin({
// Global settings (optional)
maxSessions: 50, // Limit HTTP/2 sessions
defaultTimeout: 30000, // 30 second timeout for all proxies
// Proxy routes
proxy: {
'/api': 'https://api.example.com',
'/ws': {
target: 'wss://websocket.example.com',
ws: true
}
}
})
]
})Note: This approach ensures HTTP/2 is used by default and prevents Vite from downgrading to HTTP/1.1.
// vite.config.ts
import { defineConfig } from 'vite'
import http2ProxyPlugin from 'vite-plugin-proxy-http2'
export default defineConfig({
plugins: [http2ProxyPlugin()],
server: {
proxy: {
'/api': 'https://api.example.com'
}
}
})Warning: Using Vite's
server.proxymay cause Vite to downgrade connections to HTTP/1.1. We recommend using the plugin-level configuration instead.
export default defineConfig({
plugins: [
http2ProxyPlugin({
proxy: {
// String shorthand
'/api': 'https://api.example.com',
// With options
'/api': {
target: 'https://api.example.com',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
headers: {
'X-Custom-Header': 'value'
}
},
// RegExp pattern
'^/api/.*': {
target: 'https://api.example.com',
changeOrigin: true
}
}
})
]
})'/socket.io': {
target: 'https://socket-server.com',
ws: true,
changeOrigin: true
}'/api': {
target: 'https://api.example.com',
cookieDomainRewrite: 'localhost',
cookiePathRewrite: {
'/api': '/',
'/api/v2': '/v2'
}
}'/api': {
target: 'https://default-api.com',
router: (req) => {
// Route based on headers, query params, etc.
if (req.headers['x-api-version'] === 'v2') {
return 'https://api-v2.example.com'
}
return 'https://api-v1.example.com'
}
}'/api': {
target: 'https://api.example.com',
bypass: (req, res, options) => {
// Skip proxy for certain conditions
if (req.headers.accept?.includes('text/html')) {
return '/index.html'
}
}
}// Force HTTP/1.1 for servers that don't support HTTP/2
'/legacy-api': {
target: 'https://old-server.com',
forceHttp1: true
}
// Automatically detect protocol support
'/auto': {
target: 'https://api.example.com',
autoDetectProtocol: true // Will use HTTP/2 if supported, fallback to HTTP/1.1
}'/api': {
target: 'https://api.example.com',
secure: true, // Verify SSL certificates
auth: 'username:password', // Basic authentication
xfwd: true, // Add X-Forwarded-* headers
headers: {
'Authorization': 'Bearer token'
}
}http2ProxyPlugin({
// Set global defaults for all proxies
defaultTimeout: 30000, // 30 seconds
defaultProxyTimeout: 25000, // 25 seconds
proxy: {
'/api': 'https://api.example.com', // Uses global defaults
'/slow-api': {
target: 'https://slow-api.example.com',
timeout: 60000 // Override for specific route
}
}
})'/events': {
target: 'https://sse-server.com',
sse: true, // Optimizes for SSE streams
changeOrigin: true
}'/api': {
target: 'https://api.example.com',
selfHandleResponse: true,
configure: (proxyReq, options) => {
// Custom request/response handling
proxyReq.on('response', (headers) => {
console.log('Response headers:', headers)
})
}
}These options are configured at the plugin level and affect all proxies:
| Option | Type | Default | Description |
|---|---|---|---|
proxy |
object |
- | Proxy route configurations |
maxSessions |
number |
100 |
Maximum number of HTTP/2 sessions |
sessionMaxAge |
number |
300000 |
Session idle timeout in milliseconds (5 minutes) |
connectionTimeout |
number |
10000 |
Initial connection timeout in milliseconds |
maxQueueSize |
number |
100 |
Maximum queued requests across all origins |
queueTimeout |
number |
30000 |
Queue timeout in milliseconds |
defaultTimeout |
number |
120000 |
Default timeout for all proxies in milliseconds |
defaultProxyTimeout |
number |
- | Default proxy-specific timeout in milliseconds |
Example:
http2ProxyPlugin({
// Global settings
maxSessions: 50,
sessionMaxAge: 2 * 60 * 1000, // 2 minutes
maxQueueSize: 200,
defaultTimeout: 30000, // 30 seconds
// Proxy routes
proxy: {
'/api': 'https://api.example.com'
}
})These options can be configured for each individual proxy route:
| Option | Type | Default | Description |
|---|---|---|---|
target |
string | object |
required | Backend server URL |
changeOrigin |
boolean |
true |
Changes the origin header to match the target |
ws |
boolean |
false |
Enable WebSocket proxy |
rewrite |
function |
- | Rewrite request paths |
configure |
function |
- | Custom proxy configuration callback |
bypass |
function |
- | Conditionally bypass the proxy |
secure |
boolean |
true |
Verify SSL certificates |
auth |
string |
- | Basic authentication credentials |
headers |
object |
- | Custom headers to add to requests |
forceHttp1 |
boolean |
false |
Force HTTP/1.1 protocol for this proxy |
autoDetectProtocol |
boolean |
false |
Auto-detect if origin supports HTTP/2 |
xfwd |
boolean |
true |
Add X-Forwarded-* headers |
preserveHeaderKeyCase |
boolean |
false |
Preserve original header key casing |
cookieDomainRewrite |
string | object |
- | Rewrite cookie domains |
cookiePathRewrite |
string | object |
- | Rewrite cookie paths |
router |
string | function |
- | Dynamic target routing |
timeout |
number |
global default | Proxy timeout in milliseconds (overrides global) |
proxyTimeout |
number |
global default | Proxy timeout in milliseconds (overrides global) |
selfHandleResponse |
boolean |
false |
Handle response manually |
followRedirects |
boolean |
false |
Follow HTTP redirects |
sse |
boolean |
false |
Optimize for Server-Sent Events |
Enable debug logging by setting the DEBUG environment variable:
DEBUG=vite:http2-proxy npm run devOr set LOG_LEVEL for more detailed logging:
LOG_LEVEL=debug npm run devThe plugin implements several performance optimizations:
- Connection Pooling: Reuses HTTP/2 connections across requests
- Automatic Cleanup: Removes idle connections after configurable timeout (default: 5 minutes)
- Connection Limits: Prevents resource exhaustion with configurable session limits (default: 100)
- Request Queueing: Handles high load with configurable queue size (default: 100 requests)
- Stream Management: Proper HTTP/2 stream lifecycle handling
- Timeout Handling: Configurable timeouts prevent hanging requests
This plugin maintains API compatibility with Vite's built-in proxy (which uses http-proxy). Simply install and add the plugin to migrate:
// vite.config.ts
import { defineConfig } from 'vite'
+import http2ProxyPlugin from 'vite-http2-proxy'
export default defineConfig({
+ plugins: [http2ProxyPlugin({
+ proxy: {
+ // Your existing proxy config works as-is,
+ // just move it into the plugin config
+ '/api': 'https://api.example.com'
+ }
})],
server: {
// Remove proxy config from here
}
})-
SSL Certificate Errors
// Disable SSL verification for development '/api': { target: 'https://self-signed.example.com', secure: false }
-
Cookie Issues
// Ensure cookies work on localhost '/api': { target: 'https://api.example.com', cookieDomainRewrite: 'localhost', cookiePathRewrite: '/' }
-
Timeout Errors
// Increase timeout for slow endpoints '/api': { target: 'https://slow-api.example.com', timeout: 300000 // 5 minutes }
MIT