src/server/daemon/httprequest.c

changeset 385
a1f4cb076d2f
parent 361
570026d3a685
child 396
77d81f2bb9f7
equal deleted inserted replaced
210:21274e5950af 385:a1f4cb076d2f
85 } 85 }
86 86
87 return S("/"); 87 return S("/");
88 } 88 }
89 89
90 NSAPISession* nsapisession_create(pool_handle_t *pool) {
91 NSAPISession *sn = pool_malloc(pool, sizeof(NSAPISession));
92 if(!sn) {
93 return NULL;
94 }
95
96 ZERO(sn, sizeof(NSAPISession));
97
98 sn->sn.pool = pool;
99 sn->allocator = util_pool_allocator(pool);
100
101 sn->sn.client = pblock_create_pool(sn->sn.pool, 8);
102 if(!sn->sn.client) {
103 pool_free(pool, sn);
104 return NULL;
105 }
106 sn->sn.fill = 1;
107
108 return sn;
109 }
110
111 int nsapisession_setconnection(NSAPISession *sn, Connection *conn, netbuf *inbuf, IOStream **io) {
112 SessionHandler *sh = conn->session_handler;
113 WSBool ssl;
114 IOStream *sio = sh->create_iostream(sh, conn, sn->sn.pool, &ssl);
115 if(!sio) {
116 return 1;
117 }
118 *io = sio;
119 IOStream *http = httpstream_new(sn->sn.pool, sio);
120 if(!http) {
121 return 1;
122 }
123 sn->connection = conn;
124 sn->netbuf = inbuf;
125 sn->sn.csd = http;
126 sn->sn.ssl = ssl;
127 sn->sn.inbuf = inbuf;
128 sn->sn.inbuf->sd = http;
129 return 0;
130 }
131
90 int handle_request(HTTPRequest *request, threadpool_t *thrpool, EventHandler *ev) { 132 int handle_request(HTTPRequest *request, threadpool_t *thrpool, EventHandler *ev) {
91 // handle nsapi request 133 // handle nsapi request
92 134
93 // create pool 135 // create pool
94 pool_handle_t *pool = pool_create(); 136 pool_handle_t *pool = pool_create();
95 137
96 // create nsapi data structures 138 // create nsapi data structures
97 NSAPISession *sn = pool_malloc(pool, sizeof(NSAPISession)); 139 NSAPISession *sn = nsapisession_create(pool);
98 if(sn == NULL) { 140 if(sn == NULL) {
99 /* TODO: error */ 141 /* TODO: error */
100 } 142 }
101 ZERO(sn, sizeof(NSAPISession)); 143
102 NSAPIRequest *rq = pool_malloc(pool, sizeof(NSAPIRequest)); 144 NSAPIRequest *rq = pool_malloc(pool, sizeof(NSAPIRequest));
103 if(rq == NULL) { 145 if(rq == NULL) {
104 /* TODO: error */ 146 /* TODO: error */
105 } 147 }
106 ZERO(rq, sizeof(NSAPIRequest)); 148 ZERO(rq, sizeof(NSAPIRequest));
107 rq->rq.req_start = request->req_start; 149 rq->rq.req_start = request->req_start;
108 rq->phase = NSAPIAuthTrans; 150 rq->phase = NSAPIAuthTrans;
109 151
110 // fill session structure 152 // fill session structure
111 sn->connection = request->connection; 153 IOStream *io = NULL;
112 sn->netbuf = request->netbuf; 154 if(nsapisession_setconnection(sn, request->connection, request->netbuf, &io)) {
113 sn->sn.pool = pool; 155 // TODO: error
114 SessionHandler *sh = request->connection->session_handler; 156 }
115 WSBool ssl;
116 IOStream *io = sh->create_iostream(sh, request->connection, pool, &ssl);
117 sn->sn.csd = httpstream_new(pool, io);
118 sn->sn.ssl = ssl;
119
120 sn->sn.client = pblock_create_pool(sn->sn.pool, 8);
121 sn->sn.next = NULL;
122 sn->sn.fill = 1;
123 sn->sn.subject = NULL;
124 157
125 if(!ev) { 158 if(!ev) {
126 ev = ev_instance(get_default_event_handler()); 159 ev = ev_instance(get_default_event_handler());
127 } 160 }
128 sn->sn.ev = ev; 161 sn->sn.ev = ev;
129 162
130 // the session needs the current server configuration 163 // the session needs the current server configuration
131 sn->config = request->connection->listener->cfg; 164 sn->config = request->connection->listener->cfg;
132 165
133 // add ip to sn->client pblock 166 // add ip to sn->client pblock
134 char ip_str[INET_ADDRSTRLEN]; 167 char ip_str[INET_ADDRSTRLEN];
196 } 229 }
197 230
198 /* 231 /*
199 * get absolute path and query of the request uri 232 * get absolute path and query of the request uri
200 */ 233 */
201 // TODO: check for '#' 234 // TODO: check for '#' #72
202 sstr_t absPath = http_request_get_abspath(request); 235 sstr_t absPath = http_request_get_abspath(request);
203 if(!absPath.ptr) { 236 if(!absPath.ptr) {
204 // TODO: error msg 237 // TODO: error msg
205 return 1; 238 return 1;
206 } else if(absPath.ptr[0] == '*') { 239 } else if(absPath.ptr[0] == '*') {
207 // TODO: implement global OPTIONS 240 // TODO: implement global OPTIONS #71
208 return 1; 241 return 1;
209 } 242 }
210 243
211 sstr_t query; 244 sstr_t query;
212 query.length = 0; 245 query.length = 0;
340 } 373 }
341 374
342 // check for request body and prepare input buffer 375 // check for request body and prepare input buffer
343 char *ctlen_str = pblock_findkeyval(pb_key_content_length, rq->rq.headers); 376 char *ctlen_str = pblock_findkeyval(pb_key_content_length, rq->rq.headers);
344 if(ctlen_str) { 377 if(ctlen_str) {
345 int ctlen = atoi(ctlen_str); 378 int64_t ctlen;
346 379 if(util_strtoint(ctlen_str, &ctlen)) {
347 //printf("request body length: %d\n", ctlen); 380 netbuf *nb = sn->netbuf;
348 381 HttpStream *net_io = (HttpStream*)sn->sn.csd;
349 netbuf *nb = request->netbuf; 382 net_io->read_eof = WS_FALSE;
350 383
351 // create new netbuf 384 // how many bytes are already read and in the buffer
352 HttpStream *net_io = (HttpStream*)httpstream_new(pool, io); 385 int cur_input_available = nb->cursize - nb->pos;
353 net_io->max_read = ctlen; 386
354 387 if(cur_input_available >= ctlen) {
355 sn->sn.inbuf = pool_malloc(pool, sizeof(netbuf)); 388 // we have the whole request body in the buffer and
356 sn->sn.inbuf->sd = net_io; 389 // maybe even more
357 sn->sn.inbuf->pos = 0; 390 // no more read from the socket is necessary to get the body,
358 391 // therefore disable it
359 // prepare buffer 392 net_io->max_read = 0;
360 int cur_input_len = nb->cursize - nb->pos; 393 } else {
361 394 // read still required to get the complete request body
362 if(cur_input_len >= ctlen) { 395 net_io->max_read = ctlen - cur_input_available;
363 /* 396 }
364 * all data is already in the primary input buffer 397 //printf("request body length: %d\n", ctlen);
365 * just link the new netbuf to the primary buffer 398 } // else: should we abort?
366 */ 399 }
367 sn->sn.inbuf->maxsize = ctlen; 400 char *transfer_encoding = pblock_findkeyval(pb_key_transfer_encoding, rq->rq.headers);
368 sn->sn.inbuf->cursize = ctlen; 401 if(transfer_encoding) {
369 sn->sn.inbuf->inbuf = nb->inbuf + nb->pos; 402 if(!strcmp(transfer_encoding, "chunked")) {
370 } else { 403 netbuf *nb = sn->netbuf;
371 sn->sn.inbuf->maxsize = (ctlen > 2048) ? (2048) : (ctlen); 404 sn->buffer = (char*)nb->inbuf;
372 sn->sn.inbuf->inbuf = pool_malloc(pool, sn->sn.inbuf->maxsize); 405 sn->pos = nb->pos;
373 406 sn->cursize = nb->cursize;
374 if(cur_input_len > 0) { 407
375 // we have read a part of the request body -> copy to netbuf 408 if(httpstream_enable_chunked_read(sn->sn.csd, sn->buffer, nb->maxsize, &sn->cursize, &sn->pos)) {
376 memcpy(sn->sn.inbuf->inbuf, nb->inbuf+nb->pos, cur_input_len); 409 pool_destroy(pool);
377 } 410 // TODO: error 500
378 411 return 1;
379 sn->sn.inbuf->cursize = cur_input_len; 412 }
380 } 413 }
381 } else {
382 sn->sn.inbuf = NULL;
383 } 414 }
384 415
385 // 416 //
386 // Send the request to the NSAPI system 417 // Send the request to the NSAPI system
387 // 418 //
533 564
534 return r; 565 return r;
535 } 566 }
536 567
537 int nsapi_finish_request(NSAPISession *sn, NSAPIRequest *rq) { 568 int nsapi_finish_request(NSAPISession *sn, NSAPIRequest *rq) {
569 request_free_resources(sn, rq);
570
571 WSBool read_stream_eof = httpstream_eof(sn->sn.csd);
572 if(!read_stream_eof) {
573 log_ereport(LOG_WARN, "request input stream not closed");
574 // TODO: clean stream
575 rq->rq.rq_attr.keep_alive = 0; // workaround
576 }
577 if(sn->pos < sn->cursize) {
578 log_ereport(LOG_WARN, "nsapi_finish_request: TODO: remaining bytes in buffer");
579 // TODO: reuse buffer in next request
580 rq->rq.rq_attr.keep_alive = 0; // workaround
581 }
582
583 if(rq->rq.senthdrs) {
584 // flush buffer and add termination if chunked encoding
585 // is enabled
586 net_finish(sn->sn.csd);
587 } else {
588 // why was no response sent?
589 // something must have gone wrong
590 // terminate the session
591 char *clf_req = pblock_findkeyval(pb_key_clf_request, rq->rq.reqpb);
592 log_ereport(LOG_WARN, "nsapi_finish_request: no response header: request: %s", clf_req);
593 rq->rq.rq_attr.keep_alive = 0;
594 }
595
538 if(rq->rq.rq_attr.keep_alive) { 596 if(rq->rq.rq_attr.keep_alive) {
539 SessionHandler *sh = sn->connection->session_handler; 597 SessionHandler *sh = sn->connection->session_handler;
540 sh->keep_alive(sh, sn->connection); 598 sh->keep_alive(sh, sn->connection);
541 /* 599 /*
542 * keep the connection object 600 * keep the connection object
553 free(sn->netbuf); 611 free(sn->netbuf);
554 612
555 pool_destroy(sn->sn.pool); 613 pool_destroy(sn->sn.pool);
556 614
557 return 0; 615 return 0;
616 }
617
618 void request_free_resources(NSAPISession *sn, NSAPIRequest *rq) {
619 if(!rq->resources) return;
620
621 UcxMapIterator i = ucx_map_iterator(rq->resources);
622 ResourceData *resource;
623 UCX_MAP_FOREACH(key, resource, i) {
624 resourcepool_free(&sn->sn, &rq->rq, resource);
625 }
558 } 626 }
559 627
560 int nsapi_authtrans(NSAPISession *sn, NSAPIRequest *rq) { 628 int nsapi_authtrans(NSAPISession *sn, NSAPIRequest *rq) {
561 HTTPObjectConfig *objconf = rq->vs->objects; 629 HTTPObjectConfig *objconf = rq->vs->objects;
562 httpd_object *obj = objconf->objects[0]; 630 httpd_object *obj = objconf->objects[0];
833 // execute the saf 901 // execute the saf
834 ret = nsapi_exec(d, sn, rq); 902 ret = nsapi_exec(d, sn, rq);
835 } 903 }
836 904
837 if(ret != REQ_NOACTION) { 905 if(ret != REQ_NOACTION) {
838 if(ret == REQ_PROCEED) { 906 if(ret == REQ_PROCEED && !rq->rq.senthdrs) {
839 /* 907 // a service SAF must send a response
840 * flush buffer and add termination if chunked encoding 908 // senthdrs == 0 indicators something has gone
841 * is enabled 909 // wrong
842 */ 910 protocol_status(&sn->sn, &rq->rq, 500, NULL);
843 net_finish(sn->sn.csd); 911 ret = REQ_ABORTED;
844 } else if(ret == REQ_PROCESSING) { 912 } else if(ret == REQ_PROCESSING) {
845 // save nsapi context 913 // save nsapi context
846 rq->context.objset_index = i; 914 rq->context.objset_index = i;
847 915
848 // add +1 to start next round with next function 916 // add +1 to start next round with next function
873 // execute directives 941 // execute directives
874 for(int j=NCX_DI(rq);j<dt->ndir;j++) { 942 for(int j=NCX_DI(rq);j<dt->ndir;j++) {
875 if(ret == REQ_NOACTION) { 943 if(ret == REQ_NOACTION) {
876 directive *d = dt->dirs[j]; 944 directive *d = dt->dirs[j];
877 945
878 // check status code parameter 946 // check status code parameter
947 // Error SAFs can specify, for which status code they should
948 // be executed
879 char *status = pblock_findkeyval(pb_key_type, d->param); 949 char *status = pblock_findkeyval(pb_key_type, d->param);
880 if(status) { 950 if(status) {
881 int statuscode = atoi(status); 951 int64_t statuscode = -1;
882 if(statuscode != rq->rq.status_num) { 952 if(!util_strtoint(status, &statuscode)) {
953 log_ereport(
954 LOG_WARN,
955 "nsapi_error: directive '%s' ignored: invalid type parameter: integer status code expected",
956 d->func->name);
957 } else if(statuscode != rq->rq.status_num) {
883 continue; 958 continue;
884 } 959 }
885 } 960 }
886 961
887 // execute the saf 962 // execute the saf
893 // error handler 968 // error handler
894 break; 969 break;
895 } 970 }
896 if(ret != REQ_NOACTION) { 971 if(ret != REQ_NOACTION) {
897 if(ret == REQ_PROCEED) { 972 if(ret == REQ_PROCEED) {
898 /* 973 // flush buffer and add termination if chunked encoding
899 * flush buffer and add termination if chunked encoding 974 // is enabled
900 * is enabled
901 */
902 net_finish(sn->sn.csd); 975 net_finish(sn->sn.csd);
903 } else if(ret == REQ_PROCESSING) { 976 } else if(ret == REQ_PROCESSING) {
904 // save nsapi context 977 // save nsapi context
905 rq->context.objset_index = i; 978 rq->context.objset_index = i;
906 979
912 } 985 }
913 } 986 }
914 987
915 if(ret != REQ_PROCEED) { 988 if(ret != REQ_PROCEED) {
916 // default error handler 989 // default error handler
917 nsapi_error_request((Session*)sn, (Request*)rq); 990 if(!rq->rq.senthdrs) {
991 nsapi_error_request((Session*)sn, (Request*)rq);
992 }
918 } 993 }
919 994
920 return ret; 995 return ret;
921 } 996 }
922 997

mercurial