This repository has been archived by the owner on Mar 22, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 13
/
reverse.go
92 lines (78 loc) · 2.09 KB
/
reverse.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package middlewares
import (
"net/http"
"strings"
"github.com/labstack/echo/v4"
log "github.com/sirupsen/logrus"
)
// ReverseConfig is the configuration to describe
// a reverse proxy
type ReverseConfig struct {
Path string
URL string
}
func reverse(config ReverseConfig, ctx echo.Context) error {
req := ctx.Request()
uri := config.URL + "/" + ctx.Param("*")
if config.Path != "" {
uri = config.URL + config.Path
}
if strings.Contains(req.RequestURI, "?") {
interogation := strings.Index(req.RequestURI, "?")
uri += req.RequestURI[interogation:]
}
log.WithFields(log.Fields{
"reverse": uri,
"remote": ctx.RealIP(),
"host": req.Host,
"uri": req.RequestURI,
"method": req.Method,
"path": req.URL.Path,
"referer": req.Referer(),
}).Debug("Execute reverse proxy")
req, err := http.NewRequest(ctx.Request().Method, uri, ctx.Request().Body)
if err != nil {
return ctx.String(http.StatusInternalServerError, err.Error())
}
req.Header = ctx.Request().Header
res, err := http.DefaultClient.Do(req)
if err != nil {
log.WithError(err).Error("Cannot execute the request on the endpoint")
return ctx.NoContent(http.StatusBadGateway)
}
if res.Header != nil {
// Copy Warp10 headers
for k, v := range res.Header {
log.Debugf("Header %v: %v", k, v)
if strings.HasPrefix(k, "X-Warp") {
ctx.Response().Header().Set(k, v[0])
}
}
// copy HTTP related headers
copyHeaders(res.Header, ctx.Response(), []string{
"Content-Type",
"Content-Length",
"Content-Encoding",
"Vary",
})
}
ct := res.Header.Get("Content-Type")
if ct == "" {
ct = "text/plain"
}
return ctx.Stream(res.StatusCode, ct, res.Body)
}
// ReverseWithConfig execute a reverse proxy using
// the configuration given in parameters
func ReverseWithConfig(config ReverseConfig) echo.HandlerFunc {
return func(ctx echo.Context) error {
return reverse(config, ctx)
}
}
func copyHeaders(reqheaders http.Header, res *echo.Response, headers []string) {
for _, header := range headers {
if reqheaders.Get(header) != "" {
res.Header().Set(header, reqheaders.Get(header))
}
}
}