mirror of
https://github.com/caddyserver/caddy.git
synced 2024-11-30 04:33:48 +08:00
91 lines
2.2 KiB
Go
91 lines
2.2 KiB
Go
package websockets
|
|
|
|
import (
|
|
"net"
|
|
"net/http"
|
|
"os/exec"
|
|
"strings"
|
|
|
|
"golang.org/x/net/websocket"
|
|
)
|
|
|
|
// WebSocket represents a web socket server instance. A WebSocket
|
|
// struct is instantiated for each new websocket request.
|
|
type WebSocket struct {
|
|
WSConfig
|
|
*http.Request
|
|
}
|
|
|
|
// Handle handles a WebSocket connection. It launches the
|
|
// specified command and streams input and output through
|
|
// the command's stdin and stdout.
|
|
func (ws WebSocket) Handle(conn *websocket.Conn) {
|
|
cmd := exec.Command(ws.Command, ws.Arguments...)
|
|
cmd.Stdin = conn
|
|
cmd.Stdout = conn
|
|
|
|
err := ws.buildEnv(cmd)
|
|
if err != nil {
|
|
// TODO
|
|
}
|
|
|
|
err = cmd.Run()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
// buildEnv sets the meta-variables for the child process according
|
|
// to the CGI 1.1 specification: http://tools.ietf.org/html/rfc3875#section-4.1
|
|
func (ws WebSocket) buildEnv(cmd *exec.Cmd) error {
|
|
remoteHost, remotePort, err := net.SplitHostPort(ws.RemoteAddr)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
serverHost, serverPort, err := net.SplitHostPort(ws.Host)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
cmd.Env = []string{
|
|
`AUTH_TYPE=`, // Not used
|
|
`CONTENT_LENGTH=`, // Not used
|
|
`CONTENT_TYPE=`, // Not used
|
|
`GATEWAY_INTERFACE=` + gatewayInterface,
|
|
`PATH_INFO=`, // TODO
|
|
`PATH_TRANSLATED=`, // TODO
|
|
`QUERY_STRING=` + ws.URL.RawQuery,
|
|
`REMOTE_ADDR=` + remoteHost,
|
|
`REMOTE_HOST=` + remoteHost, // TODO (Host lookups are slow; make this configurable)
|
|
`REMOTE_IDENT=`, // Not used
|
|
`REMOTE_PORT=` + remotePort,
|
|
`REMOTE_USER=`, // Not used,
|
|
`REQUEST_METHOD=` + ws.Method,
|
|
`REQUEST_URI=` + ws.RequestURI,
|
|
`SCRIPT_NAME=`, // TODO - absolute path to program being executed?
|
|
`SERVER_NAME=` + serverHost,
|
|
`SERVER_PORT=` + serverPort,
|
|
`SERVER_PROTOCOL=` + ws.Proto,
|
|
`SERVER_SOFTWARE=` + serverSoftware,
|
|
}
|
|
|
|
// Add each HTTP header to the environment as well
|
|
for header, values := range ws.Header {
|
|
value := strings.Join(values, ", ")
|
|
header = strings.ToUpper(header)
|
|
header = strings.Replace(header, "-", "_", -1)
|
|
value = strings.Replace(value, "\n", " ", -1)
|
|
cmd.Env = append(cmd.Env, "HTTP_"+header+"="+value)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
const (
|
|
// See CGI spec, 4.1.4
|
|
gatewayInterface = "caddy-CGI/1.1"
|
|
|
|
// See CGI spec, 4.1.17
|
|
serverSoftware = "caddy/0.1.0"
|
|
)
|