mirror of
				https://github.com/caddyserver/caddy.git
				synced 2025-10-30 10:12:45 -04:00 
			
		
		
		
	Added WebSocket middleware
This commit is contained in:
		
							parent
							
								
									974acbf38c
								
							
						
					
					
						commit
						811c6a986f
					
				| @ -10,6 +10,7 @@ import ( | ||||
| 	"github.com/mholt/caddy/middleware/proxy" | ||||
| 	"github.com/mholt/caddy/middleware/redirect" | ||||
| 	"github.com/mholt/caddy/middleware/rewrite" | ||||
| 	"github.com/mholt/caddy/middleware/websockets" | ||||
| ) | ||||
| 
 | ||||
| // This init function registers middleware. Register middleware | ||||
| @ -24,6 +25,7 @@ func init() { | ||||
| 	register("ext", extensionless.New) | ||||
| 	register("proxy", proxy.New) | ||||
| 	register("fastcgi", fastcgi.New) | ||||
| 	register("websocket", websockets.New) | ||||
| } | ||||
| 
 | ||||
| var ( | ||||
|  | ||||
							
								
								
									
										32
									
								
								middleware/websockets/websocket.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								middleware/websockets/websocket.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,32 @@ | ||||
| package websockets | ||||
| 
 | ||||
| import ( | ||||
| 	"os/exec" | ||||
| 
 | ||||
| 	"golang.org/x/net/websocket" | ||||
| ) | ||||
| 
 | ||||
| // WebSocket represents a web socket server configuration. | ||||
| type WebSocket struct { | ||||
| 	Path      string | ||||
| 	Command   string | ||||
| 	Arguments []string | ||||
| } | ||||
| 
 | ||||
| // 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 | ||||
| 
 | ||||
| 	// TODO: Set environment variables according to CGI 1.1 | ||||
| 	// cf. http://tools.ietf.org/html/rfc3875#section-4.1.4 | ||||
| 	cmd.Env = append(cmd.Env, `GATEWAY_INTERFACE="caddy-CGI/1.1"`) | ||||
| 
 | ||||
| 	err := cmd.Run() | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										87
									
								
								middleware/websockets/websockets.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								middleware/websockets/websockets.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,87 @@ | ||||
| // Package websockets implements a WebSocket server by executing | ||||
| // a command and piping its input and output through the WebSocket | ||||
| // connection. | ||||
| package websockets | ||||
| 
 | ||||
| import ( | ||||
| 	"log" | ||||
| 	"net/http" | ||||
| 
 | ||||
| 	"github.com/flynn/go-shlex" | ||||
| 	"github.com/mholt/caddy/middleware" | ||||
| 	"golang.org/x/net/websocket" | ||||
| ) | ||||
| 
 | ||||
| // WebSockets is a type which holds configuration | ||||
| // for the websocket middleware collectively. | ||||
| type WebSockets struct { | ||||
| 	Sockets []WebSocket | ||||
| } | ||||
| 
 | ||||
| // ServeHTTP more or less converts the HTTP request to a WebSocket connection. | ||||
| func (ws WebSockets) ServeHTTP(w http.ResponseWriter, r *http.Request) { | ||||
| 	for _, socket := range ws.Sockets { | ||||
| 		if middleware.Path(r.URL.Path).Matches(socket.Path) { | ||||
| 			websocket.Handler(socket.Handle).ServeHTTP(w, r) | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // New constructs and configures a new websockets middleware instance. | ||||
| func New(c middleware.Controller) (middleware.Middleware, error) { | ||||
| 	var websocks []WebSocket | ||||
| 
 | ||||
| 	var path string | ||||
| 	var command string | ||||
| 
 | ||||
| 	for c.Next() { | ||||
| 		var val string | ||||
| 
 | ||||
| 		// Path or command; not sure which yet | ||||
| 		if !c.NextArg() { | ||||
| 			return nil, c.ArgErr() | ||||
| 		} | ||||
| 		val = c.Val() | ||||
| 
 | ||||
| 		// The rest of the arguments are the command | ||||
| 		if c.NextArg() { | ||||
| 			path = val | ||||
| 			command = c.Val() | ||||
| 			for c.NextArg() { | ||||
| 				command += " " + c.Val() | ||||
| 			} | ||||
| 		} else { | ||||
| 			path = "/" | ||||
| 			command = val | ||||
| 		} | ||||
| 
 | ||||
| 		// Split command into the actual command and its arguments | ||||
| 		var cmd string | ||||
| 		var args []string | ||||
| 
 | ||||
| 		parts, err := shlex.Split(command) | ||||
| 		if err != nil { | ||||
| 			log.Fatal("Error parsing command for websocket use: " + err.Error()) | ||||
| 		} else if len(parts) == 0 { | ||||
| 			log.Fatal("No command found for use by websocket.") | ||||
| 		} | ||||
| 
 | ||||
| 		cmd = parts[0] | ||||
| 		if len(parts) > 1 { | ||||
| 			args = parts[1:] | ||||
| 		} | ||||
| 
 | ||||
| 		websocks = append(websocks, WebSocket{ | ||||
| 			Path:      path, | ||||
| 			Command:   cmd, | ||||
| 			Arguments: args, | ||||
| 		}) | ||||
| 	} | ||||
| 
 | ||||
| 	return func(next http.HandlerFunc) http.HandlerFunc { | ||||
| 		// We don't use next because websockets aren't HTTP, | ||||
| 		// so we don't invoke other middleware after this. | ||||
| 		return WebSockets{Sockets: websocks}.ServeHTTP | ||||
| 	}, nil | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user