diff --git a/_examples/stream-large-file/.gitignore b/_examples/stream-large-file/.gitignore new file mode 100644 index 0000000..aee7b7e --- /dev/null +++ b/_examples/stream-large-file/.gitignore @@ -0,0 +1,3 @@ +build +node_modules +.wrangler diff --git a/_examples/stream-large-file/Makefile b/_examples/stream-large-file/Makefile new file mode 100644 index 0000000..019492c --- /dev/null +++ b/_examples/stream-large-file/Makefile @@ -0,0 +1,12 @@ +.PHONY: dev +dev: + wrangler dev + +.PHONY: build +build: + go run ../../cmd/workers-assets-gen + tinygo build -o ./build/app.wasm -target wasm -no-debug ./... + +.PHONY: deploy +deploy: + wrangler deploy diff --git a/_examples/stream-large-file/README.md b/_examples/stream-large-file/README.md new file mode 100644 index 0000000..cb751db --- /dev/null +++ b/_examples/stream-large-file/README.md @@ -0,0 +1,18 @@ +# stream-large-file + +## Development + +### Requirements + +This project requires these tools to be installed globally. + +* wrangler +* tinygo + +### Commands + +``` +make dev # run dev server +make build # build Go Wasm binary +make deploy # deploy worker +``` \ No newline at end of file diff --git a/_examples/stream-large-file/go.mod b/_examples/stream-large-file/go.mod new file mode 100644 index 0000000..619130f --- /dev/null +++ b/_examples/stream-large-file/go.mod @@ -0,0 +1,7 @@ +module github.com/syumai/workers/_examples/stream + +go 1.21.3 + +require github.com/syumai/workers v0.0.0 + +replace github.com/syumai/workers => ../../ diff --git a/_examples/stream-large-file/go.sum b/_examples/stream-large-file/go.sum new file mode 100644 index 0000000..8c27871 --- /dev/null +++ b/_examples/stream-large-file/go.sum @@ -0,0 +1,2 @@ +github.com/syumai/workers v0.1.0 h1:z5QfQR2X+PCKzom7RodpI5J4D5YF7NT7Qwzb9AM9dgY= +github.com/syumai/workers v0.1.0/go.mod h1:alXIDhTyeTwSzh0ZgQ3cb9HQPyyYfIejupE4Z3efr14= diff --git a/_examples/stream-large-file/main.go b/_examples/stream-large-file/main.go new file mode 100644 index 0000000..04e88b4 --- /dev/null +++ b/_examples/stream-large-file/main.go @@ -0,0 +1,26 @@ +package main + +import ( + "fmt" + "io" + "net/http" + + "github.com/syumai/workers" + "github.com/syumai/workers/cloudflare/fetch" +) + +func main() { + http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { + cli := fetch.NewClient().HTTPClient(fetch.RedirectModeFollow) + resp, err := cli.Get("http://tyo.download.datapacket.com/1000mb.bin") + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + fmt.Fprintf(w, "err: %v", err) + return + } + defer resp.Body.Close() + + io.Copy(w, resp.Body) + }) + workers.Serve(nil) +} diff --git a/_examples/stream-large-file/wrangler.toml b/_examples/stream-large-file/wrangler.toml new file mode 100644 index 0000000..db4d764 --- /dev/null +++ b/_examples/stream-large-file/wrangler.toml @@ -0,0 +1,6 @@ +name = "stream-large-file" +main = "./build/worker.mjs" +compatibility_date = "2023-12-01" + +[build] +command = "make build" diff --git a/cloudflare/fetch/bind.go b/cloudflare/fetch/bind.go index afc6ea1..28c08e5 100644 --- a/cloudflare/fetch/bind.go +++ b/cloudflare/fetch/bind.go @@ -3,6 +3,7 @@ package fetch import ( "errors" "net/http" + "strconv" "syscall/js" "github.com/syumai/workers/internal/jshttp" @@ -15,8 +16,8 @@ func fetch(namespace js.Value, req *http.Request, init *RequestInit) (*http.Resp if namespace.IsUndefined() { return nil, errors.New("fetch function not found") } - fetchObj := namespace.Get("fetch") - promise := fetchObj.Invoke( + fetchFunc := namespace.Get("fetch") + promise := fetchFunc.Invoke( // The Request object to fetch. // Docs: https://developers.cloudflare.com/workers/runtime-apis/request jshttp.ToJSRequest(req), @@ -30,5 +31,18 @@ func fetch(namespace js.Value, req *http.Request, init *RequestInit) (*http.Resp return nil, err } - return jshttp.ToResponse(jsRes) + // Create TransformStream + ts := js.Global().Get("IdentityTransformStream").New() + readable := ts.Get("readable") + writable := ts.Get("writable") + jsRes.Get("body").Call("pipeTo", writable) + + // Create response + res := new(http.Response) + res.StatusCode = jsRes.Get("status").Int() + res.Status = strconv.Itoa(res.StatusCode) + " " + jsRes.Get("statusText").String() + res.Header = jshttp.ToHeader(jsRes.Get("headers")) + res.Body = jsutil.ConvertReadableStreamToReadCloser(readable) + + return res, nil }