master
sh 254 lines 7.98 KB
Raw
1 #!/usr/bin/env bash
2
3 test_description="Test http proxy over p2p"
4
5 . lib/test-lib.sh
6
7 if ! test_have_prereq SOCAT; then
8 skip_all="skipping '$test_description': socat is not available"
9 test_done
10 fi
11
12 WEB_SERVE_PORT=5099
13 IPFS_GATEWAY_PORT=5199
14 SENDER_GATEWAY="http://127.0.0.1:$IPFS_GATEWAY_PORT"
15
16 function show_logs() {
17
18 echo "*****************"
19 echo " RECEIVER LOG "
20 echo "*****************"
21 iptb logs 1
22 echo "*****************"
23 echo " SENDER LOG "
24 echo "*****************"
25 iptb logs 0
26 echo "*****************"
27 echo "REMOTE_SERVER LOG"
28 echo $REMOTE_SERVER_LOG
29 echo "*****************"
30 cat $REMOTE_SERVER_LOG
31 }
32
33 function start_http_server() {
34 REMOTE_SERVER_LOG="server.log"
35 rm -f $REMOTE_SERVER_LOG
36
37 touch response
38 socat tcp-listen:$WEB_SERVE_PORT,fork,bind=127.0.0.1,reuseaddr 'SYSTEM:cat response'!!CREATE:$REMOTE_SERVER_LOG &
39 REMOTE_SERVER_PID=$!
40
41 socat /dev/null tcp:127.0.01:$WEB_SERVE_PORT,retry=10
42 return $?
43 }
44
45 function teardown_remote_server() {
46 exec 7<&-
47 kill $REMOTE_SERVER_PID > /dev/null 2>&1
48 wait $REMOTE_SERVER_PID || true
49 }
50
51 function serve_content() {
52 local body=$1
53 local status_code=${2:-"200 OK"}
54 local length=$((1 + ${#body}))
55 echo -e "HTTP/1.1 $status_code\nContent-length: $length\n\n$body" > response
56 }
57
58 function curl_check_response_code() {
59 local expected_status_code=$1
60 local path_stub=${2:-p2p/$RECEIVER_ID/http/index.txt}
61 local status_code=$(curl -s --write-out %{http_code} --output /dev/null $SENDER_GATEWAY/$path_stub)
62
63 if [[ "$status_code" -ne "$expected_status_code" ]];
64 then
65 echo "Found status-code "$status_code", expected "$expected_status_code
66 return 1
67 fi
68
69 return 0
70 }
71
72 function curl_send_proxy_request_and_check_response() {
73 local expected_status_code=$1
74 local expected_content=$2
75
76 #
77 # make a request to SENDER_IPFS via the proxy endpoint
78 #
79 CONTENT_PATH="retrieved-file"
80 STATUS_CODE="$(curl -s -o $CONTENT_PATH --write-out %{http_code} $SENDER_GATEWAY/p2p/$RECEIVER_ID/http/index.txt)"
81
82 #
83 # check status code
84 #
85 if [[ "$STATUS_CODE" -ne "$expected_status_code" ]];
86 then
87 echo -e "Found status-code "$STATUS_CODE", expected "$expected_status_code
88 show_logs
89 return 1
90 fi
91
92 #
93 # check content
94 #
95 RESPONSE_CONTENT="$(tail -n 1 $CONTENT_PATH)"
96 if [[ "$RESPONSE_CONTENT" == "$expected_content" ]];
97 then
98 return 0
99 else
100 echo -e "Found response content:\n'"$RESPONSE_CONTENT"'\nthat differs from expected content:\n'"$expected_content"'"
101 return 1
102 fi
103 }
104
105 function curl_send_multipart_form_request() {
106 local expected_status_code=$1
107 local FILE_PATH="uploaded-file"
108 FILE_CONTENT="curl will send a multipart-form POST request when sending a file which is handy"
109 echo $FILE_CONTENT > $FILE_PATH
110 #
111 # send multipart form request
112 #
113 STATUS_CODE="$(curl -o /dev/null -s -F file=@$FILE_PATH --write-out %{http_code} $SENDER_GATEWAY/p2p/$RECEIVER_ID/http/index.txt)"
114 #
115 # check status code
116 #
117 if [[ "$STATUS_CODE" -ne "$expected_status_code" ]];
118 then
119 echo -e "Found status-code "$STATUS_CODE", expected "$expected_status_code
120 return 1
121 fi
122 #
123 # check request method
124 #
125 if ! grep "POST /index.txt" $REMOTE_SERVER_LOG > /dev/null;
126 then
127 echo "Remote server request method/resource path was incorrect"
128 show_logs
129 return 1
130 fi
131 #
132 # check request is multipart-form
133 #
134 if ! grep "Content-Type: multipart/form-data;" $REMOTE_SERVER_LOG > /dev/null;
135 then
136 echo "Request content-type was not multipart/form-data"
137 show_logs
138 return 1
139 fi
140 return 0
141 }
142
143 test_expect_success 'configure nodes' '
144 iptb testbed create -type localipfs -count 2 -force -init &&
145 iptb run -- ipfs config --json "Routing.LoopbackAddressesOnLanDHT" true &&
146 ipfsi 0 config --json Experimental.Libp2pStreamMounting true &&
147 ipfsi 1 config --json Experimental.Libp2pStreamMounting true &&
148 ipfsi 0 config --json Experimental.P2pHttpProxy true &&
149 ipfsi 0 config --json Addresses.Gateway "[\"/ip4/127.0.0.1/tcp/$IPFS_GATEWAY_PORT\"]"
150 '
151
152 test_expect_success 'configure a subdomain gateway with /p2p/ path whitelisted' "
153 ipfsi 0 config --json Gateway.PublicGateways '{
154 \"example.com\": {
155 \"UseSubdomains\": true,
156 \"Paths\": [\"/p2p/\"]
157 }
158 }'
159 "
160
161 test_expect_success 'start and connect nodes' '
162 iptb start -wait && iptb connect 0 1
163 '
164
165 test_expect_success 'setup p2p listener on the receiver' '
166 ipfsi 1 p2p listen --allow-custom-protocol /http /ip4/127.0.0.1/tcp/$WEB_SERVE_PORT &&
167 ipfsi 1 p2p listen /x/custom/http /ip4/127.0.0.1/tcp/$WEB_SERVE_PORT
168 '
169
170 test_expect_success 'setup environment' '
171 RECEIVER_ID=$(ipfsi 1 id -f="<id>" --peerid-base=b58mh)
172 RECEIVER_ID_CIDv1=$(ipfsi 1 id -f="<id>" --peerid-base=base36)
173 '
174
175 test_expect_success 'handle proxy http request sends bad-gateway when remote server not available ' '
176 curl_send_proxy_request_and_check_response 502 ""
177 '
178
179 test_expect_success 'start http server' '
180 start_http_server
181 '
182
183 test_expect_success 'handle proxy http request propagates error response from remote' '
184 serve_content "SORRY GUYS, I LOST IT" "404 Not Found" &&
185 curl_send_proxy_request_and_check_response 404 "SORRY GUYS, I LOST IT"
186 '
187
188 test_expect_success 'handle proxy http request ' '
189 serve_content "THE WOODS ARE LOVELY DARK AND DEEP" &&
190 curl_send_proxy_request_and_check_response 200 "THE WOODS ARE LOVELY DARK AND DEEP"
191 '
192
193 test_expect_success 'handle proxy http request invalid request' '
194 curl_check_response_code 400 p2p/DERPDERPDERP
195 '
196
197 test_expect_success 'handle proxy http request unknown proxy peer ' '
198 UNKNOWN_PEER="k51qzi5uqu5dlmbel1sd8rs4emr3bfosk9bm4eb42514r4lakt4oxw3a3fa2tm" &&
199 curl_check_response_code 502 p2p/$UNKNOWN_PEER/http/index.txt
200 '
201
202 test_expect_success 'handle proxy http request to invalid proxy peer ' '
203 curl_check_response_code 400 p2p/invalid_peer/http/index.txt
204 '
205
206 test_expect_success 'handle proxy http request to custom protocol' '
207 serve_content "THE WOODS ARE LOVELY DARK AND DEEP" &&
208 curl_check_response_code 200 p2p/$RECEIVER_ID/x/custom/http/index.txt
209 '
210
211 test_expect_success 'handle proxy http request to missing protocol' '
212 serve_content "THE WOODS ARE LOVELY DARK AND DEEP" &&
213 curl_check_response_code 502 p2p/$RECEIVER_ID/x/missing/http/index.txt
214 '
215
216 test_expect_success 'handle proxy http request missing the /http' '
217 curl_check_response_code 400 p2p/$RECEIVER_ID/x/custom/index.txt
218 '
219
220 test_expect_success 'handle multipart/form-data http request' '
221 serve_content "OK" &&
222 curl_send_multipart_form_request 200
223 '
224
225 # OK: $peerid.p2p.example.com/http/index.txt
226 test_expect_success "handle http request to a subdomain gateway" '
227 serve_content "SUBDOMAIN PROVIDES ORIGIN ISOLATION PER RECEIVER_ID" &&
228 curl -H "Host: $RECEIVER_ID_CIDv1.p2p.example.com" -sD - $SENDER_GATEWAY/http/index.txt > p2p_response &&
229 test_should_contain "SUBDOMAIN PROVIDES ORIGIN ISOLATION PER RECEIVER_ID" p2p_response
230 '
231
232 # FAIL: $peerid.p2p.example.com/p2p/$peerid/http/index.txt
233 test_expect_success "handle invalid http request to a subdomain gateway" '
234 serve_content "SUBDOMAIN DOES NOT SUPPORT FULL /p2p/ PATH" &&
235 curl -H "Host: $RECEIVER_ID_CIDv1.p2p.example.com" -sD - $SENDER_GATEWAY/p2p/$RECEIVER_ID/http/index.txt > p2p_response &&
236 test_should_contain "400 Bad Request" p2p_response
237 '
238
239 # REDIRECT: example.com/p2p/$peerid/http/index.txt → $peerid.p2p.example.com/http/index.txt
240 test_expect_success "redirect http path request to subdomain gateway" '
241 serve_content "SUBDOMAIN ROOT REDIRECTS /p2p/ PATH TO SUBDOMAIN" &&
242 curl -H "Host: example.com" -sD - $SENDER_GATEWAY/p2p/$RECEIVER_ID/http/index.txt > p2p_response &&
243 test_should_contain "Location: http://$RECEIVER_ID_CIDv1.p2p.example.com/http/index.txt" p2p_response
244 '
245
246 test_expect_success 'stop http server' '
247 teardown_remote_server
248 '
249
250 test_expect_success 'stop nodes' '
251 iptb stop
252 '
253
254 test_done