Adds support to proxy WS requests on Hop (#1857)
Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
This commit is contained in:
@@ -29,6 +29,9 @@ import (
|
||||
"net/http/cookiejar"
|
||||
url2 "net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
|
||||
v2 "github.com/minio/operator/pkg/apis/minio.min.io/v2"
|
||||
|
||||
@@ -181,11 +184,15 @@ func serveProxy(responseWriter http.ResponseWriter, req *http.Request) {
|
||||
}
|
||||
defer loginResp.Body.Close()
|
||||
}
|
||||
|
||||
if tenantCookie == nil {
|
||||
log.Println(errors.New("couldn't login to tenant and get cookie"))
|
||||
responseWriter.WriteHeader(500)
|
||||
responseWriter.WriteHeader(403)
|
||||
return
|
||||
}
|
||||
// at this point we have a valid cookie ready to either route HTTP or WS
|
||||
// now we need to know if we are doing an /api/ call (http) or /ws/ call (ws)
|
||||
callType := urlParts[5]
|
||||
|
||||
targetURL, err := url2.Parse(tenantURL)
|
||||
if err != nil {
|
||||
@@ -206,7 +213,16 @@ func serveProxy(responseWriter http.ResponseWriter, req *http.Request) {
|
||||
|
||||
proxyCookieJar, _ := cookiejar.New(nil)
|
||||
proxyCookieJar.SetCookies(targetURL, []*http.Cookie{proxiedCookie})
|
||||
switch callType {
|
||||
case "ws":
|
||||
handleWSRequest(responseWriter, req, proxyCookieJar, targetURL, tenantSchema)
|
||||
default:
|
||||
handleHTTPRequest(responseWriter, req, proxyCookieJar, tenantBase, targetURL)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func handleHTTPRequest(responseWriter http.ResponseWriter, req *http.Request, proxyCookieJar *cookiejar.Jar, tenantBase string, targetURL *url2.URL) {
|
||||
tr := &http.Transport{
|
||||
// FIXME: use restapi.GetConsoleHTTPClient()
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
@@ -259,5 +275,75 @@ func serveProxy(responseWriter http.ResponseWriter, req *http.Request) {
|
||||
responseWriter.WriteHeader(resp.StatusCode)
|
||||
|
||||
io.Copy(responseWriter, resp.Body)
|
||||
|
||||
}
|
||||
|
||||
var upgrader = websocket.Upgrader{
|
||||
ReadBufferSize: 0,
|
||||
WriteBufferSize: 1024,
|
||||
}
|
||||
|
||||
func handleWSRequest(responseWriter http.ResponseWriter, req *http.Request, proxyCookieJar *cookiejar.Jar, targetURL *url2.URL, schema string) {
|
||||
dialer := &websocket.Dialer{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
HandshakeTimeout: 45 * time.Second,
|
||||
Jar: proxyCookieJar,
|
||||
}
|
||||
|
||||
upgrader.CheckOrigin = func(r *http.Request) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
c, err := upgrader.Upgrade(responseWriter, req, nil)
|
||||
if err != nil {
|
||||
log.Print("error upgrade connection:", err)
|
||||
return
|
||||
}
|
||||
defer c.Close()
|
||||
if schema == "http" {
|
||||
targetURL.Scheme = "ws"
|
||||
} else {
|
||||
targetURL.Scheme = "wss"
|
||||
}
|
||||
|
||||
// establish a websocket to the tenant
|
||||
tenantConn, _, err := dialer.Dial(targetURL.String(), nil)
|
||||
if err != nil {
|
||||
log.Println("dial:", err)
|
||||
return
|
||||
}
|
||||
defer tenantConn.Close()
|
||||
|
||||
doneTenant := make(chan struct{})
|
||||
done := make(chan struct{})
|
||||
|
||||
// start read pump from tenant connection
|
||||
go func() {
|
||||
defer close(doneTenant)
|
||||
for {
|
||||
msgType, message, err := tenantConn.ReadMessage()
|
||||
if err != nil {
|
||||
log.Println("error read from tenant:", err)
|
||||
return
|
||||
}
|
||||
c.WriteMessage(msgType, message)
|
||||
}
|
||||
}()
|
||||
|
||||
// start read pump from tenant connection
|
||||
go func() {
|
||||
defer close(done)
|
||||
for {
|
||||
msgType, message, err := c.ReadMessage()
|
||||
if err != nil {
|
||||
log.Println("error read from client:", err)
|
||||
return
|
||||
}
|
||||
tenantConn.WriteMessage(msgType, message)
|
||||
}
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-done:
|
||||
case <-doneTenant:
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,9 +188,13 @@ const Heal = ({ classes, distributedSetup }: IHeal) => {
|
||||
const isDev = process.env.NODE_ENV === "development";
|
||||
const port = isDev ? "9090" : url.port;
|
||||
|
||||
// check if we are using base path, if not this always is `/`
|
||||
const baseLocation = new URL(document.baseURI);
|
||||
const baseUrl = baseLocation.pathname;
|
||||
|
||||
const wsProt = wsProtocol(url.protocol);
|
||||
const c = new W3CWebSocket(
|
||||
`${wsProt}://${url.hostname}:${port}/ws/heal/${bucketName}?prefix=${prefix}&recursive=${recursive}&force-start=${forceStart}&force-stop=${forceStop}`
|
||||
`${wsProt}://${url.hostname}:${port}${baseUrl}ws/heal/${bucketName}?prefix=${prefix}&recursive=${recursive}&force-start=${forceStart}&force-stop=${forceStop}`
|
||||
);
|
||||
|
||||
if (c !== null) {
|
||||
|
||||
@@ -173,8 +173,12 @@ const HealthInfo = ({
|
||||
|
||||
const wsProt = wsProtocol(url.protocol);
|
||||
|
||||
// check if we are using base path, if not this always is `/`
|
||||
const baseLocation = new URL(document.baseURI);
|
||||
const baseUrl = baseLocation.pathname;
|
||||
|
||||
const c = new W3CWebSocket(
|
||||
`${wsProt}://${url.hostname}:${port}/ws/health-info?deadline=1h`
|
||||
`${wsProt}://${url.hostname}:${port}${baseUrl}ws/health-info?deadline=1h`
|
||||
);
|
||||
|
||||
let interval: any | null = null;
|
||||
|
||||
@@ -158,11 +158,14 @@ const ErrorLogs = ({
|
||||
const port = isDev ? "9090" : url.port;
|
||||
|
||||
const wsProt = wsProtocol(url.protocol);
|
||||
// check if we are using base path, if not this always is `/`
|
||||
const baseLocation = new URL(document.baseURI);
|
||||
const baseUrl = baseLocation.pathname;
|
||||
|
||||
c = new W3CWebSocket(
|
||||
`${wsProt}://${
|
||||
url.hostname
|
||||
}:${port}/ws/console/?logType=${logType}&node=${
|
||||
}:${port}${baseUrl}ws/console/?logType=${logType}&node=${
|
||||
selectedNode === "Select node" ? "" : selectedNode
|
||||
}`
|
||||
);
|
||||
|
||||
@@ -109,9 +109,13 @@ const Speedtest = ({ classes, distributedSetup }: ISpeedtest) => {
|
||||
const isDev = process.env.NODE_ENV === "development";
|
||||
const port = isDev ? "9090" : url.port;
|
||||
|
||||
// check if we are using base path, if not this always is `/`
|
||||
const baseLocation = new URL(document.baseURI);
|
||||
const baseUrl = baseLocation.pathname;
|
||||
|
||||
const wsProt = wsProtocol(url.protocol);
|
||||
const c = new W3CWebSocket(
|
||||
`${wsProt}://${url.hostname}:${port}/ws/speedtest?&size=${size}${sizeUnit}`
|
||||
`${wsProt}://${url.hostname}:${port}${baseUrl}ws/speedtest?&size=${size}${sizeUnit}`
|
||||
);
|
||||
|
||||
const baseDate = moment();
|
||||
|
||||
@@ -166,12 +166,15 @@ const Trace = ({
|
||||
if (all) {
|
||||
calls = "all";
|
||||
}
|
||||
// check if we are using base path, if not this always is `/`
|
||||
const baseLocation = new URL(document.baseURI);
|
||||
const baseUrl = baseLocation.pathname;
|
||||
|
||||
const wsProt = wsProtocol(url.protocol);
|
||||
c = new W3CWebSocket(
|
||||
`${wsProt}://${
|
||||
url.hostname
|
||||
}:${port}/ws/trace?calls=${calls}&threshold=${threshold}&onlyErrors=${
|
||||
}:${port}${baseUrl}ws/trace?calls=${calls}&threshold=${threshold}&onlyErrors=${
|
||||
errors ? "yes" : "no"
|
||||
}&statusCode=${statusCode}&method=${method}&funcname=${func}&path=${path}`
|
||||
);
|
||||
|
||||
@@ -128,9 +128,13 @@ const Watch = ({
|
||||
const isDev = process.env.NODE_ENV === "development";
|
||||
const port = isDev ? "9090" : url.port;
|
||||
|
||||
// check if we are using base path, if not this always is `/`
|
||||
const baseLocation = new URL(document.baseURI);
|
||||
const baseUrl = baseLocation.pathname;
|
||||
|
||||
const wsProt = wsProtocol(url.protocol);
|
||||
const c = new W3CWebSocket(
|
||||
`${wsProt}://${url.hostname}:${port}/ws/watch/${bucketName}?prefix=${prefix}&suffix=${suffix}`
|
||||
`${wsProt}://${url.hostname}:${port}${baseUrl}ws/watch/${bucketName}?prefix=${prefix}&suffix=${suffix}`
|
||||
);
|
||||
|
||||
let interval: any | null = null;
|
||||
|
||||
@@ -19,13 +19,12 @@ package restapi
|
||||
// list of all console environment constants
|
||||
const (
|
||||
// Constants for common configuration
|
||||
ConsoleMinIOServer = "CONSOLE_MINIO_SERVER"
|
||||
ConsoleSubnetProxy = "CONSOLE_SUBNET_PROXY"
|
||||
ConsoleMinIORegion = "CONSOLE_MINIO_REGION"
|
||||
ConsoleHostname = "CONSOLE_HOSTNAME"
|
||||
ConsolePort = "CONSOLE_PORT"
|
||||
ConsoleTLSPort = "CONSOLE_TLS_PORT"
|
||||
ConsoleSubnetLicense = "CONSOLE_SUBNET_LICENSE"
|
||||
ConsoleMinIOServer = "CONSOLE_MINIO_SERVER"
|
||||
ConsoleSubnetProxy = "CONSOLE_SUBNET_PROXY"
|
||||
ConsoleMinIORegion = "CONSOLE_MINIO_REGION"
|
||||
ConsoleHostname = "CONSOLE_HOSTNAME"
|
||||
ConsolePort = "CONSOLE_PORT"
|
||||
ConsoleTLSPort = "CONSOLE_TLS_PORT"
|
||||
|
||||
// Constants for Secure middleware
|
||||
ConsoleSecureAllowedHosts = "CONSOLE_SECURE_ALLOWED_HOSTS"
|
||||
|
||||
Reference in New Issue
Block a user