From ed546fec093a1e46b6eb0fbad95a4194a9a3bed6 Mon Sep 17 00:00:00 2001 From: aki-0421 <118268728+aki-0421@users.noreply.github.com> Date: Sun, 28 May 2023 13:04:35 +0900 Subject: [PATCH] Add redirect mode --- cloudflare/fetch/bind.go | 6 ++--- cloudflare/fetch/client.go | 3 ++- cloudflare/fetch/http.go | 26 ++++++++++++++++--- cloudflare/fetch/property.go | 47 +++++++++++++++++++++++++++++++++++ cloudflare/fetch/request.go | 25 ------------------- cloudflare/fetch/transport.go | 5 +++- 6 files changed, 78 insertions(+), 34 deletions(-) create mode 100644 cloudflare/fetch/property.go delete mode 100644 cloudflare/fetch/request.go diff --git a/cloudflare/fetch/bind.go b/cloudflare/fetch/bind.go index d82b6db..9207cdb 100644 --- a/cloudflare/fetch/bind.go +++ b/cloudflare/fetch/bind.go @@ -11,23 +11,21 @@ import ( // 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) { +func fetch(namespace js.Value, req *http.Request, init *RequestInit) (*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(), + init.ToJS(), ) 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 c460a80..6040fab 100644 --- a/cloudflare/fetch/client.go +++ b/cloudflare/fetch/client.go @@ -21,10 +21,11 @@ func (c *Client) applyOptions(opts []ClientOption) { } // HTTPClient returns *http.Client. -func (c *Client) HTTPClient() *http.Client { +func (c *Client) HTTPClient(redirect RedirectMode) *http.Client { return &http.Client{ Transport: &transport{ namespace: c.namespace, + redirect: redirect, }, } } diff --git a/cloudflare/fetch/http.go b/cloudflare/fetch/http.go index 7e85ace..21c0759 100644 --- a/cloudflare/fetch/http.go +++ b/cloudflare/fetch/http.go @@ -1,10 +1,30 @@ package fetch import ( + "context" + "io" "net/http" ) -// Do sends an HTTP request and returns an HTTP response -func (c *Client) Do(req *Request) (*http.Response, error) { - return fetch(c.namespace, req.Request) +// Request represents an HTTP request and is part of the Fetch API. +// Docs: https://developers.cloudflare.com/workers/runtime-apis/request/ +type Request struct { + *http.Request +} + +// NewRequest returns new Request given a method, URL, and optional body +func NewRequest(ctx context.Context, method string, url string, body io.Reader) (*Request, error) { + req, err := http.NewRequestWithContext(ctx, method, url, body) + if err != nil { + return nil, err + } + + return &Request{ + Request: req, + }, nil +} + +// Do sends an HTTP request and returns an HTTP response +func (c *Client) Do(req *Request, init *RequestInit) (*http.Response, error) { + return fetch(c.namespace, req.Request, init) } diff --git a/cloudflare/fetch/property.go b/cloudflare/fetch/property.go new file mode 100644 index 0000000..73fab4b --- /dev/null +++ b/cloudflare/fetch/property.go @@ -0,0 +1,47 @@ +package fetch + +import ( + "syscall/js" + + "github.com/syumai/workers/internal/jsutil" +) + +// RedirectMode represents the redirect mode of a fetch() request. +type RedirectMode string + +var ( + RedirectModeFollow RedirectMode = "follow" + RedirectModeError RedirectMode = "error" + RedirectModeManual RedirectMode = "manual" +) + +func (mode RedirectMode) IsValid() bool { + return mode == RedirectModeFollow || mode == RedirectModeError || mode == RedirectModeManual +} + +func (mode RedirectMode) String() string { + return string(mode) +} + +// RequestInit represents the options passed to a fetch() request. +type RequestInit struct { + CF *RequestInitCF + Redirect RedirectMode +} + +// ToJS converts RequestInit to JS object. +func (init *RequestInit) ToJS() js.Value { + if init == nil { + return js.Undefined() + } + obj := jsutil.NewObject() + if init.Redirect.IsValid() { + obj.Set("redirect", init.Redirect.String()) + } + return obj +} + +// RequestInitCF represents the Cloudflare-specific options passed to a fetch() request. +type RequestInitCF struct { + /* TODO: implement */ +} diff --git a/cloudflare/fetch/request.go b/cloudflare/fetch/request.go deleted file mode 100644 index a52eba9..0000000 --- a/cloudflare/fetch/request.go +++ /dev/null @@ -1,25 +0,0 @@ -package fetch - -import ( - "context" - "io" - "net/http" -) - -// Request represents an HTTP request and is part of the Fetch API. -// Docs: https://developers.cloudflare.com/workers/runtime-apis/request/ -type Request struct { - *http.Request -} - -// NewRequest returns new Request given a method, URL, and optional body -func NewRequest(ctx context.Context, method string, url string, body io.Reader) (*Request, error) { - req, err := http.NewRequestWithContext(ctx, method, url, body) - if err != nil { - return nil, err - } - - return &Request{ - Request: req, - }, nil -} diff --git a/cloudflare/fetch/transport.go b/cloudflare/fetch/transport.go index 142b2e3..068fcf3 100644 --- a/cloudflare/fetch/transport.go +++ b/cloudflare/fetch/transport.go @@ -9,9 +9,12 @@ import ( type transport struct { // namespace - Objects that Fetch API belongs to. Default is Global namespace js.Value + redirect RedirectMode } // RoundTrip replaces http.DefaultTransport.RoundTrip to use cloudflare fetch func (t *transport) RoundTrip(req *http.Request) (*http.Response, error) { - return fetch(t.namespace, req) + return fetch(t.namespace, req, &RequestInit{ + Redirect: t.redirect, + }) }