http.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. // Copyright 2015 The go-ethereum Authors
  2. // This file is part of the go-ethereum library.
  3. //
  4. // The go-ethereum library is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // The go-ethereum library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
  16. package rpc
  17. import (
  18. "bytes"
  19. "context"
  20. "encoding/json"
  21. "errors"
  22. "fmt"
  23. "io"
  24. "io/ioutil"
  25. "mime"
  26. "net"
  27. "net/http"
  28. "strings"
  29. "sync"
  30. "time"
  31. "github.com/ethereum/go-ethereum/log"
  32. "github.com/rs/cors"
  33. )
  34. const (
  35. maxRequestContentLength = 1024 * 1024 * 5
  36. contentType = "application/json"
  37. )
  38. // https://www.jsonrpc.org/historical/json-rpc-over-http.html#id13
  39. var acceptedContentTypes = []string{contentType, "application/json-rpc", "application/jsonrequest"}
  40. type httpConn struct {
  41. client *http.Client
  42. req *http.Request
  43. closeOnce sync.Once
  44. closed chan interface{}
  45. }
  46. // httpConn is treated specially by Client.
  47. func (hc *httpConn) Write(context.Context, interface{}) error {
  48. panic("Write called on httpConn")
  49. }
  50. func (hc *httpConn) RemoteAddr() string {
  51. return hc.req.URL.String()
  52. }
  53. func (hc *httpConn) Read() ([]*jsonrpcMessage, bool, error) {
  54. <-hc.closed
  55. return nil, false, io.EOF
  56. }
  57. func (hc *httpConn) Close() {
  58. hc.closeOnce.Do(func() { close(hc.closed) })
  59. }
  60. func (hc *httpConn) Closed() <-chan interface{} {
  61. return hc.closed
  62. }
  63. // HTTPTimeouts represents the configuration params for the HTTP RPC server.
  64. type HTTPTimeouts struct {
  65. // ReadTimeout is the maximum duration for reading the entire
  66. // request, including the body.
  67. //
  68. // Because ReadTimeout does not let Handlers make per-request
  69. // decisions on each request body's acceptable deadline or
  70. // upload rate, most users will prefer to use
  71. // ReadHeaderTimeout. It is valid to use them both.
  72. ReadTimeout time.Duration
  73. // WriteTimeout is the maximum duration before timing out
  74. // writes of the response. It is reset whenever a new
  75. // request's header is read. Like ReadTimeout, it does not
  76. // let Handlers make decisions on a per-request basis.
  77. WriteTimeout time.Duration
  78. // IdleTimeout is the maximum amount of time to wait for the
  79. // next request when keep-alives are enabled. If IdleTimeout
  80. // is zero, the value of ReadTimeout is used. If both are
  81. // zero, ReadHeaderTimeout is used.
  82. IdleTimeout time.Duration
  83. }
  84. // DefaultHTTPTimeouts represents the default timeout values used if further
  85. // configuration is not provided.
  86. var DefaultHTTPTimeouts = HTTPTimeouts{
  87. ReadTimeout: 30 * time.Second,
  88. WriteTimeout: 30 * time.Second,
  89. IdleTimeout: 120 * time.Second,
  90. }
  91. // DialHTTPWithClient creates a new RPC client that connects to an RPC server over HTTP
  92. // using the provided HTTP Client.
  93. func DialHTTPWithClient(endpoint string, client *http.Client) (*Client, error) {
  94. req, err := http.NewRequest(http.MethodPost, endpoint, nil)
  95. if err != nil {
  96. return nil, err
  97. }
  98. req.Header.Set("Content-Type", contentType)
  99. req.Header.Set("Accept", contentType)
  100. initctx := context.Background()
  101. return newClient(initctx, func(context.Context) (ServerCodec, error) {
  102. return &httpConn{client: client, req: req, closed: make(chan interface{})}, nil
  103. })
  104. }
  105. // DialHTTP creates a new RPC client that connects to an RPC server over HTTP.
  106. func DialHTTP(endpoint string) (*Client, error) {
  107. return DialHTTPWithClient(endpoint, new(http.Client))
  108. }
  109. func (c *Client) sendHTTP(ctx context.Context, op *requestOp, msg interface{}) error {
  110. hc := c.writeConn.(*httpConn)
  111. respBody, err := hc.doRequest(ctx, msg)
  112. if respBody != nil {
  113. defer respBody.Close()
  114. }
  115. if err != nil {
  116. if respBody != nil {
  117. buf := new(bytes.Buffer)
  118. if _, err2 := buf.ReadFrom(respBody); err2 == nil {
  119. return fmt.Errorf("%v %v", err, buf.String())
  120. }
  121. }
  122. return err
  123. }
  124. var respmsg jsonrpcMessage
  125. if err := json.NewDecoder(respBody).Decode(&respmsg); err != nil {
  126. return err
  127. }
  128. op.resp <- &respmsg
  129. return nil
  130. }
  131. func (c *Client) sendBatchHTTP(ctx context.Context, op *requestOp, msgs []*jsonrpcMessage) error {
  132. hc := c.writeConn.(*httpConn)
  133. respBody, err := hc.doRequest(ctx, msgs)
  134. if err != nil {
  135. return err
  136. }
  137. defer respBody.Close()
  138. var respmsgs []jsonrpcMessage
  139. if err := json.NewDecoder(respBody).Decode(&respmsgs); err != nil {
  140. return err
  141. }
  142. for i := 0; i < len(respmsgs); i++ {
  143. op.resp <- &respmsgs[i]
  144. }
  145. return nil
  146. }
  147. func (hc *httpConn) doRequest(ctx context.Context, msg interface{}) (io.ReadCloser, error) {
  148. body, err := json.Marshal(msg)
  149. if err != nil {
  150. return nil, err
  151. }
  152. req := hc.req.WithContext(ctx)
  153. req.Body = ioutil.NopCloser(bytes.NewReader(body))
  154. req.ContentLength = int64(len(body))
  155. resp, err := hc.client.Do(req)
  156. if err != nil {
  157. return nil, err
  158. }
  159. if resp.StatusCode < 200 || resp.StatusCode >= 300 {
  160. return resp.Body, errors.New(resp.Status)
  161. }
  162. return resp.Body, nil
  163. }
  164. // httpServerConn turns a HTTP connection into a Conn.
  165. type httpServerConn struct {
  166. io.Reader
  167. io.Writer
  168. r *http.Request
  169. }
  170. func newHTTPServerConn(r *http.Request, w http.ResponseWriter) ServerCodec {
  171. body := io.LimitReader(r.Body, maxRequestContentLength)
  172. conn := &httpServerConn{Reader: body, Writer: w, r: r}
  173. return NewJSONCodec(conn)
  174. }
  175. // Close does nothing and always returns nil.
  176. func (t *httpServerConn) Close() error { return nil }
  177. // RemoteAddr returns the peer address of the underlying connection.
  178. func (t *httpServerConn) RemoteAddr() string {
  179. return t.r.RemoteAddr
  180. }
  181. // SetWriteDeadline does nothing and always returns nil.
  182. func (t *httpServerConn) SetWriteDeadline(time.Time) error { return nil }
  183. // NewHTTPServer creates a new HTTP RPC server around an API provider.
  184. //
  185. // Deprecated: Server implements http.Handler
  186. func NewHTTPServer(cors []string, vhosts []string, timeouts HTTPTimeouts, srv http.Handler) *http.Server {
  187. // Wrap the CORS-handler within a host-handler
  188. handler := newCorsHandler(srv, cors)
  189. handler = newVHostHandler(vhosts, handler)
  190. // Make sure timeout values are meaningful
  191. if timeouts.ReadTimeout < time.Second {
  192. log.Warn("Sanitizing invalid HTTP read timeout", "provided", timeouts.ReadTimeout, "updated", DefaultHTTPTimeouts.ReadTimeout)
  193. timeouts.ReadTimeout = DefaultHTTPTimeouts.ReadTimeout
  194. }
  195. if timeouts.WriteTimeout < time.Second {
  196. log.Warn("Sanitizing invalid HTTP write timeout", "provided", timeouts.WriteTimeout, "updated", DefaultHTTPTimeouts.WriteTimeout)
  197. timeouts.WriteTimeout = DefaultHTTPTimeouts.WriteTimeout
  198. }
  199. if timeouts.IdleTimeout < time.Second {
  200. log.Warn("Sanitizing invalid HTTP idle timeout", "provided", timeouts.IdleTimeout, "updated", DefaultHTTPTimeouts.IdleTimeout)
  201. timeouts.IdleTimeout = DefaultHTTPTimeouts.IdleTimeout
  202. }
  203. // Bundle and start the HTTP server
  204. return &http.Server{
  205. Handler: handler,
  206. ReadTimeout: timeouts.ReadTimeout,
  207. WriteTimeout: timeouts.WriteTimeout,
  208. IdleTimeout: timeouts.IdleTimeout,
  209. }
  210. }
  211. // ServeHTTP serves JSON-RPC requests over HTTP.
  212. func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  213. // Permit dumb empty requests for remote health-checks (AWS)
  214. if r.Method == http.MethodGet && r.ContentLength == 0 && r.URL.RawQuery == "" {
  215. return
  216. }
  217. if code, err := validateRequest(r); err != nil {
  218. http.Error(w, err.Error(), code)
  219. return
  220. }
  221. // All checks passed, create a codec that reads direct from the request body
  222. // untilEOF and writes the response to w and order the server to process a
  223. // single request.
  224. ctx := r.Context()
  225. ctx = context.WithValue(ctx, "remote", r.RemoteAddr)
  226. ctx = context.WithValue(ctx, "scheme", r.Proto)
  227. ctx = context.WithValue(ctx, "local", r.Host)
  228. if ua := r.Header.Get("User-Agent"); ua != "" {
  229. ctx = context.WithValue(ctx, "User-Agent", ua)
  230. }
  231. if origin := r.Header.Get("Origin"); origin != "" {
  232. ctx = context.WithValue(ctx, "Origin", origin)
  233. }
  234. w.Header().Set("content-type", contentType)
  235. codec := newHTTPServerConn(r, w)
  236. defer codec.Close()
  237. s.serveSingleRequest(ctx, codec)
  238. }
  239. // validateRequest returns a non-zero response code and error message if the
  240. // request is invalid.
  241. func validateRequest(r *http.Request) (int, error) {
  242. if r.Method == http.MethodPut || r.Method == http.MethodDelete {
  243. return http.StatusMethodNotAllowed, errors.New("method not allowed")
  244. }
  245. if r.ContentLength > maxRequestContentLength {
  246. err := fmt.Errorf("content length too large (%d>%d)", r.ContentLength, maxRequestContentLength)
  247. return http.StatusRequestEntityTooLarge, err
  248. }
  249. // Allow OPTIONS (regardless of content-type)
  250. if r.Method == http.MethodOptions {
  251. return 0, nil
  252. }
  253. // Check content-type
  254. if mt, _, err := mime.ParseMediaType(r.Header.Get("content-type")); err == nil {
  255. for _, accepted := range acceptedContentTypes {
  256. if accepted == mt {
  257. return 0, nil
  258. }
  259. }
  260. }
  261. // Invalid content-type
  262. err := fmt.Errorf("invalid content type, only %s is supported", contentType)
  263. return http.StatusUnsupportedMediaType, err
  264. }
  265. func newCorsHandler(srv http.Handler, allowedOrigins []string) http.Handler {
  266. // disable CORS support if user has not specified a custom CORS configuration
  267. if len(allowedOrigins) == 0 {
  268. return srv
  269. }
  270. c := cors.New(cors.Options{
  271. AllowedOrigins: allowedOrigins,
  272. AllowedMethods: []string{http.MethodPost, http.MethodGet},
  273. MaxAge: 600,
  274. AllowedHeaders: []string{"*"},
  275. })
  276. return c.Handler(srv)
  277. }
  278. // virtualHostHandler is a handler which validates the Host-header of incoming requests.
  279. // The virtualHostHandler can prevent DNS rebinding attacks, which do not utilize CORS-headers,
  280. // since they do in-domain requests against the RPC api. Instead, we can see on the Host-header
  281. // which domain was used, and validate that against a whitelist.
  282. type virtualHostHandler struct {
  283. vhosts map[string]struct{}
  284. next http.Handler
  285. }
  286. // ServeHTTP serves JSON-RPC requests over HTTP, implements http.Handler
  287. func (h *virtualHostHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  288. // if r.Host is not set, we can continue serving since a browser would set the Host header
  289. if r.Host == "" {
  290. h.next.ServeHTTP(w, r)
  291. return
  292. }
  293. host, _, err := net.SplitHostPort(r.Host)
  294. if err != nil {
  295. // Either invalid (too many colons) or no port specified
  296. host = r.Host
  297. }
  298. if ipAddr := net.ParseIP(host); ipAddr != nil {
  299. // It's an IP address, we can serve that
  300. h.next.ServeHTTP(w, r)
  301. return
  302. }
  303. // Not an ip address, but a hostname. Need to validate
  304. if _, exist := h.vhosts["*"]; exist {
  305. h.next.ServeHTTP(w, r)
  306. return
  307. }
  308. if _, exist := h.vhosts[host]; exist {
  309. h.next.ServeHTTP(w, r)
  310. return
  311. }
  312. http.Error(w, "invalid host specified", http.StatusForbidden)
  313. }
  314. func newVHostHandler(vhosts []string, next http.Handler) http.Handler {
  315. vhostMap := make(map[string]struct{})
  316. for _, allowedHost := range vhosts {
  317. vhostMap[strings.ToLower(allowedHost)] = struct{}{}
  318. }
  319. return &virtualHostHandler{vhostMap, next}
  320. }