src/server/daemon/httprequest.c

changeset 415
d938228c382e
parent 411
bbd82eee568e
child 448
02b003f7560c
equal deleted inserted replaced
414:99a34860c105 415:d938228c382e
62 void http_request_cleanup(HTTPRequest *req) { 62 void http_request_cleanup(HTTPRequest *req) {
63 header_array_free(req->headers); 63 header_array_free(req->headers);
64 free(req); 64 free(req);
65 } 65 }
66 66
67 sstr_t http_request_get_abspath(HTTPRequest *req) { 67 cxmutstr http_request_get_abspath(HTTPRequest *req) {
68 sstr_t uri = req->uri; 68 cxmutstr uri = req->uri;
69 69
70 int i = 0; 70 int i = 0;
71 if(uri.ptr[0] == '/') { 71 if(uri.ptr[0] == '/') {
72 return uri; 72 return uri;
73 } else if(sstrprefix(uri, S("http://"))) { 73 } else if(cx_strprefix(cx_strcast(uri), (cxstring)CX_STR("http://"))) {
74 i = 7; 74 i = 7;
75 } else if(sstrprefix(uri, S("https://"))) { 75 } else if(cx_strprefix(cx_strcast(uri), (cxstring)CX_STR("https://"))) {
76 i = 8; 76 i = 8;
77 } else if(!sstrcmp(uri, S("*"))) { 77 } else if(!cx_strcmp(cx_strcast(uri), (cxstring)CX_STR("*"))) {
78 return uri; 78 return uri;
79 } 79 }
80 80
81 for(;i<uri.length;i++) { 81 for(;i<uri.length;i++) {
82 if(uri.ptr[i] == '/') { 82 if(uri.ptr[i] == '/') {
83 return sstrsubs(uri, i); 83 return cx_strsubs_m(uri, i);
84 } 84 }
85 } 85 }
86 86
87 return S("/"); 87 return (cxmutstr){ "/", 1 };
88 } 88 }
89 89
90 NSAPISession* nsapisession_create(pool_handle_t *pool) { 90 NSAPISession* nsapisession_create(pool_handle_t *pool) {
91 NSAPISession *sn = pool_malloc(pool, sizeof(NSAPISession)); 91 NSAPISession *sn = pool_malloc(pool, sizeof(NSAPISession));
92 if(!sn) { 92 if(!sn) {
94 } 94 }
95 95
96 ZERO(sn, sizeof(NSAPISession)); 96 ZERO(sn, sizeof(NSAPISession));
97 97
98 sn->sn.pool = pool; 98 sn->sn.pool = pool;
99 sn->allocator = util_pool_allocator(pool);
100 99
101 sn->sn.client = pblock_create_pool(sn->sn.pool, 8); 100 sn->sn.client = pblock_create_pool(sn->sn.pool, 8);
102 if(!sn->sn.client) { 101 if(!sn->sn.client) {
103 pool_free(pool, sn); 102 pool_free(pool, sn);
104 return NULL; 103 return NULL;
196 // set default virtual server 195 // set default virtual server
197 rq->vs = request->connection->listener->default_vs.vs; 196 rq->vs = request->connection->listener->default_vs.vs;
198 197
199 // Pass request line as "clf-request" 198 // Pass request line as "clf-request"
200 // remove \r\n 199 // remove \r\n
201 sstr_t clfreq = request->request_line; 200 cxmutstr clfreq = request->request_line;
202 while(clfreq.length > 0 && clfreq.ptr[clfreq.length - 1] < 33) { 201 while(clfreq.length > 0 && clfreq.ptr[clfreq.length - 1] < 33) {
203 clfreq.length--; 202 clfreq.length--;
204 } 203 }
205 pblock_kvinsert( 204 pblock_kvinsert(
206 pb_key_clf_request, 205 pb_key_clf_request,
223 pb_key_protocol, 222 pb_key_protocol,
224 request->httpv.ptr, 223 request->httpv.ptr,
225 request->httpv.length, 224 request->httpv.length,
226 rq->rq.reqpb); 225 rq->rq.reqpb);
227 226
228 if(!sstrcmp(request->httpv, S("HTTP/1.1"))) { 227 if(!cx_strcmp(cx_strcast(request->httpv), (cxstring)CX_STR("HTTP/1.1"))) {
229 rq->rq.protv_num = PROTOCOL_VERSION_HTTP11; 228 rq->rq.protv_num = PROTOCOL_VERSION_HTTP11;
230 } else if(!sstrcmp(request->httpv, S("HTTP/1.0"))) { 229 } else if(!cx_strcmp(cx_strcast(request->httpv), (cxstring)CX_STR("HTTP/1.0"))) {
231 rq->rq.protv_num = PROTOCOL_VERSION_HTTP10; 230 rq->rq.protv_num = PROTOCOL_VERSION_HTTP10;
232 } else { 231 } else {
233 // invalid protocol version - abort 232 // invalid protocol version - abort
234 log_ereport( 233 log_ereport(
235 LOG_FAILURE, 234 LOG_FAILURE,
242 241
243 /* 242 /*
244 * get absolute path and query of the request uri 243 * get absolute path and query of the request uri
245 */ 244 */
246 // TODO: check for '#' #72 245 // TODO: check for '#' #72
247 sstr_t absPath = http_request_get_abspath(request); 246 cxmutstr absPath = http_request_get_abspath(request);
248 if(!absPath.ptr) { 247 if(!absPath.ptr) {
249 // TODO: error msg 248 // TODO: error msg
250 return 1; 249 return 1;
251 } else if(absPath.ptr[0] == '*') { 250 } else if(absPath.ptr[0] == '*') {
252 // TODO: implement global OPTIONS #71 251 // TODO: implement global OPTIONS #71
253 return 1; 252 return 1;
254 } 253 }
255 254
256 sstr_t query; 255 cxmutstr query;
257 query.length = 0; 256 query.length = 0;
258 257
259 for(int i=0;i<request->uri.length;i++) { 258 for(int i=0;i<request->uri.length;i++) {
260 if(request->uri.ptr[i] == '?') { 259 if(request->uri.ptr[i] == '?') {
261 /* split uri in path and query */ 260 /* split uri in path and query */
275 break; 274 break;
276 } 275 }
277 } 276 }
278 277
279 // Get abs_path part of request URI, and canonicalize the path 278 // Get abs_path part of request URI, and canonicalize the path
280 sstr_t orig_path = absPath; 279 cxmutstr orig_path = absPath;
281 absPath.ptr = util_canonicalize_uri( 280 absPath.ptr = util_canonicalize_uri(
282 pool, 281 pool,
283 absPath.ptr, 282 absPath.ptr,
284 absPath.length, 283 absPath.length,
285 (int*)&absPath.length); 284 (int*)&absPath.length);
369 rq->host = NULL; // TODO: value from listener 368 rq->host = NULL; // TODO: value from listener
370 } 369 }
371 rq->port = request->connection->listener->port; 370 rq->port = request->connection->listener->port;
372 371
373 if(rq->host) { 372 if(rq->host) {
374 VirtualServer *vs = ucx_map_cstr_get(sn->config->host_vs, rq->host); 373 VirtualServer *vs = cxMapGet(sn->config->host_vs, cx_hash_key_str(rq->host));
375 if(vs) { 374 if(vs) {
376 rq->vs = vs; 375 rq->vs = vs;
377 } else { 376 } else {
378 log_ereport( 377 log_ereport(
379 LOG_VERBOSE, 378 LOG_VERBOSE,
452 return 0; 451 return 0;
453 } 452 }
454 453
455 454
456 455
457 void header_add(HeaderArray *hd, sstr_t name, sstr_t value) { 456 void header_add(HeaderArray *hd, cxmutstr name, cxmutstr value) {
458 while(hd->len >= hd->alloc) { 457 while(hd->len >= hd->alloc) {
459 if(hd->next == NULL) { 458 if(hd->next == NULL) {
460 HeaderArray *block = malloc(sizeof(HeaderArray)); 459 HeaderArray *block = malloc(sizeof(HeaderArray));
461 block->next = NULL; 460 block->next = NULL;
462 block->len = 0; 461 block->len = 0;
646 } 645 }
647 646
648 void request_free_resources(NSAPISession *sn, NSAPIRequest *rq) { 647 void request_free_resources(NSAPISession *sn, NSAPIRequest *rq) {
649 if(!rq->resources) return; 648 if(!rq->resources) return;
650 649
651 UcxMapIterator i = ucx_map_iterator(rq->resources); 650 CxIterator i = cxMapIteratorValues(rq->resources);
652 ResourceData *resource; 651 cx_foreach(ResourceData *, resource, i) {
653 UCX_MAP_FOREACH(key, resource, i) {
654 resourcepool_free(&sn->sn, &rq->rq, resource); 652 resourcepool_free(&sn->sn, &rq->rq, resource);
655 } 653 }
656 } 654 }
657 655
658 int nsapi_authtrans(NSAPISession *sn, NSAPIRequest *rq) { 656 int nsapi_authtrans(NSAPISession *sn, NSAPIRequest *rq) {
735 } 733 }
736 } 734 }
737 735
738 // if no function has set the ppath var, translate it to docroot 736 // if no function has set the ppath var, translate it to docroot
739 if(ret == REQ_NOACTION && ppath == NULL) { 737 if(ret == REQ_NOACTION && ppath == NULL) {
740 sstr_t docroot = rq->vs->document_root; 738 cxmutstr docroot = rq->vs->document_root;
741 if(docroot.length < 1) { 739 if(docroot.length < 1) {
742 log_ereport( 740 log_ereport(
743 LOG_WARN, 741 LOG_WARN,
744 "VirtualServer(%.*s) docroot too short", 742 "VirtualServer(%.*s) docroot too short",
745 (int)rq->vs->name.length, 743 (int)rq->vs->name.length,
751 /* 749 /*
752 if(docroot.ptr[docroot.length - 1] == '/') { 750 if(docroot.ptr[docroot.length - 1] == '/') {
753 docroot.length--; 751 docroot.length--;
754 } 752 }
755 753
756 sstr_t uri = sstr(pblock_findkeyval(pb_key_uri, rq->rq.reqpb)); 754 cxmutstr uri = cx_str(pblock_findkeyval(pb_key_uri, rq->rq.reqpb));
757 755
758 sstr_t translated; 756 cxmutstr translated;
759 translated.length = docroot.length + uri.length; 757 translated.length = docroot.length + uri.length;
760 translated.ptr = alloca(translated.length + 1); 758 translated.ptr = alloca(translated.length + 1);
761 translated = sstrncat(translated, 2, docroot, uri); 759 translated = cx_strncat(translated, 2, docroot, uri);
762 760
763 pblock_kvinsert( 761 pblock_kvinsert(
764 pb_key_ppath, 762 pb_key_ppath,
765 translated.ptr, 763 translated.ptr,
766 translated.length, 764 translated.length,
767 rq->rq.vars); 765 rq->rq.vars);
768 */ 766 */
769 sstr_t uri = sstr(pblock_findkeyval(pb_key_uri, rq->rq.reqpb)); 767 cxstring uri = cx_str(pblock_findkeyval(pb_key_uri, rq->rq.reqpb));
770 request_set_path(docroot, uri, rq->rq.vars); 768 request_set_path(cx_strcast(docroot), uri, rq->rq.vars);
771 } 769 }
772 770
773 // TODO: remove ppath 771 // TODO: remove ppath
774 char *pp = pblock_findkeyval(pb_key_ppath, rq->rq.vars); 772 char *pp = pblock_findkeyval(pb_key_ppath, rq->rq.vars);
775 pblock_kvinsert(pb_key_path, pp, strlen(pp), rq->rq.vars); 773 pblock_kvinsert(pb_key_path, pp, strlen(pp), rq->rq.vars);
866 * No function returned with REQ_PROCEED, but we need a content type. 864 * No function returned with REQ_PROCEED, but we need a content type.
867 * If the path ends with a '/', we set the content type to 865 * If the path ends with a '/', we set the content type to
868 * 'internal/directory' so that 'index-common' can serve the content. 866 * 'internal/directory' so that 'index-common' can serve the content.
869 * Otherwise we set the content type to text/plain 867 * Otherwise we set the content type to text/plain
870 */ 868 */
871 sstr_t path = sstr(pblock_findkeyval(pb_key_ppath, rq->rq.vars)); 869 cxstring path = cx_str(pblock_findkeyval(pb_key_ppath, rq->rq.vars));
872 sstr_t ct; 870 cxstring ct;
873 if(path.ptr[path.length - 1] == '/') { 871 if(path.ptr[path.length - 1] == '/') {
874 // directory 872 // directory
875 ct = sstrn("internal/directory", 18); 873 ct = (cxstring)CX_STR("internal/directory");
876 } else { 874 } else {
877 ct = sstrn("text/plain", 10); 875 ct = (cxstring)CX_STR("text/plain");
878 } 876 }
879 pblock_kvinsert(pb_key_content_type, ct.ptr, ct.length, rq->rq.srvhdrs); 877 pblock_kvinsert(pb_key_content_type, ct.ptr, ct.length, rq->rq.srvhdrs);
880 878
881 return REQ_PROCEED; 879 return REQ_PROCEED;
882 } 880 }
909 content_type = pblock_findkeyval( 907 content_type = pblock_findkeyval(
910 pb_key_content_type, 908 pb_key_content_type,
911 rq->rq.srvhdrs); 909 rq->rq.srvhdrs);
912 } 910 }
913 // compare types 911 // compare types
914 if(!contenttype_match(sstr(dtp), sstr(content_type))) { 912 if(!contenttype_match(cx_str(dtp), cx_str(content_type))) {
915 continue; 913 continue;
916 } 914 }
917 } 915 }
918 916
919 // check method parameter 917 // check method parameter
1077 } 1075 }
1078 } 1076 }
1079 1077
1080 char *poolname = pblock_findkeyval(pb_key_pool, d->param); 1078 char *poolname = pblock_findkeyval(pb_key_pool, d->param);
1081 if(poolname) { 1079 if(poolname) {
1082 threadpool_t *pool = get_threadpool(sstr(poolname)); 1080 threadpool_t *pool = get_threadpool(cx_str(poolname));
1083 if(pool && pool != sn->currentpool) { 1081 if(pool && pool != sn->currentpool) {
1084 // execute directive in different thread pool 1082 // execute directive in different thread pool
1085 return nsapi_exec_tp(d, sn, rq, pool); 1083 return nsapi_exec_tp(d, sn, rq, pool);
1086 } 1084 }
1087 } else if(sn->currentpool != sn->defaultpool) { 1085 } else if(sn->currentpool != sn->defaultpool) {
1210 * checks if the content type matches the cmp string 1208 * checks if the content type matches the cmp string
1211 * the format of cmp is a single string with wildcards or a list 1209 * the format of cmp is a single string with wildcards or a list
1212 * of types (also with wildcard support) 1210 * of types (also with wildcard support)
1213 * (type1|type2*) 1211 * (type1|type2*)
1214 */ 1212 */
1215 int contenttype_match(sstr_t cmp, sstr_t ctype) { 1213 int contenttype_match(cxstring cmp, cxstring ctype) {
1216 if(cmp.ptr[0] != '(') { 1214 if(cmp.ptr[0] != '(') {
1217 if(cmp.ptr[0] == '*') { 1215 if(cmp.ptr[0] == '*') {
1218 cmp.ptr++; 1216 cmp.ptr++;
1219 cmp.length--; 1217 cmp.length--;
1220 return sstrsuffix(ctype, cmp); 1218 return cx_strsuffix(ctype, cmp);
1221 } else if(cmp.ptr[cmp.length-1] == '*') { 1219 } else if(cmp.ptr[cmp.length-1] == '*') {
1222 cmp.length--; 1220 cmp.length--;
1223 return sstrprefix(ctype, cmp); 1221 return cx_strprefix(ctype, cmp);
1224 } else { 1222 } else {
1225 return !sstrcmp(cmp, ctype); 1223 return !cx_strcmp(cmp, ctype);
1226 } 1224 }
1227 } else if(cmp.ptr[0] == 0) { 1225 } else if(cmp.ptr[0] == 0) {
1228 log_ereport(LOG_WARN, "Skipped service saf with empty type parameter"); 1226 log_ereport(LOG_WARN, "Skipped service saf with empty type parameter");
1229 return 0; 1227 return 0;
1230 } 1228 }
1231 1229
1232 cmp = sstrsubsl(cmp, 1, cmp.length - 2); 1230 cmp = cx_strsubsl(cmp, 1, cmp.length - 2);
1233 1231
1234 int begin = 0; 1232 int begin = 0;
1235 for(int i=0;i<cmp.length;i++) { 1233 for(int i=0;i<cmp.length;i++) {
1236 if(cmp.ptr[i] == '|') { 1234 if(cmp.ptr[i] == '|') {
1237 if(contenttype_match(sstrsubsl(cmp, begin, i-begin), ctype)) { 1235 if(contenttype_match(cx_strsubsl(cmp, begin, i-begin), ctype)) {
1238 return 1; 1236 return 1;
1239 } 1237 }
1240 begin = i + 1; 1238 begin = i + 1;
1241 } 1239 }
1242 } 1240 }
1243 return contenttype_match(sstrsubs(cmp, begin), ctype); 1241 return contenttype_match(cx_strsubs(cmp, begin), ctype);
1244 } 1242 }
1245 1243
1246 /* 1244 /*
1247 * adds objects with specific name or path to the httpd_objset 1245 * adds objects with specific name or path to the httpd_objset
1248 */ 1246 */

mercurial