| 32 #include <arpa/inet.h> |
32 #include <arpa/inet.h> |
| 33 #include <ctype.h> |
33 #include <ctype.h> |
| 34 #include <string.h> |
34 #include <string.h> |
| 35 |
35 |
| 36 #include "../util/pblock.h" |
36 #include "../util/pblock.h" |
| |
37 #include "../util/util.h" |
| 37 #include "../proxy/httpclient.h" |
38 #include "../proxy/httpclient.h" |
| 38 |
39 |
| 39 // Gets the uri part from an http request line |
|
| 40 static cxstring get_uri_from_clfreq(const char *clfreq) { |
|
| 41 cxstring uri = { NULL, 0 }; |
|
| 42 |
|
| 43 const char *begin = NULL; |
|
| 44 const char *str = clfreq; |
|
| 45 for(;*str != '\0';str++) { |
|
| 46 if(*str < 33) { |
|
| 47 if(begin) { |
|
| 48 str++; |
|
| 49 break; |
|
| 50 } |
|
| 51 } else { |
|
| 52 if(!begin) { |
|
| 53 begin = str; |
|
| 54 } |
|
| 55 } |
|
| 56 } |
|
| 57 |
|
| 58 begin = NULL; |
|
| 59 for(;*str != '\0';str++) { |
|
| 60 if(*str > 32) { |
|
| 61 if(!begin) { |
|
| 62 begin = str; |
|
| 63 } |
|
| 64 } else { |
|
| 65 if(begin) { |
|
| 66 break; |
|
| 67 } |
|
| 68 } |
|
| 69 } |
|
| 70 |
|
| 71 if(begin && *str != '\0') { |
|
| 72 return cx_strn(begin, str-begin); |
|
| 73 } |
|
| 74 |
|
| 75 return uri; |
|
| 76 |
|
| 77 } |
|
| 78 |
40 |
| 79 typedef struct ProxyRequest { |
41 typedef struct ProxyRequest { |
| 80 Session *sn; |
42 Session *sn; |
| 81 Request *rq; |
43 Request *rq; |
| 82 |
44 |
| 175 } |
137 } |
| 176 |
138 |
| 177 int http_reverse_proxy_service(pblock *param, Session *sn, Request *rq) { |
139 int http_reverse_proxy_service(pblock *param, Session *sn, Request *rq) { |
| 178 EventHandler *ev = sn->ev; |
140 EventHandler *ev = sn->ev; |
| 179 const char *method = pblock_findkeyval(pb_key_method, rq->reqpb); |
141 const char *method = pblock_findkeyval(pb_key_method, rq->reqpb); |
| 180 const char *clfreq = pblock_findkeyval(pb_key_clf_request, rq->reqpb); |
142 const char *uri = pblock_findkeyval(pb_key_uri, rq->reqpb); |
| 181 |
143 const char *query = pblock_findkeyval(pb_key_query, rq->reqpb); |
| 182 cxstring uri = get_uri_from_clfreq(clfreq); |
144 |
| 183 if(uri.length == 0) { |
145 cxmutstr new_uri = CX_NULLSTR; |
| 184 return REQ_ABORTED; |
146 size_t uri_len = strlen(uri); |
| |
147 size_t query_len = query ? strlen(query) : 0; |
| |
148 size_t new_uri_alloc = ((uri_len + query_len) * 3) + 2; |
| |
149 new_uri.ptr = pool_malloc(sn->pool, new_uri_alloc); |
| |
150 new_uri.length = util_uri_escape_s(new_uri.ptr, new_uri_alloc, uri); |
| |
151 if(new_uri.length > 0 && query_len > 0) { |
| |
152 new_uri.ptr[new_uri.length] = '?'; |
| |
153 memcpy(new_uri.ptr + new_uri.length + 1, query, query_len + 1); |
| |
154 new_uri.length = new_uri.length + 1 + query_len; |
| 185 } |
155 } |
| 186 |
156 |
| 187 // remove some response headers, that were previously set by ObjectType |
157 // remove some response headers, that were previously set by ObjectType |
| 188 // or other SAFs |
158 // or other SAFs |
| 189 pblock_removekey(pb_key_content_type, rq->srvhdrs); |
159 pblock_removekey(pb_key_content_type, rq->srvhdrs); |
| 213 if(http_client_set_method(client, method)) { |
183 if(http_client_set_method(client, method)) { |
| 214 http_client_free(client); |
184 http_client_free(client); |
| 215 return REQ_ABORTED; |
185 return REQ_ABORTED; |
| 216 } |
186 } |
| 217 |
187 |
| 218 if(http_client_set_uri_len(client, uri.ptr, uri.length)) { |
188 if(http_client_set_uri_len(client, new_uri.ptr, new_uri.length)) { |
| 219 http_client_free(client); |
189 http_client_free(client); |
| 220 return REQ_ABORTED; |
190 return REQ_ABORTED; |
| 221 } |
191 } |
| 222 |
192 |
| 223 // test address |
193 // test address |
| 291 } |
261 } |
| 292 |
262 |
| 293 return REQ_PROCESSING; |
263 return REQ_PROCESSING; |
| 294 } |
264 } |
| 295 |
265 |
| 296 |
|
| 297 |
|
| 298 /* --------------------------------- Tests --------------------------------- */ |
|
| 299 |
|
| 300 static CX_TEST(test_safs_proxy_get_uri_from_clfreq) { |
|
| 301 CX_TEST_DO { |
|
| 302 cxstring ret; |
|
| 303 |
|
| 304 ret = get_uri_from_clfreq("GET /uri HTTP/1.1"); |
|
| 305 CX_TEST_ASSERT(!cx_strcmp(ret, "/uri")); |
|
| 306 ret = get_uri_from_clfreq("G / HTTP/1.1"); |
|
| 307 CX_TEST_ASSERT(!cx_strcmp(ret, "/")); |
|
| 308 ret = get_uri_from_clfreq("POST /test%20/path HTTP/1.1"); |
|
| 309 CX_TEST_ASSERT(!cx_strcmp(ret, "/test%20/path")); |
|
| 310 ret = get_uri_from_clfreq(" GET /leading_space HTTP/1.1"); |
|
| 311 CX_TEST_ASSERT(!cx_strcmp(ret, "/leading_space")); |
|
| 312 ret = get_uri_from_clfreq(" PROPFIND /space2 HTTP/1.1"); |
|
| 313 CX_TEST_ASSERT(!cx_strcmp(ret, "/space2")); |
|
| 314 ret = get_uri_from_clfreq("HEAD /trailing_space HTTP/1.1"); |
|
| 315 CX_TEST_ASSERT(!cx_strcmp(ret, "/trailing_space")); |
|
| 316 ret = get_uri_from_clfreq(" GET /space3 HTTP/1.1 "); |
|
| 317 CX_TEST_ASSERT(!cx_strcmp(ret, "/space3")); |
|
| 318 |
|
| 319 // fail test |
|
| 320 ret = get_uri_from_clfreq(""); |
|
| 321 CX_TEST_ASSERT(ret.ptr == NULL); |
|
| 322 ret = get_uri_from_clfreq(" "); |
|
| 323 CX_TEST_ASSERT(ret.ptr == NULL); |
|
| 324 ret = get_uri_from_clfreq("GET"); |
|
| 325 CX_TEST_ASSERT(ret.ptr == NULL); |
|
| 326 ret = get_uri_from_clfreq("GET /path"); |
|
| 327 CX_TEST_ASSERT(ret.ptr == NULL); |
|
| 328 ret = get_uri_from_clfreq(" /path2/ "); |
|
| 329 CX_TEST_ASSERT(ret.ptr == NULL); |
|
| 330 } |
|
| 331 } |
|
| 332 |
|
| 333 void http_reverse_proxy_add_tests(CxTestSuite *suite) { |
|
| 334 cx_test_register(suite, test_safs_proxy_get_uri_from_clfreq); |
|
| 335 } |
|