Merge pull request #129 from ben-krieger/response-content-length

Response content length
This commit is contained in:
syumai 2024-11-08 01:34:56 +09:00 committed by GitHub
commit 8784539f6f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 44 additions and 16 deletions

View File

@ -32,12 +32,12 @@ func ToResponse(res js.Value) (*http.Response, error) {
// ToJSResponse converts *http.Response to JavaScript sides Response class object. // ToJSResponse converts *http.Response to JavaScript sides Response class object.
func ToJSResponse(res *http.Response) js.Value { func ToJSResponse(res *http.Response) js.Value {
return newJSResponse(res.StatusCode, res.Header, res.Body, nil) return newJSResponse(res.StatusCode, res.Header, res.ContentLength, res.Body, nil)
} }
// newJSResponse creates JavaScript sides Response class object. // newJSResponse creates JavaScript sides Response class object.
// - Response: https://developer.mozilla.org/docs/Web/API/Response // - Response: https://developer.mozilla.org/docs/Web/API/Response
func newJSResponse(statusCode int, headers http.Header, body io.ReadCloser, rawBody *js.Value) js.Value { func newJSResponse(statusCode int, headers http.Header, contentLength int64, body io.ReadCloser, rawBody *js.Value) js.Value {
status := statusCode status := statusCode
if status == 0 { if status == 0 {
status = http.StatusOK status = http.StatusOK
@ -55,6 +55,8 @@ func newJSResponse(statusCode int, headers http.Header, body io.ReadCloser, rawB
var readableStream js.Value var readableStream js.Value
if rawBody != nil { if rawBody != nil {
readableStream = *rawBody readableStream = *rawBody
} else if contentLength > 0 {
readableStream = jsutil.ConvertReaderToFixedLengthStream(body, contentLength)
} else { } else {
readableStream = jsutil.ConvertReaderToReadableStream(body) readableStream = jsutil.ConvertReaderToReadableStream(body)
} }

View File

@ -3,6 +3,7 @@ package jshttp
import ( import (
"io" "io"
"net/http" "net/http"
"strconv"
"sync" "sync"
"syscall/js" "syscall/js"
@ -51,5 +52,6 @@ func (w *ResponseWriter) WriteRawJSBody(body js.Value) {
// ToJSResponse converts *ResponseWriter to JavaScript sides Response. // ToJSResponse converts *ResponseWriter to JavaScript sides Response.
// - Response: https://developer.mozilla.org/docs/Web/API/Response // - Response: https://developer.mozilla.org/docs/Web/API/Response
func (w *ResponseWriter) ToJSResponse() js.Value { func (w *ResponseWriter) ToJSResponse() js.Value {
return newJSResponse(w.StatusCode, w.HeaderValue, w.Reader, w.RawJSBody) contentLength, _ := strconv.ParseInt(w.HeaderValue.Get("Content-Length"), 10, 64)
return newJSResponse(w.StatusCode, w.HeaderValue, contentLength, w.Reader, w.RawJSBody)
} }

View File

@ -7,19 +7,20 @@ import (
) )
var ( var (
RuntimeContext = js.Global().Get("context") RuntimeContext = js.Global().Get("context")
Binding = js.Global().Get("context").Get("binding") Binding = js.Global().Get("context").Get("binding")
ObjectClass = js.Global().Get("Object") ObjectClass = js.Global().Get("Object")
PromiseClass = js.Global().Get("Promise") PromiseClass = js.Global().Get("Promise")
RequestClass = js.Global().Get("Request") RequestClass = js.Global().Get("Request")
ResponseClass = js.Global().Get("Response") ResponseClass = js.Global().Get("Response")
HeadersClass = js.Global().Get("Headers") HeadersClass = js.Global().Get("Headers")
ArrayClass = js.Global().Get("Array") ArrayClass = js.Global().Get("Array")
Uint8ArrayClass = js.Global().Get("Uint8Array") Uint8ArrayClass = js.Global().Get("Uint8Array")
ErrorClass = js.Global().Get("Error") ErrorClass = js.Global().Get("Error")
ReadableStreamClass = js.Global().Get("ReadableStream") ReadableStreamClass = js.Global().Get("ReadableStream")
DateClass = js.Global().Get("Date") FixedLengthStreamClass = js.Global().Get("FixedLengthStream")
Null = js.ValueOf(nil) DateClass = js.Global().Get("Date")
Null = js.ValueOf(nil)
) )
func NewObject() js.Value { func NewObject() js.Value {

View File

@ -198,3 +198,26 @@ func ConvertReaderToReadableStream(reader io.ReadCloser) js.Value {
})) }))
return ReadableStreamClass.New(rsInit) return ReadableStreamClass.New(rsInit)
} }
// ConvertReaderToFixedLengthStream converts io.ReadCloser to TransformStream.
func ConvertReaderToFixedLengthStream(rc io.ReadCloser, size int64) js.Value {
stream := FixedLengthStreamClass.New(js.ValueOf(size))
go func(writer js.Value) {
defer rc.Close()
chunk := make([]byte, min(size, defaultChunkSize))
for {
n, err := rc.Read(chunk)
if n > 0 {
b := Uint8ArrayClass.New(n)
js.CopyBytesToJS(b, chunk[:n])
writer.Call("write", b)
}
if err != nil {
writer.Call("close")
return
}
}
}(stream.Get("writable").Call("getWriter"))
return stream.Get("readable")
}