added json output for logs when Accept: application/json
This commit is contained in:
parent
495f26caed
commit
47ba7aa229
|
@ -146,6 +146,17 @@ func (a *App) logsHandler(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
if strings.Contains(r.Header.Get("Accept"), "json") {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
jsonData, err := json.Marshal(logs)
|
||||
if err != nil {
|
||||
http.Error(w, "Failed to encode agents to JSON", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.Write(jsonData)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
a.renderTemplate(w, "logs_partial.html", logs)
|
||||
}
|
||||
|
@ -177,193 +188,6 @@ func (a *App) getAgentIds(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
// func readCookie(r *http.Request, name string) (string, bool){
|
||||
// c, err := r.Cookie(name)
|
||||
// if err != nil { return "", false }
|
||||
// v, _ := url.QueryUnescape(c.Value)
|
||||
// return v, true
|
||||
// }
|
||||
|
||||
// func setCookie(h http.Header, name, val string) {
|
||||
// h.Add("Set-Cookie", (&http.Cookie{
|
||||
// Name: name,
|
||||
// Value: url.QueryEscape(val),
|
||||
// Path: "/proxyAgent",
|
||||
// SameSite: http.SameSiteLaxMode,
|
||||
// }).String())
|
||||
// }
|
||||
|
||||
// // proxyAgentHandler tunnels HTTP and WebSocket traffic to an agent
|
||||
// // selected by ?ip=…&port=… . It keeps the path *after* /proxyAgent,
|
||||
// // removes the two query parameters, disables HTTP/2 (mandatory for WS),
|
||||
// // and streams with no buffering.
|
||||
// func (a *App) proxyAgentHandler(w http.ResponseWriter, r *http.Request) {
|
||||
// ip := r.URL.Query().Get("ip")
|
||||
// port := r.URL.Query().Get("port")
|
||||
// if ip == "" || port == "" {
|
||||
// http.Error(w, "ip and port query parameters are required", http.StatusBadRequest)
|
||||
// return
|
||||
// }
|
||||
|
||||
// // We leave the scheme "http" even for WebSockets – the Upgrade
|
||||
// // header does the rest. (Only cosmetic to change it to "ws”.)
|
||||
// target, err := url.Parse("http://" + ip + ":" + port)
|
||||
// if err != nil {
|
||||
// http.Error(w, "invalid ip/port: "+err.Error(), http.StatusBadRequest)
|
||||
// return
|
||||
// }
|
||||
|
||||
// proxy := &httputil.ReverseProxy{
|
||||
// Director: func(req *http.Request) {
|
||||
// // Point to the agent
|
||||
// req.URL.Scheme = target.Scheme
|
||||
// req.URL.Host = target.Host
|
||||
|
||||
// // Trim the first "/proxyAgent" prefix
|
||||
// if strings.HasPrefix(req.URL.Path, "/proxyAgent") {
|
||||
// req.URL.Path = strings.TrimPrefix(req.URL.Path, "/proxyAgent")
|
||||
// if req.URL.Path == "" {
|
||||
// req.URL.Path = "/"
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Scrub ip/port from downstream query
|
||||
// q := req.URL.Query()
|
||||
// q.Del("ip")
|
||||
// q.Del("port")
|
||||
// req.URL.RawQuery = q.Encode()
|
||||
|
||||
// // Preserve Host (many CLI-style servers care)
|
||||
// req.Host = target.Host
|
||||
// },
|
||||
|
||||
// // Critical tweaks for WebSockets
|
||||
// Transport: &http.Transport{
|
||||
// Proxy: http.ProxyFromEnvironment,
|
||||
// DialContext: (&net.Dialer{Timeout: 30 * time.Second, KeepAlive: 30 * time.Second}).DialContext,
|
||||
// ForceAttemptHTTP2: false, // MUST be HTTP/1.1 for WS
|
||||
// ResponseHeaderTimeout: 0,
|
||||
// },
|
||||
|
||||
// FlushInterval: -1, // stream bytes immediately
|
||||
// }
|
||||
|
||||
// proxy.ServeHTTP(w, r)
|
||||
// }
|
||||
|
||||
// Registration (keep the slash so sub‑paths are included):
|
||||
// webMux.HandleFunc("/proxyAgent/", app.proxyAgentHandler)
|
||||
|
||||
//func (app *App) proxyAgentHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// //------------------------------------------------------------------
|
||||
// // 0. Helpers for cookie handling
|
||||
// //------------------------------------------------------------------
|
||||
// readCookie := func(name string) (string, bool) {
|
||||
// c, err := r.Cookie(name)
|
||||
// if err != nil { return "", false }
|
||||
// v, _ := url.QueryUnescape(c.Value)
|
||||
// return v, true
|
||||
// }
|
||||
// writeCookie := func(h http.Header, name, val string) {
|
||||
// h.Add("Set-Cookie", (&http.Cookie{
|
||||
// Name: name,
|
||||
// Value: url.QueryEscape(val),
|
||||
// Path: "/proxyAgent", // cookie visible only here
|
||||
// SameSite: http.SameSiteLaxMode,
|
||||
// }).String())
|
||||
// }
|
||||
|
||||
// //------------------------------------------------------------------
|
||||
// // 1. Decide which agent to talk to
|
||||
// //------------------------------------------------------------------
|
||||
// ip, port := r.URL.Query().Get("ip"), r.URL.Query().Get("port")
|
||||
// // fallback to cookies if query params are absent
|
||||
// if ip == "" || port == "" {
|
||||
// if v, ok := readCookie("proxyagent_ip"); ok { ip = v }
|
||||
// if v, ok := readCookie("proxyagent_port"); ok { port = v }
|
||||
// }
|
||||
// if ip == "" || port == "" {
|
||||
// http.Error(w, "ip and port query parameters are required", http.StatusBadRequest)
|
||||
// return
|
||||
// }
|
||||
|
||||
// target, err := url.Parse("http://" + ip + ":" + port)
|
||||
// if err != nil {
|
||||
// http.Error(w, "invalid ip/port: "+err.Error(), http.StatusBadRequest)
|
||||
// return
|
||||
// }
|
||||
|
||||
// // keep copies for ModifyResponse (Director will delete them)
|
||||
// ipForCookie, portForCookie := ip, port
|
||||
|
||||
// //------------------------------------------------------------------
|
||||
// // 2. Reverse proxy
|
||||
// //------------------------------------------------------------------
|
||||
// proxy := &httputil.ReverseProxy{
|
||||
|
||||
// Director: func(req *http.Request) {
|
||||
// // 2.1 upstream address
|
||||
// req.URL.Scheme = target.Scheme
|
||||
// req.URL.Host = target.Host
|
||||
|
||||
// // 2.2 strip ONE leading /proxyAgent
|
||||
// if strings.HasPrefix(req.URL.Path, "/proxyAgent") {
|
||||
// req.URL.Path = strings.TrimPrefix(req.URL.Path, "/proxyAgent")
|
||||
// if req.URL.Path == "" { req.URL.Path = "/" }
|
||||
// }
|
||||
|
||||
// // 2.3 remove ip/port from outgoing query
|
||||
// q := req.URL.Query()
|
||||
// q.Del("ip"); q.Del("port")
|
||||
// req.URL.RawQuery = q.Encode()
|
||||
|
||||
// // 2.4 keep original Host header
|
||||
// req.Host = target.Host
|
||||
|
||||
// // 2.5 force uncompressed HTML so we can patch it
|
||||
// req.Header.Del("Accept-Encoding")
|
||||
// },
|
||||
|
||||
// Transport: &http.Transport{
|
||||
// Proxy: http.ProxyFromEnvironment,
|
||||
// DialContext: (&net.Dialer{Timeout: 30 * time.Second, KeepAlive: 30 * time.Second}).DialContext,
|
||||
// ForceAttemptHTTP2: false, // must stay on h1 for WebSocket upgrade
|
||||
// ResponseHeaderTimeout: 0,
|
||||
// },
|
||||
|
||||
// FlushInterval: -1, // instant streaming for xterm.js
|
||||
|
||||
// //------------------------------------------------------------------
|
||||
// // 3. Response rewrite & cookie injection
|
||||
// //------------------------------------------------------------------
|
||||
// ModifyResponse: func(resp *http.Response) error {
|
||||
|
||||
// // 3.1 always (once per agent) set the cookies
|
||||
// writeCookie(resp.Header, "proxyagent_ip", ipForCookie)
|
||||
// writeCookie(resp.Header, "proxyagent_port", portForCookie)
|
||||
|
||||
// // 3.2 if the payload is HTML, inject <base href="/proxyAgent/">
|
||||
// if ct := resp.Header.Get("Content-Type"); strings.HasPrefix(ct, "text/html") {
|
||||
// body, _ := io.ReadAll(resp.Body)
|
||||
// patched := bytes.Replace(
|
||||
// body,
|
||||
// []byte("<head>"),
|
||||
// []byte(`<head><base href="/proxyAgent/">`),
|
||||
// 1)
|
||||
|
||||
// resp.Body = io.NopCloser(bytes.NewReader(patched))
|
||||
// resp.ContentLength = int64(len(patched))
|
||||
// resp.Header.Set("Content-Length", strconv.Itoa(len(patched)))
|
||||
// }
|
||||
|
||||
// return nil
|
||||
// },
|
||||
// }
|
||||
|
||||
// proxy.ServeHTTP(w, r)
|
||||
//}
|
||||
|
||||
func (app *App) proxyAgentHandler(w http.ResponseWriter, r *http.Request) {
|
||||
// path is /proxyAgent/<agentKey>/whatever…
|
||||
tail := strings.TrimPrefix(r.URL.Path, "/proxyAgent/")
|
||||
|
|
Loading…
Reference in New Issue