summaryrefslogtreecommitdiff
path: root/plugins/http
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/http')
-rw-r--r--plugins/http/config/fcgi.go7
-rw-r--r--plugins/http/config/http.go (renamed from plugins/http/config.go)158
-rw-r--r--plugins/http/config/http2.go28
-rw-r--r--plugins/http/config/ip.go26
-rw-r--r--plugins/http/config/ssl.go19
-rw-r--r--plugins/http/config/uploads_config.go (renamed from plugins/http/uploads_config.go)12
-rw-r--r--plugins/http/handler.go15
-rw-r--r--plugins/http/parse.go4
-rw-r--r--plugins/http/plugin.go39
-rw-r--r--plugins/http/request.go3
-rw-r--r--plugins/http/uploads.go5
11 files changed, 161 insertions, 155 deletions
diff --git a/plugins/http/config/fcgi.go b/plugins/http/config/fcgi.go
new file mode 100644
index 00000000..3d4acbe1
--- /dev/null
+++ b/plugins/http/config/fcgi.go
@@ -0,0 +1,7 @@
+package config
+
+// FCGI for FastCGI server.
+type FCGI struct {
+ // Address and port to handle as http server.
+ Address string
+}
diff --git a/plugins/http/config.go b/plugins/http/config/http.go
index e272e550..76547fde 100644
--- a/plugins/http/config.go
+++ b/plugins/http/config/http.go
@@ -1,4 +1,4 @@
-package http
+package config
import (
"net"
@@ -11,42 +11,19 @@ import (
poolImpl "github.com/spiral/roadrunner/v2/pkg/pool"
)
-// Cidrs is a slice of IPNet addresses
-type Cidrs []*net.IPNet
-
-// IsTrusted checks if the ip address exists in the provided in the config addresses
-func (c *Cidrs) IsTrusted(ip string) bool {
- if len(*c) == 0 {
- return false
- }
-
- i := net.ParseIP(ip)
- if i == nil {
- return false
- }
-
- for _, cird := range *c {
- if cird.Contains(i) {
- return true
- }
- }
-
- return false
-}
-
-// Config configures RoadRunner HTTP server.
-type Config struct {
+// HTTP configures RoadRunner HTTP server.
+type HTTP struct {
// Port and port to handle as http server.
Address string
- // SSL defines https server options.
- SSL *SSLConfig
+ // SSLConfig defines https server options.
+ SSLConfig *SSL `mapstructure:"ssl"`
- // FCGI configuration. You can use FastCGI without HTTP server.
- FCGI *FCGIConfig
+ // FCGIConfig configuration. You can use FastCGI without HTTP server.
+ FCGIConfig *FCGI `mapstructure:"fcgi"`
- // HTTP2 configuration
- HTTP2 *HTTP2Config
+ // HTTP2Config configuration
+ HTTP2Config *HTTP2 `mapstructure:"http2"`
// MaxRequestSize specified max size for payload body in megabytes, set 0 to unlimited.
MaxRequestSize uint64 `mapstructure:"max_request_size"`
@@ -55,7 +32,7 @@ type Config struct {
TrustedSubnets []string `mapstructure:"trusted_subnets"`
// Uploads configures uploads configuration.
- Uploads *UploadsConfig
+ Uploads *Uploads `mapstructure:"uploads"`
// Pool configures worker pool.
Pool *poolImpl.Config `mapstructure:"pool"`
@@ -67,80 +44,31 @@ type Config struct {
Middleware []string
// slice of net.IPNet
- cidrs Cidrs
-}
-
-// FCGIConfig for FastCGI server.
-type FCGIConfig struct {
- // Address and port to handle as http server.
- Address string
-}
-
-// HTTP2Config HTTP/2 server customizations.
-type HTTP2Config struct {
- // Enable or disable HTTP/2 extension, default enable.
- Enabled bool
-
- // H2C enables HTTP/2 over TCP
- H2C bool
-
- // MaxConcurrentStreams defaults to 128.
- MaxConcurrentStreams uint32 `mapstructure:"max_concurrent_streams"`
-}
-
-// InitDefaults sets default values for HTTP/2 configuration.
-func (cfg *HTTP2Config) InitDefaults() error {
- cfg.Enabled = true
- cfg.MaxConcurrentStreams = 128
-
- return nil
-}
-
-// SSLConfig defines https server configuration.
-type SSLConfig struct {
- // Port to listen as HTTPS server, defaults to 443.
- Port int
-
- // Redirect when enabled forces all http connections to switch to https.
- Redirect bool
-
- // Key defined private server key.
- Key string
-
- // Cert is https certificate.
- Cert string
-
- // Root CA file
- RootCA string
+ Cidrs Cidrs
}
// EnableHTTP is true when http server must run.
-func (c *Config) EnableHTTP() bool {
+func (c *HTTP) EnableHTTP() bool {
return c.Address != ""
}
// EnableTLS returns true if pool must listen TLS connections.
-func (c *Config) EnableTLS() bool {
- return c.SSL.Key != "" || c.SSL.Cert != "" || c.SSL.RootCA != ""
-}
-
-// EnableHTTP2 when HTTP/2 extension must be enabled (only with TSL).
-func (c *Config) EnableHTTP2() bool {
- return c.HTTP2.Enabled
+func (c *HTTP) EnableTLS() bool {
+ return c.SSLConfig.Key != "" || c.SSLConfig.Cert != "" || c.SSLConfig.RootCA != ""
}
// EnableH2C when HTTP/2 extension must be enabled on TCP.
-func (c *Config) EnableH2C() bool {
- return c.HTTP2.H2C
+func (c *HTTP) EnableH2C() bool {
+ return c.HTTP2Config.H2C
}
// EnableFCGI is true when FastCGI server must be enabled.
-func (c *Config) EnableFCGI() bool {
- return c.FCGI.Address != ""
+func (c *HTTP) EnableFCGI() bool {
+ return c.FCGIConfig.Address != ""
}
-// InitDefaults must populate Config values using given Config source. Must return error if Config is not valid.
-func (c *Config) InitDefaults() error {
+// InitDefaults must populate HTTP values using given HTTP source. Must return error if HTTP is not valid.
+func (c *HTTP) InitDefaults() error {
if c.Pool == nil {
// default pool
c.Pool = &poolImpl.Config{
@@ -153,27 +81,27 @@ func (c *Config) InitDefaults() error {
}
}
- if c.HTTP2 == nil {
- c.HTTP2 = &HTTP2Config{}
+ if c.HTTP2Config == nil {
+ c.HTTP2Config = &HTTP2{}
}
- if c.FCGI == nil {
- c.FCGI = &FCGIConfig{}
+ if c.FCGIConfig == nil {
+ c.FCGIConfig = &FCGI{}
}
if c.Uploads == nil {
- c.Uploads = &UploadsConfig{}
+ c.Uploads = &Uploads{}
}
- if c.SSL == nil {
- c.SSL = &SSLConfig{}
+ if c.SSLConfig == nil {
+ c.SSLConfig = &SSL{}
}
- if c.SSL.Port == 0 {
- c.SSL.Port = 443
+ if c.SSLConfig.Port == 0 {
+ c.SSLConfig.Port = 443
}
- err := c.HTTP2.InitDefaults()
+ err := c.HTTP2Config.InitDefaults()
if err != nil {
return err
}
@@ -199,7 +127,7 @@ func (c *Config) InitDefaults() error {
if err != nil {
return err
}
- c.cidrs = cidrs
+ c.Cidrs = cidrs
return c.Valid()
}
@@ -220,8 +148,8 @@ func ParseCIDRs(subnets []string) (Cidrs, error) {
}
// IsTrusted if api can be trusted to use X-Real-Ip, X-Forwarded-For
-func (c *Config) IsTrusted(ip string) bool {
- if c.cidrs == nil {
+func (c *HTTP) IsTrusted(ip string) bool {
+ if c.Cidrs == nil {
return false
}
@@ -230,7 +158,7 @@ func (c *Config) IsTrusted(ip string) bool {
return false
}
- for _, cird := range c.cidrs {
+ for _, cird := range c.Cidrs {
if cird.Contains(i) {
return true
}
@@ -240,13 +168,13 @@ func (c *Config) IsTrusted(ip string) bool {
}
// Valid validates the configuration.
-func (c *Config) Valid() error {
+func (c *HTTP) Valid() error {
const op = errors.Op("validation")
if c.Uploads == nil {
return errors.E(op, errors.Str("malformed uploads config"))
}
- if c.HTTP2 == nil {
+ if c.HTTP2Config == nil {
return errors.E(op, errors.Str("malformed http2 config"))
}
@@ -263,27 +191,27 @@ func (c *Config) Valid() error {
}
if c.EnableTLS() {
- if _, err := os.Stat(c.SSL.Key); err != nil {
+ if _, err := os.Stat(c.SSLConfig.Key); err != nil {
if os.IsNotExist(err) {
- return errors.E(op, errors.Errorf("key file '%s' does not exists", c.SSL.Key))
+ return errors.E(op, errors.Errorf("key file '%s' does not exists", c.SSLConfig.Key))
}
return err
}
- if _, err := os.Stat(c.SSL.Cert); err != nil {
+ if _, err := os.Stat(c.SSLConfig.Cert); err != nil {
if os.IsNotExist(err) {
- return errors.E(op, errors.Errorf("cert file '%s' does not exists", c.SSL.Cert))
+ return errors.E(op, errors.Errorf("cert file '%s' does not exists", c.SSLConfig.Cert))
}
return err
}
// RootCA is optional, but if provided - check it
- if c.SSL.RootCA != "" {
- if _, err := os.Stat(c.SSL.RootCA); err != nil {
+ if c.SSLConfig.RootCA != "" {
+ if _, err := os.Stat(c.SSLConfig.RootCA); err != nil {
if os.IsNotExist(err) {
- return errors.E(op, errors.Errorf("root ca path provided, but path '%s' does not exists", c.SSL.RootCA))
+ return errors.E(op, errors.Errorf("root ca path provided, but path '%s' does not exists", c.SSLConfig.RootCA))
}
return err
}
diff --git a/plugins/http/config/http2.go b/plugins/http/config/http2.go
new file mode 100644
index 00000000..b1e109e9
--- /dev/null
+++ b/plugins/http/config/http2.go
@@ -0,0 +1,28 @@
+package config
+
+// HTTP2 HTTP/2 server customizations.
+type HTTP2 struct {
+ // h2cHandler is a Handler which implements h2c by hijacking the HTTP/1 traffic
+ // that should be h2c traffic. There are two ways to begin a h2c connection
+ // (RFC 7540 Section 3.2 and 3.4): (1) Starting with Prior Knowledge - this
+ // works by starting an h2c connection with a string of bytes that is valid
+ // HTTP/1, but unlikely to occur in practice and (2) Upgrading from HTTP/1 to
+ // h2c - this works by using the HTTP/1 Upgrade header to request an upgrade to
+ // h2c. When either of those situations occur we hijack the HTTP/1 connection,
+ // convert it to a HTTP/2 connection and pass the net.Conn to http2.ServeConn.
+
+ // H2C enables HTTP/2 over TCP
+ H2C bool
+
+ // MaxConcurrentStreams defaults to 128.
+ MaxConcurrentStreams uint32 `mapstructure:"max_concurrent_streams"`
+}
+
+// InitDefaults sets default values for HTTP/2 configuration.
+func (cfg *HTTP2) InitDefaults() error {
+ if cfg.MaxConcurrentStreams == 0 {
+ cfg.MaxConcurrentStreams = 128
+ }
+
+ return nil
+}
diff --git a/plugins/http/config/ip.go b/plugins/http/config/ip.go
new file mode 100644
index 00000000..c4981f74
--- /dev/null
+++ b/plugins/http/config/ip.go
@@ -0,0 +1,26 @@
+package config
+
+import "net"
+
+// Cidrs is a slice of IPNet addresses
+type Cidrs []*net.IPNet
+
+// IsTrusted checks if the ip address exists in the provided in the config addresses
+func (c *Cidrs) IsTrusted(ip string) bool {
+ if len(*c) == 0 {
+ return false
+ }
+
+ i := net.ParseIP(ip)
+ if i == nil {
+ return false
+ }
+
+ for _, cird := range *c {
+ if cird.Contains(i) {
+ return true
+ }
+ }
+
+ return false
+}
diff --git a/plugins/http/config/ssl.go b/plugins/http/config/ssl.go
new file mode 100644
index 00000000..aae6e920
--- /dev/null
+++ b/plugins/http/config/ssl.go
@@ -0,0 +1,19 @@
+package config
+
+// SSL defines https server configuration.
+type SSL struct {
+ // Port to listen as HTTPS server, defaults to 443.
+ Port int
+
+ // Redirect when enabled forces all http connections to switch to https.
+ Redirect bool
+
+ // Key defined private server key.
+ Key string
+
+ // Cert is https certificate.
+ Cert string
+
+ // Root CA file
+ RootCA string
+}
diff --git a/plugins/http/uploads_config.go b/plugins/http/config/uploads_config.go
index 4c20c8e8..5edb0ab7 100644
--- a/plugins/http/uploads_config.go
+++ b/plugins/http/config/uploads_config.go
@@ -1,4 +1,4 @@
-package http
+package config
import (
"os"
@@ -6,8 +6,8 @@ import (
"strings"
)
-// UploadsConfig describes file location and controls access to them.
-type UploadsConfig struct {
+// Uploads describes file location and controls access to them.
+type Uploads struct {
// Dir contains name of directory to control access to.
Dir string
@@ -17,14 +17,14 @@ type UploadsConfig struct {
}
// InitDefaults sets missing values to their default values.
-func (cfg *UploadsConfig) InitDefaults() error {
+func (cfg *Uploads) InitDefaults() error {
cfg.Forbid = []string{".php", ".exe", ".bat"}
cfg.Dir = os.TempDir()
return nil
}
// TmpDir returns temporary directory.
-func (cfg *UploadsConfig) TmpDir() string {
+func (cfg *Uploads) TmpDir() string {
if cfg.Dir != "" {
return cfg.Dir
}
@@ -33,7 +33,7 @@ func (cfg *UploadsConfig) TmpDir() string {
}
// Forbids must return true if file extension is not allowed for the upload.
-func (cfg *UploadsConfig) Forbids(filename string) bool {
+func (cfg *Uploads) Forbids(filename string) bool {
ext := strings.ToLower(path.Ext(filename))
for _, v := range cfg.Forbid {
diff --git a/plugins/http/handler.go b/plugins/http/handler.go
index 3e21ab2b..ecdcb2c0 100644
--- a/plugins/http/handler.go
+++ b/plugins/http/handler.go
@@ -12,17 +12,10 @@ import (
"github.com/spiral/errors"
"github.com/spiral/roadrunner/v2/interfaces/events"
"github.com/spiral/roadrunner/v2/interfaces/pool"
+ "github.com/spiral/roadrunner/v2/plugins/http/config"
"github.com/spiral/roadrunner/v2/plugins/logger"
)
-const (
- // EventResponse thrown after the request been processed. See ErrorEvent as payload.
- EventResponse = iota + 500
-
- // EventError thrown on any non job error provided by road runner server.
- EventError
-)
-
// MB is 1024 bytes
const MB uint64 = 1024 * 1024
@@ -66,8 +59,8 @@ func (e *ResponseEvent) Elapsed() time.Duration {
// parsed files and query, payload will include parsed form dataTree (if any).
type Handler struct {
maxRequestSize uint64
- uploads UploadsConfig
- trusted Cidrs
+ uploads config.Uploads
+ trusted config.Cidrs
log logger.Logger
pool pool.Pool
mul sync.Mutex
@@ -75,7 +68,7 @@ type Handler struct {
}
// NewHandler return handle interface implementation
-func NewHandler(maxReqSize uint64, uploads UploadsConfig, trusted Cidrs, pool pool.Pool) (*Handler, error) {
+func NewHandler(maxReqSize uint64, uploads config.Uploads, trusted config.Cidrs, pool pool.Pool) (*Handler, error) {
if pool == nil {
return nil, errors.E(errors.Str("pool should be initialized"))
}
diff --git a/plugins/http/parse.go b/plugins/http/parse.go
index d4a1604b..780e1279 100644
--- a/plugins/http/parse.go
+++ b/plugins/http/parse.go
@@ -2,6 +2,8 @@ package http
import (
"net/http"
+
+ "github.com/spiral/roadrunner/v2/plugins/http/config"
)
// MaxLevel defines maximum tree depth for incoming request data and files.
@@ -60,7 +62,7 @@ func (d dataTree) mount(i []string, v []string) {
}
// parse incoming dataTree request into JSON (including contentMultipart form dataTree)
-func parseUploads(r *http.Request, cfg UploadsConfig) *Uploads {
+func parseUploads(r *http.Request, cfg config.Uploads) *Uploads {
u := &Uploads{
cfg: cfg,
tree: make(fileTree),
diff --git a/plugins/http/plugin.go b/plugins/http/plugin.go
index d9c1729e..35acd2b7 100644
--- a/plugins/http/plugin.go
+++ b/plugins/http/plugin.go
@@ -21,6 +21,7 @@ import (
"github.com/spiral/roadrunner/v2/plugins/checker"
"github.com/spiral/roadrunner/v2/plugins/config"
"github.com/spiral/roadrunner/v2/plugins/http/attributes"
+ httpConfig "github.com/spiral/roadrunner/v2/plugins/http/config"
"github.com/spiral/roadrunner/v2/plugins/logger"
"github.com/spiral/roadrunner/v2/plugins/server"
"github.com/spiral/roadrunner/v2/utils"
@@ -52,7 +53,7 @@ type Plugin struct {
server server.Server
log logger.Logger
- cfg *Config `mapstructure:"http"`
+ cfg *httpConfig.HTTP `mapstructure:"http"`
// middlewares to chain
mdwr middleware
@@ -72,16 +73,15 @@ type Plugin struct {
// misconfiguration. Services must not be used without proper configuration pushed first.
func (s *Plugin) Init(cfg config.Configurer, log logger.Logger, server server.Server) error {
const op = errors.Op("http_plugin_init")
+ if !cfg.Has(PluginName) {
+ return errors.E(op, errors.Disabled)
+ }
+
err := cfg.UnmarshalKey(PluginName, &s.cfg)
if err != nil {
return errors.E(op, err)
}
- // if no HTTP section in config - disable HTTP
- if s.cfg == nil {
- return errors.E(op, errors.Disabled)
- }
-
err = s.cfg.InitDefaults()
if err != nil {
return errors.E(op, err)
@@ -142,7 +142,7 @@ func (s *Plugin) Serve() chan error {
s.handler, err = NewHandler(
s.cfg.MaxRequestSize,
*s.cfg.Uploads,
- s.cfg.cidrs,
+ s.cfg.Cidrs,
s.pool,
)
if err != nil {
@@ -162,7 +162,7 @@ func (s *Plugin) Serve() chan error {
if s.cfg.EnableTLS() {
s.https = s.initSSL()
- if s.cfg.SSL.RootCA != "" {
+ if s.cfg.SSLConfig.RootCA != "" {
err = s.appendRootCa()
if err != nil {
errCh <- errors.E(op, err)
@@ -170,7 +170,8 @@ func (s *Plugin) Serve() chan error {
}
}
- if s.cfg.EnableHTTP2() {
+ // if HTTP2Config not nil
+ if s.cfg.HTTP2Config != nil {
if err := s.initHTTP2(); err != nil {
errCh <- errors.E(op, err)
return errCh
@@ -200,8 +201,8 @@ func (s *Plugin) Serve() chan error {
if s.https != nil {
go func() {
httpErr := s.https.ListenAndServeTLS(
- s.cfg.SSL.Cert,
- s.cfg.SSL.Key,
+ s.cfg.SSLConfig.Cert,
+ s.cfg.SSLConfig.Key,
)
if httpErr != nil && httpErr != http.ErrServerClosed {
@@ -322,7 +323,7 @@ func (s *Plugin) Reset() error {
s.handler, err = NewHandler(
s.cfg.MaxRequestSize,
*s.cfg.Uploads,
- s.cfg.cidrs,
+ s.cfg.Cidrs,
s.pool,
)
if err != nil {
@@ -362,7 +363,7 @@ func (s *Plugin) Status() checker.Status {
}
func (s *Plugin) redirect(w http.ResponseWriter, r *http.Request) bool {
- if s.https != nil && r.TLS == nil && s.cfg.SSL.Redirect {
+ if s.https != nil && r.TLS == nil && s.cfg.SSLConfig.Redirect {
target := &url.URL{
Scheme: "https",
Host: s.tlsAddr(r.Host, false),
@@ -396,7 +397,7 @@ func (s *Plugin) appendRootCa() error {
rootCAs = x509.NewCertPool()
}
- CA, err := ioutil.ReadFile(s.cfg.SSL.RootCA)
+ CA, err := ioutil.ReadFile(s.cfg.SSLConfig.RootCA)
if err != nil {
return err
}
@@ -489,13 +490,13 @@ func (s *Plugin) initSSL() *http.Server {
// init http/2 server
func (s *Plugin) initHTTP2() error {
return http2.ConfigureServer(s.https, &http2.Server{
- MaxConcurrentStreams: s.cfg.HTTP2.MaxConcurrentStreams,
+ MaxConcurrentStreams: s.cfg.HTTP2Config.MaxConcurrentStreams,
})
}
// serveFCGI starts FastCGI server.
func (s *Plugin) serveFCGI() error {
- l, err := utils.CreateListener(s.cfg.FCGI.Address)
+ l, err := utils.CreateListener(s.cfg.FCGIConfig.Address)
if err != nil {
return err
}
@@ -508,13 +509,13 @@ func (s *Plugin) serveFCGI() error {
return nil
}
-// tlsAddr replaces listen or host port with port configured by SSL config.
+// tlsAddr replaces listen or host port with port configured by SSLConfig config.
func (s *Plugin) tlsAddr(host string, forcePort bool) string {
// remove current forcePort first
host = strings.Split(host, ":")[0]
- if forcePort || s.cfg.SSL.Port != 443 {
- host = fmt.Sprintf("%s:%v", host, s.cfg.SSL.Port)
+ if forcePort || s.cfg.SSLConfig.Port != 443 {
+ host = fmt.Sprintf("%s:%v", host, s.cfg.SSLConfig.Port)
}
return host
diff --git a/plugins/http/request.go b/plugins/http/request.go
index 3983fdde..a1398819 100644
--- a/plugins/http/request.go
+++ b/plugins/http/request.go
@@ -11,6 +11,7 @@ import (
j "github.com/json-iterator/go"
"github.com/spiral/roadrunner/v2/pkg/payload"
"github.com/spiral/roadrunner/v2/plugins/http/attributes"
+ "github.com/spiral/roadrunner/v2/plugins/http/config"
"github.com/spiral/roadrunner/v2/plugins/logger"
)
@@ -70,7 +71,7 @@ func fetchIP(pair string) string {
}
// NewRequest creates new PSR7 compatible request using net/http request.
-func NewRequest(r *http.Request, cfg UploadsConfig) (*Request, error) {
+func NewRequest(r *http.Request, cfg config.Uploads) (*Request, error) {
req := &Request{
RemoteAddr: fetchIP(r.RemoteAddr),
Protocol: r.Proto,
diff --git a/plugins/http/uploads.go b/plugins/http/uploads.go
index d5196844..f9f8e1c8 100644
--- a/plugins/http/uploads.go
+++ b/plugins/http/uploads.go
@@ -1,6 +1,7 @@
package http
import (
+ "github.com/spiral/roadrunner/v2/plugins/http/config"
"github.com/spiral/roadrunner/v2/plugins/logger"
"io"
@@ -30,7 +31,7 @@ const (
// Uploads tree manages uploaded files tree and temporary files.
type Uploads struct {
// associated temp directory and forbidden extensions.
- cfg UploadsConfig
+ cfg config.Uploads
// pre processed data tree for Uploads.
tree fileTree
@@ -112,7 +113,7 @@ func NewUpload(f *multipart.FileHeader) *FileUpload {
// STACK
// DEFER FILE CLOSE (2)
// DEFER TMP CLOSE (1)
-func (f *FileUpload) Open(cfg UploadsConfig) (err error) {
+func (f *FileUpload) Open(cfg config.Uploads) (err error) {
if cfg.Forbids(f.Name) {
f.Error = UploadErrorExtension
return nil