Files
netbird/client/wasm/internal/http/http.go

101 lines
2.7 KiB
Go

//go:build js
package http
import (
"fmt"
"io"
log "github.com/sirupsen/logrus"
"net/http"
"strings"
"syscall/js"
"time"
netbird "github.com/netbirdio/netbird/client/embed"
)
const (
httpTimeout = 30 * time.Second
maxResponseSize = 1024 * 1024 // 1MB
)
// performRequest executes an HTTP request through NetBird and returns the response and body
func performRequest(nbClient *netbird.Client, method, url string, headers map[string]string, body []byte) (*http.Response, []byte, error) {
httpClient := nbClient.NewHTTPClient()
httpClient.Timeout = httpTimeout
req, err := http.NewRequest(method, url, strings.NewReader(string(body)))
if err != nil {
return nil, nil, fmt.Errorf("create request: %w", err)
}
for key, value := range headers {
req.Header.Set(key, value)
}
resp, err := httpClient.Do(req)
if err != nil {
return nil, nil, fmt.Errorf("request failed: %w", err)
}
defer func() {
if err := resp.Body.Close(); err != nil {
log.Errorf("failed to close response body: %v", err)
}
}()
respBody, err := io.ReadAll(io.LimitReader(resp.Body, maxResponseSize))
if err != nil {
return nil, nil, fmt.Errorf("read response: %w", err)
}
return resp, respBody, nil
}
// ProxyRequest performs a proxied HTTP request through NetBird and returns a JavaScript object
func ProxyRequest(nbClient *netbird.Client, request js.Value) (js.Value, error) {
url := request.Get("url").String()
if url == "" {
return js.Undefined(), fmt.Errorf("URL is required")
}
method := "GET"
if methodVal := request.Get("method"); !methodVal.IsNull() && !methodVal.IsUndefined() {
method = strings.ToUpper(methodVal.String())
}
var requestBody []byte
if bodyVal := request.Get("body"); !bodyVal.IsNull() && !bodyVal.IsUndefined() {
requestBody = []byte(bodyVal.String())
}
requestHeaders := make(map[string]string)
if headersVal := request.Get("headers"); !headersVal.IsNull() && !headersVal.IsUndefined() && headersVal.Type() == js.TypeObject {
headerKeys := js.Global().Get("Object").Call("keys", headersVal)
for i := 0; i < headerKeys.Length(); i++ {
key := headerKeys.Index(i).String()
value := headersVal.Get(key).String()
requestHeaders[key] = value
}
}
resp, body, err := performRequest(nbClient, method, url, requestHeaders, requestBody)
if err != nil {
return js.Undefined(), err
}
result := js.Global().Get("Object").New()
result.Set("status", resp.StatusCode)
result.Set("statusText", resp.Status)
result.Set("body", string(body))
headers := js.Global().Get("Object").New()
for key, values := range resp.Header {
if len(values) > 0 {
headers.Set(strings.ToLower(key), values[0])
}
}
result.Set("headers", headers)
return result, nil
}