2022-12-08 13:05:19 -03:00

78 lines
2.1 KiB
Go

// Copyright (c) 2021 Gitpod GmbH. All rights reserved.
// Licensed under the GNU Affero General Public License (AGPL).
// See License.AGPL.txt in the project root for license information.
package secwebsocketkey
import (
"crypto/rand"
"encoding/base64"
"net/http"
"github.com/caddyserver/caddy/v2"
"github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
"github.com/caddyserver/caddy/v2/caddyconfig/httpcaddyfile"
"github.com/caddyserver/caddy/v2/modules/caddyhttp"
)
const (
secWebsocketKeyHeader = "Sec-WebSocket-Key"
secWebsocketKeyModule = "gitpod.sec_websocket_key"
)
func init() {
caddy.RegisterModule(SecWebsocketKey{})
httpcaddyfile.RegisterHandlerDirective(secWebsocketKeyModule, parseWebsocketCaddyfile)
}
// SecWebsocketKey implements an HTTP handler that adds a random sec-websocket-key if the header is missing
type SecWebsocketKey struct {
BaseDomain string `json:"base_domain,omitempty"`
Debug bool `json:"debug,omitempty"`
}
// CaddyModule returns the Caddy module information.
func (SecWebsocketKey) CaddyModule() caddy.ModuleInfo {
return caddy.ModuleInfo{
ID: "http.handlers.gitpod_sec_websocket_key",
New: func() caddy.Module { return new(SecWebsocketKey) },
}
}
// ServeHTTP implements caddyhttp.MiddlewareHandler.
func (m SecWebsocketKey) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error {
key := r.Header.Get(secWebsocketKeyHeader)
if key == "" {
buf := make([]byte, 20)
_, err := rand.Read(buf)
if err != nil {
return err
}
randomKey := base64.StdEncoding.EncodeToString(buf)
r.Header.Set(secWebsocketKeyHeader, randomKey)
}
return next.ServeHTTP(w, r)
}
// UnmarshalCaddyfile implements Caddyfile.Unmarshaler.
func (m *SecWebsocketKey) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
return nil
}
func parseWebsocketCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) {
m := new(SecWebsocketKey)
err := m.UnmarshalCaddyfile(h.Dispenser)
if err != nil {
return nil, err
}
return m, nil
}
// Interface guards
var (
_ caddyhttp.MiddlewareHandler = (*SecWebsocketKey)(nil)
_ caddyfile.Unmarshaler = (*SecWebsocketKey)(nil)
)