From cd154341ff08d53d6f0563a8363454cabdb20be8 Mon Sep 17 00:00:00 2001 From: syumai Date: Wed, 22 Feb 2023 19:10:47 +0900 Subject: [PATCH] move Reqeust / Response / ResponseWriterBuffer to jsutil --- handler.go | 6 ++-- request.go => internal/jsutil/request.go | 24 +++++++-------- internal/jsutil/response.go | 30 +++++++++++++++++++ internal/jsutil/responsewriter.go | 38 ++++++++++++++++++++++++ response.go | 32 -------------------- responsewriter.go | 38 ------------------------ 6 files changed, 82 insertions(+), 86 deletions(-) rename request.go => internal/jsutil/request.go (65%) create mode 100644 internal/jsutil/response.go create mode 100644 internal/jsutil/responsewriter.go delete mode 100644 response.go delete mode 100644 responsewriter.go diff --git a/handler.go b/handler.go index bc9232a..ba3ad12 100644 --- a/handler.go +++ b/handler.go @@ -47,14 +47,14 @@ func handleRequest(reqObj js.Value, runtimeCtxObj js.Value) (js.Value, error) { if httpHandler == nil { return js.Value{}, fmt.Errorf("Serve must be called before handleRequest.") } - req, err := toRequest(reqObj) + req, err := jsutil.ToRequest(reqObj) if err != nil { panic(err) } ctx := runtimecontext.New(context.Background(), runtimeCtxObj) req = req.WithContext(ctx) reader, writer := io.Pipe() - w := &responseWriterBuffer{ + w := &jsutil.ResponseWriterBuffer{ header: http.Header{}, statusCode: http.StatusOK, reader: reader, @@ -66,7 +66,7 @@ func handleRequest(reqObj js.Value, runtimeCtxObj js.Value) (js.Value, error) { defer writer.Close() httpHandler.ServeHTTP(w, req) }() - return toJSResponse(w) + return jsutil.ToJSResponse(w) } // Server serves http.Handler on Cloudflare Workers. diff --git a/request.go b/internal/jsutil/request.go similarity index 65% rename from request.go rename to internal/jsutil/request.go index 43af70d..6c44b9f 100644 --- a/request.go +++ b/internal/jsutil/request.go @@ -1,4 +1,4 @@ -package workers +package jsutil import ( "io" @@ -7,24 +7,22 @@ import ( "strconv" "strings" "syscall/js" - - "github.com/syumai/workers/internal/jsutil" ) -// toBody converts JavaScripts sides ReadableStream (can be null) to io.ReadCloser. +// ToBody converts JavaScripts sides ReadableStream (can be null) to io.ReadCloser. // - ReadableStream: https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream -func toBody(streamOrNull js.Value) io.ReadCloser { +func ToBody(streamOrNull js.Value) io.ReadCloser { if streamOrNull.IsNull() { return nil } sr := streamOrNull.Call("getReader") - return io.NopCloser(jsutil.ConvertStreamReaderToReader(sr)) + return io.NopCloser(ConvertStreamReaderToReader(sr)) } -// toHeader converts JavaScript sides Headers to http.Header. +// ToHeader converts JavaScript sides Headers to http.Header. // - Headers: https://developer.mozilla.org/ja/docs/Web/API/Headers -func toHeader(headers js.Value) http.Header { - entries := jsutil.ArrayFrom(headers.Call("entries")) +func ToHeader(headers js.Value) http.Header { + entries := ArrayFrom(headers.Call("entries")) headerLen := entries.Length() h := http.Header{} for i := 0; i < headerLen; i++ { @@ -38,14 +36,14 @@ func toHeader(headers js.Value) http.Header { return h } -// toRequest converts JavaScript sides Request to *http.Request. +// ToRequest converts JavaScript sides Request to *http.Request. // - Request: https://developer.mozilla.org/ja/docs/Web/API/Request -func toRequest(req js.Value) (*http.Request, error) { +func ToRequest(req js.Value) (*http.Request, error) { reqUrl, err := url.Parse(req.Get("url").String()) if err != nil { return nil, err } - header := toHeader(req.Get("headers")) + header := ToHeader(req.Get("headers")) // ignore err contentLength, _ := strconv.ParseInt(header.Get("Content-Length"), 10, 64) @@ -53,7 +51,7 @@ func toRequest(req js.Value) (*http.Request, error) { Method: req.Get("method").String(), URL: reqUrl, Header: header, - Body: toBody(req.Get("body")), + Body: ToBody(req.Get("body")), ContentLength: contentLength, TransferEncoding: strings.Split(header.Get("Transfer-Encoding"), ","), Host: header.Get("Host"), diff --git a/internal/jsutil/response.go b/internal/jsutil/response.go new file mode 100644 index 0000000..62343a2 --- /dev/null +++ b/internal/jsutil/response.go @@ -0,0 +1,30 @@ +package jsutil + +import ( + "net/http" + "syscall/js" +) + +func ToJSHeader(header http.Header) js.Value { + h := HeadersClass.New() + for key, values := range header { + for _, value := range values { + h.Call("append", key, value) + } + } + return h +} + +func ToJSResponse(w *ResponseWriterBuffer) (js.Value, error) { + <-w.readyCh // wait until ready + status := w.statusCode + if status == 0 { + status = http.StatusOK + } + respInit := NewObject() + respInit.Set("status", status) + respInit.Set("statusText", http.StatusText(status)) + respInit.Set("headers", ToJSHeader(w.Header())) + readableStream := ConvertReaderToReadableStream(w.reader) + return ResponseClass.New(readableStream, respInit), nil +} diff --git a/internal/jsutil/responsewriter.go b/internal/jsutil/responsewriter.go new file mode 100644 index 0000000..4938d3d --- /dev/null +++ b/internal/jsutil/responsewriter.go @@ -0,0 +1,38 @@ +package jsutil + +import ( + "io" + "net/http" + "sync" +) + +type ResponseWriterBuffer struct { + header http.Header + statusCode int + reader *io.PipeReader + writer *io.PipeWriter + readyCh chan struct{} + once sync.Once +} + +var _ http.ResponseWriter = &ResponseWriterBuffer{} + +// ready indicates that ResponseWriterBuffer is ready to be converted to Response. +func (w *ResponseWriterBuffer) ready() { + w.once.Do(func() { + close(w.readyCh) + }) +} + +func (w *ResponseWriterBuffer) Write(data []byte) (n int, err error) { + w.ready() + return w.writer.Write(data) +} + +func (w *ResponseWriterBuffer) Header() http.Header { + return w.header +} + +func (w *ResponseWriterBuffer) WriteHeader(statusCode int) { + w.statusCode = statusCode +} diff --git a/response.go b/response.go deleted file mode 100644 index da9505a..0000000 --- a/response.go +++ /dev/null @@ -1,32 +0,0 @@ -package workers - -import ( - "net/http" - "syscall/js" - - "github.com/syumai/workers/internal/jsutil" -) - -func toJSHeader(header http.Header) js.Value { - h := jsutil.HeadersClass.New() - for key, values := range header { - for _, value := range values { - h.Call("append", key, value) - } - } - return h -} - -func toJSResponse(w *responseWriterBuffer) (js.Value, error) { - <-w.readyCh // wait until ready - status := w.statusCode - if status == 0 { - status = http.StatusOK - } - respInit := jsutil.NewObject() - respInit.Set("status", status) - respInit.Set("statusText", http.StatusText(status)) - respInit.Set("headers", toJSHeader(w.Header())) - readableStream := jsutil.ConvertReaderToReadableStream(w.reader) - return jsutil.ResponseClass.New(readableStream, respInit), nil -} diff --git a/responsewriter.go b/responsewriter.go deleted file mode 100644 index b4e11c9..0000000 --- a/responsewriter.go +++ /dev/null @@ -1,38 +0,0 @@ -package workers - -import ( - "io" - "net/http" - "sync" -) - -type responseWriterBuffer struct { - header http.Header - statusCode int - reader *io.PipeReader - writer *io.PipeWriter - readyCh chan struct{} - once sync.Once -} - -var _ http.ResponseWriter = &responseWriterBuffer{} - -// ready indicates that responseWriterBuffer is ready to be converted to Response. -func (w *responseWriterBuffer) ready() { - w.once.Do(func() { - close(w.readyCh) - }) -} - -func (w *responseWriterBuffer) Write(data []byte) (n int, err error) { - w.ready() - return w.writer.Write(data) -} - -func (w *responseWriterBuffer) Header() http.Header { - return w.header -} - -func (w *responseWriterBuffer) WriteHeader(statusCode int) { - w.statusCode = statusCode -}