support full urls (with eg tcp:// prefix)
This commit is contained in:
parent
dea910cd3e
commit
479510be0e
|
@ -8,26 +8,40 @@ import (
|
|||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
. "github.com/tendermint/go-common"
|
||||
"github.com/tendermint/go-rpc/types"
|
||||
"github.com/tendermint/go-wire"
|
||||
)
|
||||
|
||||
// Set the net.Dial manually so we can do http over tcp or unix.
|
||||
// Get/Post require a dummyDomain but it's over written by the Transport
|
||||
var dummyDomain = "http://dummyDomain"
|
||||
// TODO: Deprecate support for IP:PORT or /path/to/socket
|
||||
func makeHTTPDialer(remoteAddr string) (string, func(string, string) (net.Conn, error)) {
|
||||
|
||||
func dialer(remote string) func(string, string) (net.Conn, error) {
|
||||
return func(proto, addr string) (conn net.Conn, err error) {
|
||||
return net.Dial(rpctypes.SocketType(remote), remote)
|
||||
parts := strings.SplitN(remoteAddr, "://", 2)
|
||||
var protocol, address string
|
||||
if len(parts) != 2 {
|
||||
log.Warn("WARNING (go-rpc): Please use fully formed listening addresses, including the tcp:// or unix:// prefix")
|
||||
protocol = rpctypes.SocketType(remoteAddr)
|
||||
address = remoteAddr
|
||||
} else {
|
||||
protocol, address = parts[0], parts[1]
|
||||
}
|
||||
|
||||
trimmedAddress := strings.Replace(address, "/", ".", -1) // replace / with . for http requests (dummy domain)
|
||||
return trimmedAddress, func(proto, addr string) (net.Conn, error) {
|
||||
return net.Dial(protocol, address)
|
||||
}
|
||||
}
|
||||
|
||||
// remote is IP:PORT or /path/to/socket
|
||||
func socketTransport(remote string) *http.Transport {
|
||||
return &http.Transport{
|
||||
Dial: dialer(remote),
|
||||
// We overwrite the http.Client.Dial so we can do http over tcp or unix.
|
||||
// remoteAddr should be fully featured (eg. with tcp:// or unix://)
|
||||
func makeHTTPClient(remoteAddr string) (string, *http.Client) {
|
||||
address, dialer := makeHTTPDialer(remoteAddr)
|
||||
return "http://" + address, &http.Client{
|
||||
Transport: &http.Transport{
|
||||
Dial: dialer,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,14 +54,15 @@ type Client interface {
|
|||
|
||||
// JSON rpc takes params as a slice
|
||||
type ClientJSONRPC struct {
|
||||
remote string
|
||||
address string
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
func NewClientJSONRPC(remote string) *ClientJSONRPC {
|
||||
address, client := makeHTTPClient(remote)
|
||||
return &ClientJSONRPC{
|
||||
remote: remote,
|
||||
client: &http.Client{Transport: socketTransport(remote)},
|
||||
address: address,
|
||||
client: client,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,7 +81,7 @@ func (c *ClientJSONRPC) call(method string, params []interface{}, result interfa
|
|||
requestBytes := wire.JSONBytes(request)
|
||||
requestBuf := bytes.NewBuffer(requestBytes)
|
||||
// log.Info(Fmt("RPC request to %v (%v): %v", c.remote, method, string(requestBytes)))
|
||||
httpResponse, err := c.client.Post(dummyDomain, "text/json", requestBuf)
|
||||
httpResponse, err := c.client.Post(c.address, "text/json", requestBuf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -83,14 +98,15 @@ func (c *ClientJSONRPC) call(method string, params []interface{}, result interfa
|
|||
|
||||
// URI takes params as a map
|
||||
type ClientURI struct {
|
||||
remote string
|
||||
address string
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
func NewClientURI(remote string) *ClientURI {
|
||||
address, client := makeHTTPClient(remote)
|
||||
return &ClientURI{
|
||||
remote: remote,
|
||||
client: &http.Client{Transport: socketTransport(remote)},
|
||||
address: address,
|
||||
client: client,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,8 +119,8 @@ func (c *ClientURI) call(method string, params map[string]interface{}, result in
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Info(Fmt("URI request to %v (%v): %v", c.remote, method, values))
|
||||
resp, err := c.client.PostForm(dummyDomain+"/"+method, values)
|
||||
log.Info(Fmt("URI request to %v (%v): %v", c.address, method, values))
|
||||
resp, err := c.client.PostForm(c.address+"/"+method, values)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package rpcclient
|
|||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
|
@ -21,15 +22,18 @@ type WSClient struct {
|
|||
QuitService
|
||||
Address string // IP:PORT or /path/to/socket
|
||||
Endpoint string // /websocket/url/endpoint
|
||||
Dialer func(string, string) (net.Conn, error)
|
||||
*websocket.Conn
|
||||
ResultsCh chan json.RawMessage // closes upon WSClient.Stop()
|
||||
ErrorsCh chan error // closes upon WSClient.Stop()
|
||||
}
|
||||
|
||||
// create a new connection
|
||||
func NewWSClient(addr, endpoint string) *WSClient {
|
||||
func NewWSClient(remoteAddr, endpoint string) *WSClient {
|
||||
addr, dialer := makeHTTPDialer(remoteAddr)
|
||||
wsClient := &WSClient{
|
||||
Address: addr,
|
||||
Dialer: dialer,
|
||||
Endpoint: endpoint,
|
||||
Conn: nil,
|
||||
ResultsCh: make(chan json.RawMessage, wsResultsChannelCapacity),
|
||||
|
@ -57,11 +61,11 @@ func (wsc *WSClient) dial() error {
|
|||
|
||||
// Dial
|
||||
dialer := &websocket.Dialer{
|
||||
NetDial: dialer(wsc.Address),
|
||||
NetDial: wsc.Dialer,
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
}
|
||||
rHeader := http.Header{}
|
||||
con, _, err := dialer.Dial("ws://"+dummyDomain+wsc.Endpoint, rHeader)
|
||||
con, _, err := dialer.Dial("ws://"+wsc.Address+wsc.Endpoint, rHeader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -13,8 +13,8 @@ import (
|
|||
|
||||
// Client and Server should work over tcp or unix sockets
|
||||
var (
|
||||
tcpAddr = "0.0.0.0:46657"
|
||||
unixAddr = "/tmp/go-rpc.sock" // NOTE: must remove file for test to run again
|
||||
tcpAddr = "tcp://0.0.0.0:46657"
|
||||
unixAddr = "unix:///tmp/go-rpc.sock" // NOTE: must remove file for test to run again
|
||||
|
||||
websocketEndpoint = "/websocket/endpoint"
|
||||
)
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"net"
|
||||
"net/http"
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
. "github.com/tendermint/go-common"
|
||||
|
@ -15,11 +16,23 @@ import (
|
|||
//"github.com/tendermint/go-wire"
|
||||
)
|
||||
|
||||
func StartHTTPServer(listenAddr string, handler http.Handler) (net.Listener, error) {
|
||||
// listenAddr is `IP:PORT` or /path/to/socket
|
||||
socketType := SocketType(listenAddr)
|
||||
log.Notice(Fmt("Starting RPC HTTP server on %s socket %v", socketType, listenAddr))
|
||||
listener, err := net.Listen(socketType, listenAddr)
|
||||
func StartHTTPServer(listenAddr string, handler http.Handler) (listener net.Listener, err error) {
|
||||
// listenAddr should be fully formed including tcp:// or unix:// prefix
|
||||
var proto, addr string
|
||||
parts := strings.SplitN(listenAddr, "://", 2)
|
||||
if len(parts) != 2 {
|
||||
log.Warn("WARNING (go-rpc): Please use fully formed listening addresses, including the tcp:// or unix:// prefix")
|
||||
// we used to allow addrs without tcp/unix prefix by checking for a colon
|
||||
// TODO: Deprecate
|
||||
proto = SocketType(listenAddr)
|
||||
addr = listenAddr
|
||||
// return nil, fmt.Errorf("Invalid listener address %s", lisenAddr)
|
||||
} else {
|
||||
proto, addr = parts[0], parts[1]
|
||||
}
|
||||
|
||||
log.Notice(Fmt("Starting RPC HTTP server on %s socket %v", proto, addr))
|
||||
listener, err = net.Listen(proto, addr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to listen to %v: %v", listenAddr, err)
|
||||
}
|
||||
|
|
|
@ -2,6 +2,6 @@ package rpc
|
|||
|
||||
const Maj = "0"
|
||||
const Min = "5" // refactored out of tendermint/tendermint; RPCResponse.Result is RawJSON
|
||||
const Fix = "0"
|
||||
const Fix = "1" // support tcp:// or unix:// prefixes
|
||||
|
||||
const Version = Maj + "." + Min + "." + Fix
|
||||
|
|
Loading…
Reference in New Issue