diff --git a/cloudflare/fetch/bind.go b/cloudflare/fetch/bind.go new file mode 100644 index 0000000..d82b6db --- /dev/null +++ b/cloudflare/fetch/bind.go @@ -0,0 +1,33 @@ +package fetch + +import ( + "errors" + "net/http" + "syscall/js" + + "github.com/syumai/workers/internal/jshttp" + "github.com/syumai/workers/internal/jsutil" +) + +// fetch is a function that reproduces cloudflare fetch. +// Docs: https://developers.cloudflare.com/workers/runtime-apis/fetch/ +func fetch(namespace js.Value, req *http.Request /* TO DO: options here */) (*http.Response, error) { + if namespace.IsUndefined() { + return nil, errors.New("fetch function not found") + } + + promise := namespace.Call("fetch", + // The Request object to fetch. + // Docs: https://developers.cloudflare.com/workers/runtime-apis/request + jshttp.ToJSRequest(req), + // The content of the request. + // Docs: https://developers.cloudflare.com/workers/runtime-apis/request#requestinit + jsutil.NewObject(), + ) + jsRes, err := jsutil.AwaitPromise(promise) + if err != nil { + return nil, err + } + + return jshttp.ToResponse(jsRes) +} diff --git a/cloudflare/fetch/client.go b/cloudflare/fetch/client.go index 4a36d19..c460a80 100644 --- a/cloudflare/fetch/client.go +++ b/cloudflare/fetch/client.go @@ -1,6 +1,7 @@ package fetch import ( + "net/http" "syscall/js" "github.com/syumai/workers/internal/jsutil" @@ -19,6 +20,15 @@ func (c *Client) applyOptions(opts []ClientOption) { } } +// HTTPClient returns *http.Client. +func (c *Client) HTTPClient() *http.Client { + return &http.Client{ + Transport: &transport{ + namespace: c.namespace, + }, + } +} + // ClientOption is a type that represents an optional function. type ClientOption func(*Client) diff --git a/cloudflare/fetch/http.go b/cloudflare/fetch/http.go index 35a8faa..7e85ace 100644 --- a/cloudflare/fetch/http.go +++ b/cloudflare/fetch/http.go @@ -2,21 +2,9 @@ package fetch import ( "net/http" - - "github.com/syumai/workers/internal/jshttp" - "github.com/syumai/workers/internal/jsutil" ) // Do sends an HTTP request and returns an HTTP response func (c *Client) Do(req *Request) (*http.Response, error) { - jsReq := jshttp.ToJSRequest(req.Request) - - init := jsutil.NewObject() - promise := c.namespace.Call("fetch", jsReq, init) - jsRes, err := jsutil.AwaitPromise(promise) - if err != nil { - return nil, err - } - - return jshttp.ToResponse(jsRes) + return fetch(c.namespace, req.Request) } diff --git a/cloudflare/fetch/transport.go b/cloudflare/fetch/transport.go new file mode 100644 index 0000000..142b2e3 --- /dev/null +++ b/cloudflare/fetch/transport.go @@ -0,0 +1,17 @@ +package fetch + +import ( + "net/http" + "syscall/js" +) + +// transport is an implementation of http.RoundTripper +type transport struct { + // namespace - Objects that Fetch API belongs to. Default is Global + namespace js.Value +} + +// RoundTrip replaces http.DefaultTransport.RoundTrip to use cloudflare fetch +func (t *transport) RoundTrip(req *http.Request) (*http.Response, error) { + return fetch(t.namespace, req) +} diff --git a/examples/service-bindings/Makefile b/examples/service-bindings/Makefile index 320ddc3..11a0197 100644 --- a/examples/service-bindings/Makefile +++ b/examples/service-bindings/Makefile @@ -5,7 +5,8 @@ dev: .PHONY: build build: mkdir -p dist - tinygo build -o ./dist/app.wasm -target wasm ./... + #tinygo build -o ./dist/app.wasm -target wasm ./... + tinygo build -o ./dist/app.wasm -target wasm -no-debug ./... .PHONY: publish publish: diff --git a/examples/service-bindings/main.go b/examples/service-bindings/main.go index 452c715..81e1614 100644 --- a/examples/service-bindings/main.go +++ b/examples/service-bindings/main.go @@ -13,17 +13,11 @@ import ( func main() { handler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { ctx := req.Context() + bind := cloudflare.GetBinding(ctx, "hello") + fc := fetch.NewClient(fetch.WithBinding(bind)) - obj := cloudflare.GetBinding(ctx, "hello") - cli := fetch.NewClient(fetch.WithBinding(obj)) - r, err := fetch.NewRequest(ctx, http.MethodGet, req.URL.String(), nil) - if err != nil { - fmt.Println(err) - w.WriteHeader(http.StatusInternalServerError) - return - } - - res, err := cli.Do(r) + hc := fc.HTTPClient() + res, err := hc.Do(req) if err != nil { fmt.Println(err) w.WriteHeader(http.StatusInternalServerError)