Skip to content

Commit

Permalink
feat: support client headers request
Browse files Browse the repository at this point in the history
currently support client custom headers and convert to metadata.MD for grpc.
  • Loading branch information
Ja7ad committed Jun 9, 2024
1 parent 95647c5 commit c18bd7d
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 8 deletions.
17 changes: 15 additions & 2 deletions _example/proto/echo_jgw.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

44 changes: 43 additions & 1 deletion jrpc/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ package jrpc
import (
"context"
"encoding/json"
"github.com/creachadair/jrpc2"
"google.golang.org/grpc/metadata"
"io"
"net"
"net/http"
"time"
Expand All @@ -22,6 +25,11 @@ type Server struct {
handler http.Handler
}

type paramsAndHeaders struct {
Headers metadata.MD `json:"headers,omitempty"`
Params json.RawMessage `json:"params"`
}

// NewServer create json rpc server
func NewServer() *Server {
sv := new(Server)
Expand Down Expand Up @@ -58,9 +66,43 @@ func (s *Server) RegisterServices(svs ...Service) {
hd[m] = handler.New(h)
}
}
s.handler = jhttp.NewBridge(hd, nil)
s.handler = jhttp.NewBridge(hd, &jhttp.BridgeOptions{
ParseRequest: func(req *http.Request) ([]*jrpc2.ParsedRequest, error) {
body, err := io.ReadAll(req.Body)
if err != nil {
return nil, err
}
prs, err := jrpc2.ParseRequests(body)
if err != nil {
return nil, err
}

// Decorate the incoming request parameters with the headers.
for _, pr := range prs {
w, err := json.Marshal(paramsAndHeaders{
Headers: headersToMetadata(req),
Params: pr.Params,
})
if err != nil {
return nil, err
}
pr.Params = w
}
return prs, nil
},
})
}

func (s *Server) httpHandler(w http.ResponseWriter, r *http.Request) {
s.handler.ServeHTTP(w, r)
}

func headersToMetadata(r *http.Request) metadata.MD {
headersMap := make(map[string]string)
for key, values := range r.Header {
if len(values) > 0 {
headersMap[key] = values[0]
}
}
return metadata.New(headersMap)
}
16 changes: 13 additions & 3 deletions jrpc/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,16 @@ func (ms *MockService) Methods() map[string]method {
}

func (ms *MockService) testMethod(ctx context.Context, message json.RawMessage) (any, error) {
var ph paramsAndHeaders
if err := json.Unmarshal(message, &ph); err != nil {
return nil, err
}

var params map[string]string
if err := json.Unmarshal(message, &params); err != nil {
if err := json.Unmarshal(ph.Params, &params); err != nil {
return nil, err
}

return map[string]string{"response": "Hello " + params["name"]}, nil
}

Expand All @@ -34,15 +40,19 @@ func TestServer(t *testing.T) {
mockService := &MockService{}
server.RegisterServices(mockService)

// Create a listener for the server
listener, err := net.Listen("tcp", "127.0.0.1:0")
assert.NoError(t, err, "Failed to create listener")

serverStarted := make(chan struct{})

go func() {
err = server.Serve(listener)
close(serverStarted)
err := server.Serve(listener)
assert.Error(t, err, "Server failed to serve")
}()

<-serverStarted

requestBody, err := json.Marshal(map[string]any{
"jsonrpc": "2.0",
"id": "1",
Expand Down
18 changes: 16 additions & 2 deletions protoc-gen-jrpc-gateway/internal/jgw.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit c18bd7d

Please sign in to comment.