diff --git a/handler.go b/handler.go index cb41d69a40863c8ffe09f6dabd1a25e30c4f8031..2a69ba8081bcaf4aa83d8828d0331391ec760e2b 100644 --- a/handler.go +++ b/handler.go @@ -226,6 +226,7 @@ func (h *handler) handleCall(cp *callProc, msg *jsonrpcMessage) *jsonrpcMessage } req := &Request{ctx: cp.ctx, msg: *msg, peer: h.peer} mw := NewReaderResponseWriterMsg(req) + // now actually run the handler h.reg.ServeRPC(mw, req) //TODO: notifications diff --git a/http.go b/http.go index 553de3d3e72131a68f63f6897a9beaafc79aa283..6f9475b2549b310e15aa64c77b566c135f30c397 100644 --- a/http.go +++ b/http.go @@ -30,6 +30,8 @@ import ( "strings" "sync" "time" + + "gfx.cafe/util/go/bufpool" ) const ( @@ -219,7 +221,11 @@ func (hc *httpConn) doRequest(ctx context.Context, msg any) (io.ReadCloser, erro type httpServerConn struct { io.Reader io.Writer + + jc ServerCodec + r *http.Request + w http.ResponseWriter } func newHTTPServerConn(r *http.Request, w http.ResponseWriter) ServerCodec { @@ -240,8 +246,8 @@ func newHTTPServerConn(r *http.Request, w http.ResponseWriter) ServerCodec { if pb, err := base64.URLEncoding.DecodeString(params); err == nil { param = pb } - buf := new(bytes.Buffer) - buf.Grow(128) + buf := bufpool.GetStd() + defer bufpool.Put(buf) jzon.NewEncoder(buf).Encode(jsonrpcMessage{ ID: NewStringIDPtr(id), Method: method_up, @@ -252,7 +258,54 @@ func newHTTPServerConn(r *http.Request, w http.ResponseWriter) ServerCodec { // it's a post request or whatever, so just process it like normal conn.Reader = io.LimitReader(r.Body, maxRequestContentLength) } - return NewCodec(conn) + conn.jc = NewCodec(conn) + return conn +} + +func (c *httpServerConn) peerInfo() PeerInfo { + connInfo := PeerInfo{ + Transport: "http", + RemoteAddr: c.remoteAddr(), + HTTP: HttpInfo{ + Version: c.r.Proto, + UserAgent: c.r.UserAgent(), + Origin: c.r.Header.Get("Origin"), + Host: c.r.Host, + Headers: c.r.Header, + WriteHeaders: c.w.Header(), + }, + } + + connInfo.HTTP.Origin = c.r.Header.Get("X-Real-Ip") + if connInfo.HTTP.Origin == "" { + connInfo.HTTP.Origin = c.r.Header.Get("X-Forwarded-For") + } + if connInfo.HTTP.Origin == "" { + connInfo.HTTP.Origin = c.r.Header.Get("Origin") + } + + return connInfo +} + +func (c *httpServerConn) remoteAddr() string { + return c.RemoteAddr() +} + +func (c *httpServerConn) readBatch() (messages []*jsonrpcMessage, batch bool, err error) { + return c.jc.readBatch() +} + +func (c *httpServerConn) writeJSON(ctx context.Context, v any) error { + return c.jc.writeJSON(ctx, v) +} + +func (c *httpServerConn) close() { + c.jc.close() +} + +// Closed returns a channel which will be closed when Close is called +func (c *httpServerConn) closed() <-chan any { + return c.jc.closed() } // Close does nothing and always returns nil. diff --git a/protocol.go b/protocol.go index 808023610350fae550837694fb6991f61b01f195..42c89e1ea4285e3531796048835782c4ece2639e 100644 --- a/protocol.go +++ b/protocol.go @@ -3,6 +3,7 @@ package jrpc import ( "context" "encoding/json" + "net/http" ) type HandlerFunc func(w ResponseWriter, r *Request) @@ -14,6 +15,7 @@ type Handler interface { type ResponseWriter interface { Send(v any, err error) error Notify(v any) error + Header() http.Header } func (fn HandlerFunc) ServeRPC(w ResponseWriter, r *Request) { @@ -118,6 +120,10 @@ func NewReaderResponseWriterMsg(r *Request) *ResponseWriterMsg { return rw } +func (w *ResponseWriterMsg) Header() http.Header { + return w.r.Peer().HTTP.WriteHeaders +} + func (w *ResponseWriterMsg) Send(args any, e error) (err error) { cm := w.r.Msg() if e != nil { diff --git a/server.go b/server.go index 8a8247db622e6f16e9461329232446623ee11a45..ab37347a33578dcd1bff28247f6cb5a33becc453 100644 --- a/server.go +++ b/server.go @@ -135,16 +135,20 @@ type PeerInfo struct { RemoteAddr string // Addditional information for HTTP and WebSocket connections. - HTTP struct { - // Protocol version, i.e. "HTTP/1.1". This is not set for WebSocket. - Version string - // Header values sent by the client. - UserAgent string - Origin string - Host string - - Headers http.Header - } + HTTP HttpInfo +} + +type HttpInfo struct { + // Protocol version, i.e. "HTTP/1.1". This is not set for WebSocket. + Version string + // Header values sent by the client. + UserAgent string + Origin string + Host string + + Headers http.Header + + WriteHeaders http.Header } type peerInfoContextKey struct{}