From 3f78d76da1f114d4e0e50f8ed3ed19fda980342d Mon Sep 17 00:00:00 2001 From: Junegunn Choi Date: Sat, 4 Nov 2023 16:06:59 +0900 Subject: Allow accepting remote connections Close #3498 # FZF_API_KEY is required for a non-localhost listen address FZF_API_KEY=xxx fzf --listen 0.0.0.0:6266 --- src/server.go | 55 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 16 deletions(-) (limited to 'src/server.go') diff --git a/src/server.go b/src/server.go index 8fc605ac..a89c5e08 100644 --- a/src/server.go +++ b/src/server.go @@ -26,12 +26,13 @@ type getParams struct { } const ( - crlf = "\r\n" - httpOk = "HTTP/1.1 200 OK" + crlf - httpBadRequest = "HTTP/1.1 400 Bad Request" + crlf - httpUnauthorized = "HTTP/1.1 401 Unauthorized" + crlf - httpReadTimeout = 10 * time.Second - maxContentLength = 1024 * 1024 + crlf = "\r\n" + httpOk = "HTTP/1.1 200 OK" + crlf + httpBadRequest = "HTTP/1.1 400 Bad Request" + crlf + httpUnauthorized = "HTTP/1.1 401 Unauthorized" + crlf + httpReadTimeout = 10 * time.Second + maxContentLength = 1024 * 1024 + defaultListenAddr = "localhost:0" ) type httpServer struct { @@ -40,30 +41,52 @@ type httpServer struct { responseChannel chan string } -func startHttpServer(port int, actionChannel chan []*action, responseChannel chan string) (error, int) { - if port < 0 { - return nil, port +func parseListenAddress(address string) (error, string, int) { + parts := strings.SplitN(address, ":", 3) + if len(parts) == 1 { + parts = []string{"localhost", parts[0]} } + if len(parts) != 2 { + return fmt.Errorf("invalid listen address: %s", address), "", 0 + } + portStr := parts[len(parts)-1] + port, err := strconv.Atoi(portStr) + if err != nil || port < 0 || port > 65535 { + return fmt.Errorf("invalid listen port: %s", portStr), "", 0 + } + if len(parts[0]) == 0 { + parts[0] = "localhost" + } + return nil, parts[0], port +} - listener, err := net.Listen("tcp", fmt.Sprintf("localhost:%d", port)) +func startHttpServer(address string, actionChannel chan []*action, responseChannel chan string) (error, int) { + err, host, port := parseListenAddress(address) + if err != nil { + return err, port + } + + apiKey := os.Getenv("FZF_API_KEY") + if host != "localhost" && host != "127.0.0.1" && len(apiKey) == 0 { + return fmt.Errorf("FZF_API_KEY is required for remote access"), port + } + listener, err := net.Listen("tcp", fmt.Sprintf("%s:%d", host, port)) if err != nil { - return fmt.Errorf("port not available: %d", port), port + return fmt.Errorf("failed to listen on %s", address), port } if port == 0 { addr := listener.Addr().String() - parts := strings.SplitN(addr, ":", 2) + parts := strings.Split(addr, ":") if len(parts) < 2 { return fmt.Errorf("cannot extract port: %s", addr), port } - var err error - port, err = strconv.Atoi(parts[1]) - if err != nil { + if port, err := strconv.Atoi(parts[len(parts)-1]); err != nil { return err, port } } server := httpServer{ - apiKey: []byte(os.Getenv("FZF_API_KEY")), + apiKey: []byte(apiKey), actionChannel: actionChannel, responseChannel: responseChannel, } -- cgit v1.2.3