Skip to content

Commit

Permalink
feat: implement flush() (dunglas#90)
Browse files Browse the repository at this point in the history
* feat: implement flush()

* add tests
  • Loading branch information
dunglas authored Nov 8, 2022
1 parent 0a30dd1 commit 8e136d0
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 2 deletions.
11 changes: 10 additions & 1 deletion frankenphp.c
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,15 @@ static int frankenphp_send_headers(sapi_headers_struct *sapi_headers)
return SAPI_HEADER_SENT_SUCCESSFULLY;
}

static void frankenphp_sapi_flush(void *server_context)
{
frankenphp_server_context *ctx = (frankenphp_server_context *) server_context;

if (!ctx || ctx->current_request == 0) return;

go_sapi_flush(ctx->current_request);
}

static size_t frankenphp_read_post(char *buffer, size_t count_bytes)
{
frankenphp_server_context* ctx = SG(server_context);
Expand Down Expand Up @@ -483,7 +492,7 @@ sapi_module_struct frankenphp_sapi_module = {
frankenphp_deactivate, /* deactivate */

frankenphp_ub_write, /* unbuffered write */
NULL, /* flush */
frankenphp_sapi_flush, /* flush */
NULL, /* get uid */
NULL, /* getenv */

Expand Down
17 changes: 17 additions & 0 deletions frankenphp.go
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,23 @@ func go_write_header(rh C.uintptr_t, status C.int) {
}
}

//export go_sapi_flush
func go_sapi_flush(rh C.uintptr_t) {
r := cgo.Handle(rh).Value().(*http.Request)
fc := r.Context().Value(contextKey).(*FrankenPHPContext)

if fc.responseWriter == nil {
return
}

flusher, ok := fc.responseWriter.(http.Flusher)
if !ok {
return
}

flusher.Flush()
}

//export go_read_post
func go_read_post(rh C.uintptr_t, cBuf *C.char, countBytes C.size_t) C.size_t {
r := cgo.Handle(rh).Value().(*http.Request)
Expand Down
34 changes: 34 additions & 0 deletions frankenphp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,40 @@ func testEarlyHints(t *testing.T, opts *testOptions) {
}, opts)
}

type streamResponseRecorder struct {
*httptest.ResponseRecorder
writeCallback func(buf []byte)
}

func (srr *streamResponseRecorder) Write(buf []byte) (int, error) {
srr.writeCallback(buf)

return srr.ResponseRecorder.Write(buf)
}

func TestFlush_module(t *testing.T) { testFlush(t, &testOptions{}) }
func TestFlush_worker(t *testing.T) {
testFlush(t, &testOptions{workerScript: "flush.php"})
}
func testFlush(t *testing.T, opts *testOptions) {
runTest(t, func(handler func(http.ResponseWriter, *http.Request), _ *httptest.Server, i int) {
var j int

req := httptest.NewRequest("GET", fmt.Sprintf("http://example.com/flush.php?i=%d", i), nil)
w := &streamResponseRecorder{httptest.NewRecorder(), func(buf []byte) {
if j == 0 {
assert.Equal(t, []byte("He"), buf)
} else {
assert.Equal(t, []byte(fmt.Sprintf("llo %d", i)), buf)
}

j++
}}
handler(w, req)

assert.Equal(t, 2, j)
}, opts)
}
func ExampleServeHTTP() {
if err := frankenphp.Init(); err != nil {
panic(err)
Expand Down
2 changes: 1 addition & 1 deletion testdata/Caddyfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
debug
frankenphp {
worker ./phpinfo.php
#worker ./phpinfo.php
}
}

Expand Down
11 changes: 11 additions & 0 deletions testdata/flush.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

require_once __DIR__.'/_executor.php';

return function () {
echo 'He';

flush();

echo 'llo '.($_GET['i'] ?? '');
};

0 comments on commit 8e136d0

Please sign in to comment.