diff --git a/pkg/download/engine/engine.go b/pkg/download/engine/engine.go index ac0db488..1809e542 100644 --- a/pkg/download/engine/engine.go +++ b/pkg/download/engine/engine.go @@ -145,6 +145,10 @@ func NewEngine(cfg *Config) *Engine { if err := runtime.Set("global", runtime.GlobalObject()); err != nil { return } + // polyfill window + if err := runtime.Set("window", runtime.GlobalObject()); err != nil { + return + } // polyfill window.location if _, err := runtime.RunString("global.location = new URL('http://localhost');"); err != nil { return diff --git a/pkg/download/engine/engine_test.go b/pkg/download/engine/engine_test.go index 61443bd3..a1763f42 100644 --- a/pkg/download/engine/engine_test.go +++ b/pkg/download/engine/engine_test.go @@ -80,6 +80,30 @@ async function testFormData(file){ return await resp.json(); } +function testHeader(){ + return new Promise((resolve, reject) => { + const xhr = new XMLHttpRequest(); + xhr.open('GET', host+'/header'); + xhr.setRequestHeader('X-Gopeed-Test', 'test1'); + xhr.setRequestHeader('x-gopeed-test', 'test2'); + xhr.setRequestHeader('x-Gopeed-test', 'test3'); + xhr.onload = function(){ + const testHeader1 = xhr.getResponseHeader("X-Gopeed-Test"); + const testHeader2 = xhr.getResponseHeader("x-gopeed-test"); + const testHeader3 = xhr.getResponseHeader("x-Gopeed-test"); + const expect = 'test1, test2, test3'; + const all = xhr.getAllResponseHeaders(); + if(testHeader1 === expect && testHeader2 === expect && testHeader3 === expect + && all.includes('X-Gopeed-Test: '+expect)){ + resolve(); + }else{ + reject(); + } + }; + xhr.send(); + }); +} + function testProgress(){ return new Promise((resolve, reject) => { const xhr = new XMLHttpRequest(); @@ -190,14 +214,19 @@ function testTimeout(){ } }() + _, err = callTestFun(engine, "testHeader") + if err != nil { + t.Fatal("header test failed", err) + } + _, err = callTestFun(engine, "testProgress") if err != nil { - t.Fatal("progress test failed") + t.Fatal("progress test failed", err) } _, err = callTestFun(engine, "testAbort") if err != nil { - t.Fatal("abort test failed") + t.Fatal("abort test failed", err) } _, err = callTestFun(engine, "testTimeout") @@ -328,6 +357,15 @@ func startServer() net.Listener { w.WriteHeader(http.StatusOK) w.Write([]byte("ok")) }) + mux.HandleFunc("/header", func(w http.ResponseWriter, r *http.Request) { + for k, v := range r.Header { + if strings.HasPrefix(k, "X-Gopeed") { + w.Header().Set(k, strings.Join(v, ", ")) + } + } + w.WriteHeader(http.StatusOK) + w.Write([]byte("ok")) + }) mux.HandleFunc("/text", func(w http.ResponseWriter, r *http.Request) { buf, _ := io.ReadAll(r.Body) w.WriteHeader(http.StatusOK) diff --git a/pkg/download/engine/inject/xhr/module.go b/pkg/download/engine/inject/xhr/module.go index dd6e0a77..292041c2 100644 --- a/pkg/download/engine/inject/xhr/module.go +++ b/pkg/download/engine/inject/xhr/module.go @@ -12,6 +12,7 @@ import ( "net" "net/http" "net/url" + "strings" "time" ) @@ -118,8 +119,8 @@ type XMLHttpRequestUpload struct { type XMLHttpRequest struct { method string url string - requestHeaders map[string]string - responseHeaders map[string]string + requestHeaders http.Header + responseHeaders http.Header aborted bool proxyHandler func(r *http.Request) (*url.URL, error) @@ -137,13 +138,13 @@ type XMLHttpRequest struct { func (xhr *XMLHttpRequest) Open(method, url string) { xhr.method = method xhr.url = url - xhr.requestHeaders = make(map[string]string) - xhr.responseHeaders = make(map[string]string) + xhr.requestHeaders = make(http.Header) + xhr.responseHeaders = make(http.Header) xhr.doReadystatechange(1) } func (xhr *XMLHttpRequest) SetRequestHeader(key, value string) { - xhr.requestHeaders[key] = value + xhr.requestHeaders.Add(key, value) } func (xhr *XMLHttpRequest) Send(data goja.Value) { @@ -194,15 +195,13 @@ func (xhr *XMLHttpRequest) Send(data goja.Value) { xhr.callOnerror() return } + req.Header = xhr.requestHeaders if contentType != "" { req.Header.Set("Content-Type", contentType) } if contentLength > 0 { req.ContentLength = contentLength } - for k, v := range xhr.requestHeaders { - req.Header.Set(k, v) - } transport := &http.Transport{ Proxy: xhr.proxyHandler, } @@ -230,9 +229,7 @@ func (xhr *XMLHttpRequest) Send(data goja.Value) { if !xhr.aborted { xhr.Upload.callOnload() } - for k, v := range resp.Header { - xhr.responseHeaders[k] = v[0] - } + xhr.responseHeaders = resp.Header xhr.Status = resp.StatusCode xhr.StatusText = resp.Status xhr.doReadystatechange(2) @@ -261,7 +258,7 @@ func (xhr *XMLHttpRequest) Abort() { } func (xhr *XMLHttpRequest) GetResponseHeader(key string) string { - return xhr.responseHeaders[key] + return strings.Join(xhr.responseHeaders.Values(key), ", ") } func (xhr *XMLHttpRequest) GetAllResponseHeaders() string { @@ -269,7 +266,7 @@ func (xhr *XMLHttpRequest) GetAllResponseHeaders() string { for k, v := range xhr.responseHeaders { buf.WriteString(k) buf.WriteString(": ") - buf.WriteString(v) + buf.WriteString(strings.Join(v, ", ")) buf.WriteString("\r\n") } return buf.String() diff --git a/pkg/download/extension_test.go b/pkg/download/extension_test.go index 59707722..a7c4a504 100644 --- a/pkg/download/extension_test.go +++ b/pkg/download/extension_test.go @@ -238,7 +238,7 @@ func TestDownloader_Extension_OnError(t *testing.T) { select { case err = <-errCh: break - case <-time.After(time.Second * 10): + case <-time.After(time.Second * 30): err = errors.New("timeout") }