mirror of
https://github.com/syumai/workers.git
synced 2025-03-10 17:29:11 +00:00
move Reqeust / Response / ResponseWriterBuffer to jsutil
This commit is contained in:
parent
8bb44582c5
commit
cd154341ff
@ -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.
|
||||
|
@ -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"),
|
30
internal/jsutil/response.go
Normal file
30
internal/jsutil/response.go
Normal file
@ -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
|
||||
}
|
38
internal/jsutil/responsewriter.go
Normal file
38
internal/jsutil/responsewriter.go
Normal file
@ -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
|
||||
}
|
32
response.go
32
response.go
@ -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
|
||||
}
|
@ -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
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user