@cryptotaxi247 / kubo / commits / 5f246e321

[http_proxy_over_p2p] httputil.ReverseProxy

Reimplement http-request proxying ala httputil.ReverseProxy. NB: this is proxies the request synchronously (sends all request-body before reading any response). License: MIT Signed-off-by: Chris Boddy <chris@boddy.im>

Chris Boddy committed Oct 2, 2018 at 17:18 UTC 5f246e3211cba21c2e6122ee1c535458b13ad3a5
2 files changed +43 -50
core/corehttp/proxy.go
+24 -25
@@ -5,16 +5,17 @@ import (
5 "fmt"
6 "net"
7 "net/http"
8 - //"net/http/httputil"
8 + "net/http/httputil"
9 "strings"
10
11 core "github.com/ipfs/go-ipfs/core"
12
13 protocol "gx/ipfs/QmZNkThpqfVXs9GNbexPrfBbXSLNYeKrE7jwFM2oqHbyqN/go-libp2p-protocol"
14 peer "gx/ipfs/QmbNepETomvmXfz1X5pHNFD2QuPqnqi47dTd94QJWSorQ3/go-libp2p-peer"
15 + inet "gx/ipfs/QmfDPh144WGBqRxZb1TGDHerbMnZATrHZggAPw7putNnBq/go-libp2p-net"
16 )
17
17 -// This adds an endpoint for proxying a request to another ipfs peer
18 +// This adds an endpoint for proxying a HTTP request to another ipfs peer
19 func ProxyOption() ServeOption {
20 return func(ipfsNode *core.IpfsNode, _ net.Listener, mux *http.ServeMux) (*http.ServeMux, error) {
21 mux.HandleFunc("/proxy/http/", func(w http.ResponseWriter, request *http.Request) {
@@ -33,28 +34,7 @@ func ProxyOption() ServeOption {
34 return
35 }
36
36 - //httputil.ReverseProxy(
37 - // send request to peer
38 - proxyReq, err := http.NewRequest(request.Method, parsedRequest.httpPath, request.Body)
39 -
40 - if err != nil {
41 - handleError(w, "Failed to format proxy request", err, 500)
42 - return
43 - }
44 -
45 - proxyReq.Write(stream)
46 -
47 - s := bufio.NewReader(stream)
48 - proxyResponse, err := http.ReadResponse(s, proxyReq)
49 -
50 - defer func() { proxyResponse.Body.Close() }()
51 - if err != nil {
52 - msg := fmt.Sprintf("Failed to send request to stream '%v' to peer '%v'", parsedRequest.name, parsedRequest.target)
53 - handleError(w, msg, err, 500)
54 - return
55 - }
56 - // send client response
57 - proxyResponse.Write(w)
37 + newReverseHttpProxy(parsedRequest, &stream).ServeHTTP(w, request)
38 })
39 return mux, nil
40 }
@@ -85,9 +65,28 @@ func parseRequest(request *http.Request) (*proxyRequest, error) {
65 return &proxyRequest{peerID, split[4], split[5]}, nil
66 }
67
88 -// log error and send response to client
68 func handleError(w http.ResponseWriter, msg string, err error, code int) {
69 w.WriteHeader(code)
70 fmt.Fprintf(w, "%s: %s\n", msg, err)
71 log.Warningf("server error: %s: %s", err)
72 }
73 +
74 +func newReverseHttpProxy(req *proxyRequest, streamToPeer *inet.Stream) *httputil.ReverseProxy {
75 + director := func(r *http.Request) {
76 + r.URL.Path = req.httpPath //the scheme etc. doesn't matter
77 + }
78 +
79 + return &httputil.ReverseProxy{
80 + Director: director,
81 + Transport: &roundTripper{streamToPeer}}
82 +}
83 +
84 +type roundTripper struct {
85 + stream *inet.Stream
86 +}
87 +
88 +func (self *roundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
89 + req.Write(*self.stream)
90 + s := bufio.NewReader(*self.stream)
91 + return http.ReadResponse(s, req)
92 +}
test/sharness/t0184-http-proxy-over-p2p.sh
+19 -25
@@ -55,6 +55,9 @@ function setup_sender_ipfs() {
55 sleep 5
56 }
57
58 +function setup_sender_and_receiver_ipfs() {
59 + setup_receiver_ipfs && setup_sender_ipfs
60 +}
61
62 function teardown_sender_and_receiver() {
63 kill -9 $SENDER_PID $RECEIVER_PID > /dev/null 2>&1
@@ -64,9 +67,9 @@ function teardown_sender_and_receiver() {
67 function curl_check_response_code() {
68 local expected_status_code=$1
69 local path_stub=${2:-http/$RECEIVER_ID/test/index.txt}
67 - local status_code=$(curl -s --write-out %{http_code} --output /dev/null http://localhost:5001/proxy/$path_stub)
70 + local status_code=$(curl -s --write-out %{http_code} --output /dev/null http://localhost:5001/proxy/http/$path_stub)
71
69 - if [[ $status_code -ne $expected_status_code ]];
72 + if [[ "$status_code" -ne "$expected_status_code" ]];
73 then
74 echo "Found status-code "$status_code", expected "$expected_status_code
75 return 1
@@ -108,44 +111,35 @@ function curl_send_proxy_request_and_check_response() {
111 }
112
113
111 -#test_expect_success 'handle proxy http request propogates error response from remote' '
112 -#serve_http_once "SORRY GUYS, I LOST IT" "404 Not Found" &&
113 -#setup_receiver_ipfs &&
114 -#setup_sender_ipfs &&
115 -#curl_send_proxy_request_and_check_response 404 "SORRY GUYS, I LOST IT"
116 -#'
117 -#kill -9 $REMOTE_SERVER_PID
118 -#teardown_sender_and_receiver
114 +test_expect_success 'handle proxy http request propogates error response from remote' '
115 +serve_http_once "SORRY GUYS, I LOST IT" "404 Not Found" &&
116 +setup_sender_and_receiver_ipfs &&
117 +curl_send_proxy_request_and_check_response 404 "SORRY GUYS, I LOST IT"
118 +'
119 +teardown_sender_and_receiver
120
120 -test_expect_success 'handle proxy http request when remote server not available ' '
121 -setup_receiver_ipfs &&
122 -setup_sender_ipfs &&
123 -curl_check_response_code "000"
121 +test_expect_success 'handle proxy http request sends bad-gateway when remote server not available ' '
122 +setup_sender_and_receiver_ipfs &&
123 +curl_send_proxy_request_and_check_response 502 ""
124 '
125 teardown_sender_and_receiver
126
127 test_expect_success 'handle proxy http request ' '
128 serve_http_once "THE WOODS ARE LOVELY DARK AND DEEP" &&
129 -setup_receiver_ipfs &&
130 -setup_sender_ipfs &&
129 +setup_sender_and_receiver_ipfs &&
130 curl_send_proxy_request_and_check_response 200 "THE WOODS ARE LOVELY DARK AND DEEP"
131 '
133 -kill -9 $REMOTE_SERVER_PID
132 teardown_sender_and_receiver
133
136 -
137 -
134 test_expect_success 'handle proxy http request invalid request' '
139 -setup_receiver_ipfs &&
140 -setup_sender_ipfs &&
141 -curl_check_response_code 404 DERPDERPDERP
135 +setup_sender_and_receiver_ipfs &&
136 +curl_check_response_code 400 DERPDERPDERP
137 '
138 teardown_sender_and_receiver
139
140 test_expect_success 'handle proxy http request unknown proxy peer ' '
146 -setup_receiver_ipfs &&
147 -setup_sender_ipfs &&
148 -curl_check_response_code 400 http/unknown_peer/test/index.txt
141 +setup_sender_and_receiver_ipfs &&
142 +curl_check_response_code 400 unknown_peer/test/index.txt
143 '
144 teardown_sender_and_receiver
145