mirror of
https://github.com/openfaas/faasd.git
synced 2025-06-09 00:16:46 +00:00
* revendor k3sup to prevent arch / OS from being printed in the logs * print version on startup * bump minor CNI and containerd version for e2e tests * revendor faas-provider for latest log printing update Signed-off-by: Alex Ellis (OpenFaaS Ltd) <alexellis2@gmail.com>
127 lines
2.6 KiB
Go
127 lines
2.6 KiB
Go
package pkg
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"log"
|
|
"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
|
|
}
|
|
|
|
// 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)
|
|
|
|
s := &http.Server{
|
|
Addr: fmt.Sprintf(":%d", tcp),
|
|
ReadTimeout: p.Timeout,
|
|
WriteTimeout: p.Timeout,
|
|
MaxHeaderBytes: 1 << 20, // Max header of 1MB
|
|
Handler: http.HandlerFunc(makeProxy(&ps)),
|
|
}
|
|
|
|
go func() {
|
|
log.Printf("[proxy] Begin listen on %d\n", p.Port)
|
|
if err := s.ListenAndServe(); err != http.ErrServerClosed {
|
|
log.Printf("Error ListenAndServe: %v", err)
|
|
}
|
|
}()
|
|
|
|
log.Println("[proxy] Wait for done")
|
|
<-done
|
|
log.Println("[proxy] Done received")
|
|
if err := s.Shutdown(context.Background()); err != nil {
|
|
log.Printf("[proxy] Error in Shutdown: %v", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// copyHeaders clones the header values from the source into the destination.
|
|
func copyHeaders(destination http.Header, source *http.Header) {
|
|
for k, v := range *source {
|
|
vClone := make([]string, len(v))
|
|
copy(vClone, v)
|
|
destination[k] = vClone
|
|
}
|
|
}
|
|
|
|
type proxyState struct {
|
|
Host string
|
|
}
|
|
|
|
func makeProxy(ps *proxyState) func(w http.ResponseWriter, r *http.Request) {
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
query := ""
|
|
if len(r.URL.RawQuery) > 0 {
|
|
query = "?" + r.URL.RawQuery
|
|
}
|
|
|
|
upstream := fmt.Sprintf("http://%s%s%s", ps.Host, r.URL.Path, query)
|
|
fmt.Printf("[faasd] proxy: %s\n", upstream)
|
|
|
|
if r.Body != nil {
|
|
defer r.Body.Close()
|
|
}
|
|
|
|
wrapper := ioutil.NopCloser(r.Body)
|
|
upReq, upErr := http.NewRequest(r.Method, upstream, wrapper)
|
|
|
|
copyHeaders(upReq.Header, &r.Header)
|
|
|
|
if upErr != nil {
|
|
log.Println(upErr)
|
|
|
|
http.Error(w, upErr.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
upRes, upResErr := http.DefaultClient.Do(upReq)
|
|
|
|
if upResErr != nil {
|
|
log.Println(upResErr)
|
|
|
|
http.Error(w, upResErr.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
copyHeaders(w.Header(), &upRes.Header)
|
|
|
|
w.WriteHeader(upRes.StatusCode)
|
|
io.Copy(w, upRes.Body)
|
|
}
|
|
}
|