faasd/pkg/proxy.go
Alex Ellis (OpenFaaS Ltd) 97c11b3f5d Proxy the gateway using TCP
There appeared to be an issue with logs appearing #98 and #68

@LucasRoesler spent a considerable amount of time looking into
this and concluded that the faas-provider and approach we are
taking to stream logs from journalctl as a process was
working as expected.

The issue appears to have been with the proxy code and its
use of a HTTP connection. Somewhere within the code, a buffer
was holding onto the data before flushing it 20-30 seconds later

This appeared to users as if the logs were not working at all.

Before fixing, the gateway container was tested by exposing
it over an SSH tunnel and inlets tunnel, both worked as
expected. The updates have been tested on multipass with
Ubuntu 18.04 and a binary built locally.

Signed-off-by: Alex Ellis (OpenFaaS Ltd) <alexellis2@gmail.com>
2020-09-08 11:33:11 +01:00

84 lines
1.5 KiB
Go

package pkg
import (
"fmt"
"io"
"log"
"net"
"net/http"
"time"
)
// NewProxy creates a HTTP proxy to expose the gateway container
// from OpenFaaS to the host
func NewProxy(port int, timeout time.Duration) *Proxy {
return &Proxy{
Port: port,
Timeout: timeout,
}
}
// Proxy for exposing a private container
type Proxy struct {
Timeout time.Duration
Port int
}
type proxyState struct {
Host string
}
// Start listening and forwarding HTTP to the host
func (p *Proxy) Start(gatewayChan chan string, done chan bool) error {
tcp := p.Port
http.DefaultClient.CheckRedirect = func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
}
ps := proxyState{
Host: "",
}
ps.Host = <-gatewayChan
log.Printf("Starting faasd proxy on %d\n", tcp)
fmt.Printf("Gateway: %s\n", ps.Host)
l, err := net.Listen("tcp", fmt.Sprintf("0.0.0.0:%d", tcp))
if err != nil {
log.Printf("Error: %s", err.Error())
return err
}
defer l.Close()
for {
// Wait for a connection.
conn, err := l.Accept()
if err != nil {
acceptErr := fmt.Errorf("Unable to accept on %d, error: %s", tcp, err.Error())
log.Printf("%s", acceptErr.Error())
return acceptErr
}
upstream, err := net.Dial("tcp", fmt.Sprintf("%s", ps.Host))
if err != nil {
log.Printf("unable to dial to %s, error: %s", ps.Host, err.Error())
return err
}
go pipe(conn, upstream)
go pipe(upstream, conn)
}
}
func pipe(from net.Conn, to net.Conn) {
defer from.Close()
io.Copy(from, to)
}