Commit 5f246e32 authored by Chris Boddy's avatar Chris Boddy Committed by Steven Allen

[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: default avatarChris Boddy <chris@boddy.im>
parent 335bca2b
......@@ -5,16 +5,17 @@ import (
"fmt"
"net"
"net/http"
//"net/http/httputil"
"net/http/httputil"
"strings"
core "github.com/ipfs/go-ipfs/core"
protocol "gx/ipfs/QmZNkThpqfVXs9GNbexPrfBbXSLNYeKrE7jwFM2oqHbyqN/go-libp2p-protocol"
peer "gx/ipfs/QmbNepETomvmXfz1X5pHNFD2QuPqnqi47dTd94QJWSorQ3/go-libp2p-peer"
inet "gx/ipfs/QmfDPh144WGBqRxZb1TGDHerbMnZATrHZggAPw7putNnBq/go-libp2p-net"
)
// This adds an endpoint for proxying a request to another ipfs peer
// This adds an endpoint for proxying a HTTP request to another ipfs peer
func ProxyOption() ServeOption {
return func(ipfsNode *core.IpfsNode, _ net.Listener, mux *http.ServeMux) (*http.ServeMux, error) {
mux.HandleFunc("/proxy/http/", func(w http.ResponseWriter, request *http.Request) {
......@@ -33,28 +34,7 @@ func ProxyOption() ServeOption {
return
}
//httputil.ReverseProxy(
// send request to peer
proxyReq, err := http.NewRequest(request.Method, parsedRequest.httpPath, request.Body)
if err != nil {
handleError(w, "Failed to format proxy request", err, 500)
return
}
proxyReq.Write(stream)
s := bufio.NewReader(stream)
proxyResponse, err := http.ReadResponse(s, proxyReq)
defer func() { proxyResponse.Body.Close() }()
if err != nil {
msg := fmt.Sprintf("Failed to send request to stream '%v' to peer '%v'", parsedRequest.name, parsedRequest.target)
handleError(w, msg, err, 500)
return
}
// send client response
proxyResponse.Write(w)
newReverseHttpProxy(parsedRequest, &stream).ServeHTTP(w, request)
})
return mux, nil
}
......@@ -85,9 +65,28 @@ func parseRequest(request *http.Request) (*proxyRequest, error) {
return &proxyRequest{peerID, split[4], split[5]}, nil
}
// log error and send response to client
func handleError(w http.ResponseWriter, msg string, err error, code int) {
w.WriteHeader(code)
fmt.Fprintf(w, "%s: %s\n", msg, err)
log.Warningf("server error: %s: %s", err)
}
func newReverseHttpProxy(req *proxyRequest, streamToPeer *inet.Stream) *httputil.ReverseProxy {
director := func(r *http.Request) {
r.URL.Path = req.httpPath //the scheme etc. doesn't matter
}
return &httputil.ReverseProxy{
Director: director,
Transport: &roundTripper{streamToPeer}}
}
type roundTripper struct {
stream *inet.Stream
}
func (self *roundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
req.Write(*self.stream)
s := bufio.NewReader(*self.stream)
return http.ReadResponse(s, req)
}
......@@ -55,6 +55,9 @@ function setup_sender_ipfs() {
sleep 5
}
function setup_sender_and_receiver_ipfs() {
setup_receiver_ipfs && setup_sender_ipfs
}
function teardown_sender_and_receiver() {
kill -9 $SENDER_PID $RECEIVER_PID > /dev/null 2>&1
......@@ -64,9 +67,9 @@ function teardown_sender_and_receiver() {
function curl_check_response_code() {
local expected_status_code=$1
local path_stub=${2:-http/$RECEIVER_ID/test/index.txt}
local status_code=$(curl -s --write-out %{http_code} --output /dev/null http://localhost:5001/proxy/$path_stub)
local status_code=$(curl -s --write-out %{http_code} --output /dev/null http://localhost:5001/proxy/http/$path_stub)
if [[ $status_code -ne $expected_status_code ]];
if [[ "$status_code" -ne "$expected_status_code" ]];
then
echo "Found status-code "$status_code", expected "$expected_status_code
return 1
......@@ -108,44 +111,35 @@ function curl_send_proxy_request_and_check_response() {
}
#test_expect_success 'handle proxy http request propogates error response from remote' '
#serve_http_once "SORRY GUYS, I LOST IT" "404 Not Found" &&
#setup_receiver_ipfs &&
#setup_sender_ipfs &&
#curl_send_proxy_request_and_check_response 404 "SORRY GUYS, I LOST IT"
#'
#kill -9 $REMOTE_SERVER_PID
#teardown_sender_and_receiver
test_expect_success 'handle proxy http request propogates error response from remote' '
serve_http_once "SORRY GUYS, I LOST IT" "404 Not Found" &&
setup_sender_and_receiver_ipfs &&
curl_send_proxy_request_and_check_response 404 "SORRY GUYS, I LOST IT"
'
teardown_sender_and_receiver
test_expect_success 'handle proxy http request when remote server not available ' '
setup_receiver_ipfs &&
setup_sender_ipfs &&
curl_check_response_code "000"
test_expect_success 'handle proxy http request sends bad-gateway when remote server not available ' '
setup_sender_and_receiver_ipfs &&
curl_send_proxy_request_and_check_response 502 ""
'
teardown_sender_and_receiver
test_expect_success 'handle proxy http request ' '
serve_http_once "THE WOODS ARE LOVELY DARK AND DEEP" &&
setup_receiver_ipfs &&
setup_sender_ipfs &&
setup_sender_and_receiver_ipfs &&
curl_send_proxy_request_and_check_response 200 "THE WOODS ARE LOVELY DARK AND DEEP"
'
kill -9 $REMOTE_SERVER_PID
teardown_sender_and_receiver
test_expect_success 'handle proxy http request invalid request' '
setup_receiver_ipfs &&
setup_sender_ipfs &&
curl_check_response_code 404 DERPDERPDERP
setup_sender_and_receiver_ipfs &&
curl_check_response_code 400 DERPDERPDERP
'
teardown_sender_and_receiver
test_expect_success 'handle proxy http request unknown proxy peer ' '
setup_receiver_ipfs &&
setup_sender_ipfs &&
curl_check_response_code 400 http/unknown_peer/test/index.txt
setup_sender_and_receiver_ipfs &&
curl_check_response_code 400 unknown_peer/test/index.txt
'
teardown_sender_and_receiver
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment