Overview
RoadRunner provides built-in support for HTTPS and HTTP/2 protocols. This guide explains how to configure secure connections and leverage advanced HTTP features.
HTTPS Configuration
Enable HTTPS by adding the ssl section within the http configuration block:
http:
# Server binding address
address: 127.0.0.1:8080
ssl:
# HTTPS binding address (defaults to :443)
address: :8892
redirect: false
cert: fixtures/server.crt
key: fixtures/server.key
root_ca: root.crt
# HTTP/2 configuration
http2:
h2c: false
max_concurrent_streams: 128
Forcing HTTPS Redirects
To automatically redirect incoming http:// requests to https://, enable the redirect option:
http:
ssl:
redirect: true
HTTP/2 Server Push
RoadRunner supports HTTP/2 push functionality through a special header provided in the PHP response. This allows sending resources to the client before they are requested:
// PHP example
return $response->withAddedHeader('http2-push', '/ styles.css');
Note that resource paths must be relative to the public application directory and must start with a forward slash.
Important: HTTP/2 push only functions when serving static content over HTTPS.
H2C (HTTP/2 over Clear Text)
You can enable HTTP/2 support over unencrypted TCP connections using H2C:
http:
http2:
h2c: true
FastCGI Frontend
The HTTP module includes FastCGI frontend support, which can be enabled as follows:
http:
# HTTP service provides FastCGI as frontend
fcgi:
# FastCGI connection DSN. Supports TCP and Unix sockets.
address: tcp://0.0.0.0:6920
Root Certificate Authority
Configure root CA support in your .rr.yaml file:
http:
ssl:
root_ca: root.crt
Serving Static Files
RoadRunner can serve static content directly without involving PHP workers.
Basic Configuration
Enable static content serving using the static block within the http section:
http:
address: 127.0.0.1:44933
static:
dir: "."
forbid: [""]
allow: [".txt", ".php"]
calculate_etag: false
weak: false
request:
input: "custom-header"
response:
output: "output-header"
Configuration parameters explained:
dir: Directory path containing static files.forbid: File extensions that should not be served.allow: File extensions permitted for serving. If empty, all files except forbidden ones are served. When an extention appears in bothallowandforbid, its treated as forbidden.calculate_etag: Enable ETag calculation for static files.weak: Use weak ETag generator (/W) which only uses filename for CRC32. When false, uses full file content for checksum.request/response: Custom headers for static file requests and responses.
Combining with Other Middleware
To combine static content with other middleware, configure them in sequence. Note that static middleware always executes last, with the file server applying headers and gzip plugins:
http:
address: 127.0.0.1:44933
middleware: [ "headers", "gzip" ]
headers:
# configuration...
static:
dir: "."
forbid: [""]
allow: [".txt", ".php"]
calculate_etag: false
weak: false
Headers and CORS Configuration
RoadRunner can automatically manage request/response headers and handle Cross-Origin Resource Sharing (CORS).
CORS Setup
Enable CORS headers by adding the following configuration:
http:
address: 127.0.0.1:44933
middleware: ["headers"]
headers:
cors:
allowed_origin: "*"
allowed_headers: "*"
allowed_methods: "GET,POST,PUT,DELETE"
allow_credentials: true
exposed_headers: "Cache-Control,Content-Language,Content-Type,Expires,Last-Modified,Pragma"
max_age: 600
Note: You must declare the "headers" middleware in your configuration.
Custom Headers
Configure custom headers for incoming requests and outgoing responses:
http:
headers:
# Headers added to every request sent to PHP
request:
Example-Request-Header: "Value"
# Headers added to every response
response:
X-Powered-By: "RoadRunner"
Custom HTTP Middleware
RoadRunner's HTTP server uses Go's standard middleware pattern, allowing extension through custom or community-provided middleware plugins.
Middleware Implementation
A basic middleware implementation structure:
package middleware
import (
"net/http"
)
const PluginName = "customMiddleware"
type CustomMiddleware struct{}
// Initialize the middleware plugin
func (m *CustomMiddleware) Init() error {
return nil
}
// Middleware handler function
func (m *CustomMiddleware) Middleware(next http.Handler) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// Process the request
// Call next handler
next.ServeHTTP(w, r)
}
}
// Plugin name identification
func (m *CustomMiddleware) Name() string {
return PluginName
}
Ensure your middleware implements the required interface and provides a unique name.
Registering Middleware
Register the middleware service in your main.go file to resolve dependencies correctly:
container, err := endure.NewContainer(nil, endure.SetLogLevel(endure.ErrorLevel), endure.RetryOnFail(false))
if err != nil {
panic(err)
}
// Register HTTP service
err = container.Register(&http.Service{})
if err != nil {
panic(err)
}
// Register custom service
err = container.Register(&custom.Service{})
if err != nil {
panic(err)
}
// Register middleware
err = container.RegisterAll(
&middleware.CustomMiddleware{},
)
Using PSR7 Attributes
Pass values securely through the request attributes using the attributes package:
func (s *Service) middleware(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
attributes.Set(r, "key", "value")
next(w, r)
}
}
These attributes can then be accessed via ServerRequestInterface->getAttributes() in your PHP application.