Merge pull request #31 from aki-0421/fetch-transport

Add ability to use fetch as a http.Client
This commit is contained in:
syumai 2023-04-11 22:36:43 +09:00 committed by GitHub
commit 2609f2a76f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 67 additions and 24 deletions

33
cloudflare/fetch/bind.go Normal file
View File

@ -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)
}

View File

@ -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)

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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:

View File

@ -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)