Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion execution/grpc/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ package grpc

import (
"context"
"crypto/tls"
"fmt"
"net"
"net/http"
"time"

"connectrpc.com/connect"
"golang.org/x/net/http2"
"google.golang.org/protobuf/types/known/timestamppb"

"github.com/evstack/ev-node/core/execution"
Expand All @@ -23,6 +26,20 @@ type Client struct {
client v1connect.ExecutorServiceClient
}

// newHTTP2Client creates an HTTP/2 client that supports cleartext (h2c) connections.
// This is required to connect to native gRPC servers without TLS.
func newHTTP2Client() *http.Client {
return &http.Client{
Transport: &http2.Transport{
AllowHTTP: true,
DialTLSContext: func(ctx context.Context, network, addr string, _ *tls.Config) (net.Conn, error) {
var d net.Dialer
return d.DialContext(ctx, network, addr)
},
},
}
Comment on lines +32 to +40
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The custom http.Client is created without any timeouts. This can lead to the client hanging indefinitely if the server is unresponsive, potentially causing resource exhaustion.

It's a good practice to configure timeouts for production-ready clients. Since all the RPCs in this service are unary, you can safely set a timeout on the http.Client for the entire request-response cycle. Additionally, setting a timeout on the net.Dialer is recommended to avoid long waits during connection establishment.

return &http.Client{
		Timeout: 60 * time.Second,
		Transport: &http2.Transport{
			AllowHTTP: true,
			DialTLSContext: func(ctx context.Context, network, addr string, _ *tls.Config) (net.Conn, error) {
				d := net.Dialer{Timeout: 15 * time.Second}
				return d.DialContext(ctx, network, addr)
			},
		},
	}

}

// NewClient creates a new gRPC execution client.
//
// Parameters:
Expand All @@ -32,9 +49,11 @@ type Client struct {
// Returns:
// - *Client: The initialized gRPC client
func NewClient(url string, opts ...connect.ClientOption) *Client {
// Prepend WithGRPC to use the native gRPC protocol (required for tonic/gRPC servers)
opts = append([]connect.ClientOption{connect.WithGRPC()}, opts...)
return &Client{
client: v1connect.NewExecutorServiceClient(
http.DefaultClient,
newHTTP2Client(),
url,
opts...,
),
Expand Down
Loading