Files
Servo/httpmuxer/proxy.go
Antonio Mika 9696686880 Added streaming for httpmuxer (#255)
* Added streaming for httpmuxer

* Fix gzip response checking
2022-10-21 11:44:48 -04:00

110 lines
3.3 KiB
Go

package httpmuxer
import (
"bytes"
"compress/gzip"
"crypto/tls"
"encoding/base64"
"io"
"log"
"net"
"net/http"
"strings"
"github.com/antoniomika/sish/utils"
"github.com/gin-gonic/gin"
"github.com/spf13/viper"
)
// RoundTripper returns the specific handler for unix connections. This
// will allow us to use our created sockets cleanly.
func RoundTripper() *http.Transport {
dialer := func(network, addr string) (net.Conn, error) {
realAddr, err := base64.StdEncoding.DecodeString(strings.Split(addr, ":")[0])
if err != nil {
log.Println("Unable to parse socket:", err)
}
return net.Dial("unix", string(realAddr))
}
tlsConfig := &tls.Config{
InsecureSkipVerify: !viper.GetBool("verify-ssl"),
}
return &http.Transport{
Dial: dialer,
TLSClientConfig: tlsConfig,
}
}
// ResponseModifier implements a response modifier for the specified request.
// We don't actually modify any requests, but we do want to record the request
// so we can send it to the web console.
func ResponseModifier(state *utils.State, hostname string, reqBody []byte, c *gin.Context, currentListener *utils.HTTPHolder) func(*http.Response) error {
return func(response *http.Response) error {
if viper.GetBool("admin-console") || viper.GetBool("service-console") {
var err error
var resBody []byte
if viper.GetInt64("service-console-max-content-length") == -1 || (viper.GetInt64("service-console-max-content-length") > -1 && response.ContentLength > -1 && response.ContentLength < viper.GetInt64("service-console-max-content-length")) {
resBody, err = io.ReadAll(response.Body)
if err != nil {
log.Println("Error reading response body:", err)
}
}
if resBody != nil {
response.Body = io.NopCloser(bytes.NewBuffer(resBody))
if response.Header.Get("Content-Encoding") == "gzip" {
gzData := bytes.NewBuffer(resBody)
gzReader, err := gzip.NewReader(gzData)
if err != nil {
log.Println("Error reading gzip data:", err)
}
resBody, err = io.ReadAll(gzReader)
if err != nil {
log.Println("Error reading gzip data:", err)
}
}
} else {
resBody = []byte("{\"_sish_status\": false, \"_sish_message\": \"response body size exceeds limit for service console\"}")
}
startTime := c.GetTime("startTime")
requestHeaders := c.Request.Header.Clone()
requestHeaders.Add("Host", hostname)
data := map[string]any{
"startTime": startTime,
"startTimePretty": startTime.Format(viper.GetString("time-format")),
"requestIP": c.ClientIP(),
"requestMethod": c.Request.Method,
"requestUrl": c.Request.URL,
"originalRequestURI": c.GetString("originalURI"),
"requestHeaders": requestHeaders,
"requestBody": base64.StdEncoding.EncodeToString(reqBody),
"responseHeaders": response.Header,
"responseBody": base64.StdEncoding.EncodeToString(resBody),
}
if response.Request != nil {
hostLocation, err := base64.StdEncoding.DecodeString(response.Request.URL.Host)
if err != nil {
log.Println("Error loading proxy info from request", err)
}
c.Set("proxySocket", string(hostLocation))
}
c.Set("broadcastRoute", currentListener.HTTPUrl.String())
c.Set("broadcastData", data)
}
return nil
}
}