[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