Skip to content

Commit

Permalink
refactor: group methods under new Client type
Browse files Browse the repository at this point in the history
  • Loading branch information
chetan committed Nov 3, 2021
1 parent b83763a commit b0de06c
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 39 deletions.
4 changes: 4 additions & 0 deletions bin/vproxy/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ vproxy connect hello.local:8888 -- vproxy hello
Name: "bind",
Usage: "Bind hostname to local port (e.g., app.local.com:7000)",
},
&cli.BoolFlag{
Name: "detach",
Usage: "Do not stream logs after binding",
},
},
},
{
Expand Down
6 changes: 3 additions & 3 deletions bin/vproxy/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,12 @@ func startClient(c *cli.Context) error {
}
}

addr := fmt.Sprintf("%s:%d", host, httpPort)
if !vproxy.IsDaemonRunning(addr) {
client := &vproxy.Client{Addr: fmt.Sprintf("%s:%d", host, httpPort)}
if !client.IsDaemonRunning() {
return fmt.Errorf("daemon not running on localhost")
}

vproxy.StartClientMode(addr, binds, args)
client.AddBindings(binds, c.Bool("detach"), args)
return nil
}

Expand Down
90 changes: 56 additions & 34 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,45 +14,56 @@ import (
"sync"
)

func StartClientMode(addr string, binds []string, args []string) {
type Client struct {
Addr string
cmd *exec.Cmd
wg *sync.WaitGroup
}

func (c *Client) uri(path string) string {
return fmt.Sprintf("http://%s/_vproxy%s", c.Addr, path)
}

func (c *Client) AddBindings(binds []string, detach bool, args []string) {
if len(binds) == 0 {
fmt.Println("error: must bind at least one hostname")
os.Exit(1)
}

// run command, if given
var cmd *exec.Cmd
if len(args) > 0 {
cmd = runCommand(args)

// trap signal for later cleanup
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
go func() {
// catch ^c, cleanup
s := <-c
if s == nil {
return
}
fmt.Println("[*] caught signal:", s)
stopCommand(cmd)
os.Exit(0)
}()
c.wg = &sync.WaitGroup{}
for _, bind := range binds {
c.wg.Add(1)
go c.addBinding(bind, detach)
c.wg.Wait()
}

wg := &sync.WaitGroup{}
for _, bind := range binds {
wg.Add(1)
go startClientBinding(addr, bind, cmd, wg)
wg.Wait()
c.wg.Add(1)
c.wg.Wait()
}

func (c *Client) runCommand(args []string) {
// run command, if given
if len(args) == 0 {
return
}
c.cmd = runCommand(args)

wg.Add(1)
wg.Wait()
// trap signal for later cleanup
cs := make(chan os.Signal, 1)
signal.Notify(cs, os.Interrupt)
go func() {
// catch ^c, cleanup
s := <-cs
if s == nil {
return
}
fmt.Println("[*] caught signal:", s)
stopCommand(c.cmd)
os.Exit(0)
}()
}

func startClientBinding(addr string, bind string, cmd *exec.Cmd, wg *sync.WaitGroup) {
uri := fmt.Sprintf("http://%s/_vproxy", addr)
func (c *Client) addBinding(bind string, detach bool) {
data := url.Values{}
data.Add("binding", bind)

Expand All @@ -62,20 +73,31 @@ func startClientBinding(addr string, bind string, cmd *exec.Cmd, wg *sync.WaitGr
} else {
fmt.Println("[*] registering vhost:", bind)
}
res, err := http.DefaultClient.PostForm(uri, data)
res, err := http.DefaultClient.PostForm(c.uri("/clients/add"), data)
if err != nil {
stopCommand(cmd)
stopCommand(c.cmd)
log.Fatalf("error registering client: %s\n", err)
}

wg.Done()
c.wg.Done()
if detach {
res.Body.Close()
} else {
streamLogs(res)
}
}

func attach(addr string, bind string) {

}

func streamLogs(res *http.Response) {
defer res.Body.Close()
r := bufio.NewReader(res.Body)
for {
line, err := r.ReadString('\n')
if err != nil {
fmt.Printf("error reading from daemon: %s\n", err)
stopCommand(cmd)
fmt.Println("exiting")
os.Exit(0)
}
Expand All @@ -88,8 +110,8 @@ func startClientBinding(addr string, bind string, cmd *exec.Cmd, wg *sync.WaitGr
}

// IsDaemonRunning tries to check if a vproxy daemon is already running on the given addr
func IsDaemonRunning(addr string) bool {
res, err := http.DefaultClient.Get(fmt.Sprintf("http://%s/_vproxy/hello", addr))
func (c *Client) IsDaemonRunning() bool {
res, err := http.DefaultClient.Get(c.uri("/hello"))
if err != nil || res.StatusCode != 200 {
return false
}
Expand Down
5 changes: 3 additions & 2 deletions logged_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ import (

var defaultTLSHost = "vproxy.local"

// LoggedHandler is an http.Server implementation which multiplexes requests to the
// vhost backends (via a handler) and logs each request.
// LoggedHandler is an extension of http.ServeMux which multiplexes requests to
// the vhost backends (via a handler) and logs each request.
// TODO: replace ServeMux with a proper router (chi?)
type LoggedHandler struct {
*http.ServeMux
VhostLogListeners map[string]chan string
Expand Down

0 comments on commit b0de06c

Please sign in to comment.