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