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) { |
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 */ |
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 } |
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 */ |