feat(webclient): add request context and HTML navigation handling
- Add context to HTTP requests in JSRequestToHTTPRequest, storing the request mode for downstream use - Implement IsHTMLContentType function to properly parse and check for HTML content types - Modify proxy ServeHTTP to read and log HTML bodies for navigation mode requests, ensuring proper handling of HTML responses
lemon-mint committed
Oct 31, 2025 at 13:38 UTC
79ceefeb334ff64b89d93d3dda2db9a4d2cf754d
2 files changed
+40
-3
cmd/webclient/httpjs/http_js.go
+5
-1
@@ -3,6 +3,7 @@ package httpjs
3
import (
4
"bufio"
5
"bytes"
6
+ "context"
7
"errors"
8
"io"
9
"net/http"
@@ -365,8 +366,11 @@ func JSRequestToHTTPRequest(jsReq js.Value) (*http.Request, error) {
366
bodyReader = bytes.NewReader([]byte{})
367
}
368
369
+ ctx := context.Background()
370
+ ctx = context.WithValue(ctx, "http.request.mode", jsReq.Get("mode").String())
371
+
372
// Create HTTP request
369
- httpReq, err := http.NewRequest(method, url, bodyReader)
373
+ httpReq, err := http.NewRequestWithContext(ctx, method, url, bodyReader)
374
if err != nil {
375
return nil, err
376
}
cmd/webclient/main_js.go
+35
-2
@@ -3,6 +3,7 @@ package main
3
import (
4
"context"
5
"io"
6
+ "mime"
7
"net"
8
"net/http"
9
"os"
@@ -44,6 +45,24 @@ var client = &http.Client{
45
type Proxy struct {
46
}
47
48
+// IsHTMLContentType checks if the Content-Type header indicates HTML content
49
+// It properly handles media type parsing with parameters like charset
50
+func IsHTMLContentType(contentType string) bool {
51
+ if contentType == "" {
52
+ return false
53
+ }
54
+
55
+ // Parse the media type and parameters
56
+ mediaType, _, err := mime.ParseMediaType(contentType)
57
+ if err != nil {
58
+ // If parsing fails, do a simple case-insensitive check for "text/html"
59
+ return strings.HasPrefix(strings.ToLower(contentType), "text/html")
60
+ }
61
+
62
+ // Check if the media type is HTML
63
+ return mediaType == "text/html"
64
+}
65
+
66
func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
67
log.Info().Msgf("Proxying request to %s", r.URL.String())
68
@@ -69,8 +88,22 @@ func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
88
for key, value := range resp.Header {
89
w.Header()[key] = value
90
}
72
- w.WriteHeader(resp.StatusCode)
73
- io.Copy(w, resp.Body)
91
+
92
+ if r.Context().Value("http.request.mode").(string) == "navigate" &&
93
+ IsHTMLContentType(resp.Header.Get("Content-Type")) {
94
+ body, err := io.ReadAll(resp.Body)
95
+ if err != nil {
96
+ w.WriteHeader(http.StatusBadGateway)
97
+ w.Write([]byte("502: Failed to read response body"))
98
+ return
99
+ }
100
+ log.Debug().Msgf("HTML content received: %s", body)
101
+ w.WriteHeader(resp.StatusCode)
102
+ w.Write(body)
103
+ } else {
104
+ w.WriteHeader(resp.StatusCode)
105
+ io.Copy(w, resp.Body)
106
+ }
107
}
108
109
func main() {