Skip to content

Commit

Permalink
Merge pull request #129 from ben-krieger/response-content-length
Browse files Browse the repository at this point in the history
Response content length
  • Loading branch information
syumai authored Nov 7, 2024
2 parents f0f5c6f + bdd54f0 commit 8784539
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 16 deletions.
6 changes: 4 additions & 2 deletions internal/jshttp/response.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ func ToResponse(res js.Value) (*http.Response, error) {

// ToJSResponse converts *http.Response to JavaScript sides Response class object.
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.
// - 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
if status == 0 {
status = http.StatusOK
Expand All @@ -55,6 +55,8 @@ func newJSResponse(statusCode int, headers http.Header, body io.ReadCloser, rawB
var readableStream js.Value
if rawBody != nil {
readableStream = *rawBody
} else if contentLength > 0 {
readableStream = jsutil.ConvertReaderToFixedLengthStream(body, contentLength)
} else {
readableStream = jsutil.ConvertReaderToReadableStream(body)
}
Expand Down
4 changes: 3 additions & 1 deletion internal/jshttp/responsewriter.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package jshttp
import (
"io"
"net/http"
"strconv"
"sync"
"syscall/js"

Expand Down Expand Up @@ -51,5 +52,6 @@ func (w *ResponseWriter) WriteRawJSBody(body js.Value) {
// ToJSResponse converts *ResponseWriter to JavaScript sides Response.
// - Response: https://developer.mozilla.org/docs/Web/API/Response
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)
}
27 changes: 14 additions & 13 deletions internal/jsutil/jsutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,20 @@ import (
)

var (
RuntimeContext = js.Global().Get("context")
Binding = js.Global().Get("context").Get("binding")
ObjectClass = js.Global().Get("Object")
PromiseClass = js.Global().Get("Promise")
RequestClass = js.Global().Get("Request")
ResponseClass = js.Global().Get("Response")
HeadersClass = js.Global().Get("Headers")
ArrayClass = js.Global().Get("Array")
Uint8ArrayClass = js.Global().Get("Uint8Array")
ErrorClass = js.Global().Get("Error")
ReadableStreamClass = js.Global().Get("ReadableStream")
DateClass = js.Global().Get("Date")
Null = js.ValueOf(nil)
RuntimeContext = js.Global().Get("context")
Binding = js.Global().Get("context").Get("binding")
ObjectClass = js.Global().Get("Object")
PromiseClass = js.Global().Get("Promise")
RequestClass = js.Global().Get("Request")
ResponseClass = js.Global().Get("Response")
HeadersClass = js.Global().Get("Headers")
ArrayClass = js.Global().Get("Array")
Uint8ArrayClass = js.Global().Get("Uint8Array")
ErrorClass = js.Global().Get("Error")
ReadableStreamClass = js.Global().Get("ReadableStream")
FixedLengthStreamClass = js.Global().Get("FixedLengthStream")
DateClass = js.Global().Get("Date")
Null = js.ValueOf(nil)
)

func NewObject() js.Value {
Expand Down
23 changes: 23 additions & 0 deletions internal/jsutil/stream.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,3 +198,26 @@ func ConvertReaderToReadableStream(reader io.ReadCloser) js.Value {
}))
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")
}

0 comments on commit 8784539

Please sign in to comment.