diff --git a/contrib/codecs/http/codecs.go b/contrib/codecs/http/codecs.go
index 97d6fb3ecd55c674aff487df74c4d3862abbba68..ec9e01a0be1db05c4b557253f71ef145642df953 100644
--- a/contrib/codecs/http/codecs.go
+++ b/contrib/codecs/http/codecs.go
@@ -4,9 +4,11 @@ import (
 	"context"
 	"encoding/base64"
 	"errors"
+	"fmt"
 	"io"
 	"net/http"
 	"net/url"
+	"runtime/debug"
 	"strings"
 
 	"gfx.cafe/open/jrpc/pkg/jsonrpc"
@@ -96,7 +98,7 @@ func NewPostCodec(w http.ResponseWriter, r *http.Request) (*HttpCodec, error) {
 	}
 	c.ctx, c.cn = context.WithCancel(r.Context())
 	flusher, ok := w.(http.Flusher)
-	if ok {
+	if ok && flusher != nil {
 		c.f = flusher
 	}
 
@@ -137,19 +139,33 @@ func (c *HttpCodec) Write(p []byte) (n int, err error) {
 }
 
 func (c *HttpCodec) Flush() error {
-	c.w.Write([]byte{'\n'})
-	if c.f != nil {
-		c.f.Flush()
+	_, err := c.w.Write([]byte{'\n'})
+	if err != nil {
+		return err
 	}
+	c._flush()
 	return nil
 }
 
 func (c *HttpCodec) Close() error {
+	select {
+	case <-c.ctx.Done():
+	default:
+		c._flush()
+		c.cn()
+	}
+	return nil
+}
+
+func (c *HttpCodec) _flush() {
+	defer func() {
+		if err := recover(); err != nil {
+			fmt.Println("err", err, "stack: \n"+string(debug.Stack()))
+		}
+	}()
 	if c.f != nil {
 		c.f.Flush()
 	}
-	c.cn()
-	return nil
 }
 
 // Closed returns a channel which is closed when the connection is closed.