Skip to content

Commit a69dee0

Browse files
authored
Merge pull request #2 from kernelshard/feature/use-tunnel-manager
Integrate tunnel manager in CLI
2 parents e02f3d2 + df079f2 commit a69dee0

File tree

2 files changed

+67
-12
lines changed

2 files changed

+67
-12
lines changed

internal/cli/tunnel.go

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
package cli
22

33
import (
4+
"context"
45
"fmt"
5-
"net/http"
6-
"net/http/httputil"
7-
"net/url"
6+
"os"
7+
"os/signal"
8+
"syscall"
89

9-
"github.com/kernelshard/expose/internal/config"
1010
"github.com/spf13/cobra"
11+
12+
"github.com/kernelshard/expose/internal/config"
13+
"github.com/kernelshard/expose/internal/tunnel"
1114
)
1215

1316
// tunnelCmd represents the 'tunnel' command in the CLI application.
@@ -40,14 +43,39 @@ func newTunnelCmd() *cobra.Command {
4043
// runTunnel sets up a reverse proxy to expose the local server
4144
// on the specified port.
4245
func runTunnel(port int) error {
43-
fmt.Printf("Exposing localhost:%d\n", port)
44-
fmt.Printf("Local URL: http://localhost:8080\n")
45-
fmt.Println("\nPress Ctrl+C to stop")
4646

47-
// Create reverse proxy to forward requests
48-
target, _ := url.Parse(fmt.Sprintf("http://localhost:%d", port))
49-
proxy := httputil.NewSingleHostReverseProxy(target)
47+
// Create manager
48+
mgr := tunnel.NewManager(port)
49+
50+
// context with signal handling
51+
ctx, cancel := context.WithCancel(context.Background())
52+
defer cancel()
53+
54+
// handle Ctrl+C, kill pid etc
55+
sigChan := make(chan os.Signal, 1)
56+
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
57+
58+
// waiting to read from channel is blocking ops, so wait in bg.
59+
go func() {
60+
<-sigChan
61+
fmt.Println("\n\nShutting down...")
62+
cancel()
63+
}()
64+
65+
// start in background
66+
errChan := make(chan error, 1)
67+
go func() {
68+
errChan <- mgr.Start(ctx)
69+
}()
70+
71+
// wait for ready
72+
<-mgr.Ready()
73+
74+
// Show info
75+
fmt.Printf("🚀 Starting tunnel for localhost:%d\n\n", port)
76+
fmt.Printf("✓ Public URL: %s\n", mgr.PublicURL())
77+
fmt.Printf("✓ Forwarding to: http://localhost:%d\n\n", port)
78+
fmt.Println("Press Ctrl+C to stop")
5079

51-
// Start local server
52-
return http.ListenAndServe(":8080", proxy)
80+
return <-errChan
5381
}

internal/cli/tunnel_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package cli
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func TestTunnelCmd(t *testing.T) {
8+
cmd := newTunnelCmd()
9+
10+
if cmd == nil {
11+
t.Fatal("newTunnelCmd returned nil")
12+
}
13+
14+
if cmd.Use != "tunnel" {
15+
t.Errorf("expected Use 'tunnel', got '%s'", cmd.Use)
16+
}
17+
18+
// Check flag parsing
19+
flag := cmd.Flags().Lookup("port")
20+
if flag == nil {
21+
t.Error("port flag not defined")
22+
}
23+
24+
if flag.Shorthand != "p" {
25+
t.Errorf("expected shorthand 'p' got %s", flag.Shorthand)
26+
}
27+
}

0 commit comments

Comments
 (0)