📄 nth_server.c
字号:
site->site_access = now; if (subsite && subsite->site_isdir && subpath == site_nodir_match) { /* Answer with 301 */ http_location_t loc[1]; http_location_init(loc); *loc->loc_url = *site->site_url; if (site->site_wildcard) { if (http->http_host) { loc->loc_url->url_host = http->http_host->h_host; loc->loc_url->url_port = http->http_host->h_port; } else { tp_name_t const *tpn = tport_name(tport); assert(tpn); loc->loc_url->url_host = tpn->tpn_canon; if (strcmp(url_port_default(loc->loc_url->url_type), tpn->tpn_port)) loc->loc_url->url_port = tpn->tpn_port; } } loc->loc_url->url_root = 1; loc->loc_url->url_path = subsite->site_url->url_path; msg_header_add_dup(response, NULL, (msg_header_t *)loc); server_reply(srv, tport, request, response, HTTP_301_MOVED_PERMANENTLY); } else if (subsite) nth_site_request(srv, subsite, tport, request, http, subpath, response); else if (site) nth_site_request(srv, site, tport, request, http, path, response); else /* Answer with 404 */ server_reply(srv, tport, request, response, HTTP_404_NOT_FOUND);}static void server_tport_error(server_t *srv, tport_t *tport, int errcode, char const *remote){ su_log("\nth: tport: %s%s%s\n", remote ? remote : "", remote ? ": " : "", su_strerror(errcode));}/** Respond without creating a request structure */static void server_reply(server_t *srv, tport_t *tport, msg_t *request, msg_t *response, int status, char const *phrase){ http_t *http; http_payload_t *pl; int close; http_status_t st[1]; char const *req_version = NULL; if (status < 200 || status >= 600) status = 500, phrase = http_500_internal_server; http = http_object(request); if (http && http->http_request) req_version = http->http_request->rq_version; close = status >= 200 && (!srv->srv_persistent || status == 400 || (http && http->http_request && http->http_request->rq_version != http_version_1_1) || (http && http->http_connection && msg_params_find(http->http_connection->k_items, "close"))); msg_destroy(request); http = http_object(response); pl = http_payload_format(msg_home(response), "<html>\n" "<head><title>%u %s</title></head>\n" "<body><h2>%u %s</h2></body>\n" "</html>\n", status, phrase, status, phrase); msg_header_insert(response, (msg_pub_t *)http, (msg_header_t *)pl); if (req_version != http_version_0_9) { http_status_init(st); st->st_version = http_version_1_1; st->st_status = status; st->st_phrase = phrase; http_add_tl(response, http, HTTPTAG_STATUS(st), HTTPTAG_SERVER(srv->srv_server), HTTPTAG_CONTENT_TYPE_STR("text/html"), HTTPTAG_SEPARATOR_STR("\r\n"), TAG_IF(close, HTTPTAG_CONNECTION_STR("close")), TAG_END()); msg_serialize(response, (msg_pub_t *)http); } else { /* Just send the response */ *msg_chain_head(response) = (msg_header_t *)pl; close = 1; } if (tport_tqsend(tport, response, NULL, TPTAG_CLOSE_AFTER(close), TAG_END()) == -1) { SU_DEBUG_3(("server_reply(): cannot queue response\n")); tport_shutdown(tport, 2); } msg_destroy(response);}/** Create a new message for transport */staticmsg_t *server_msg_create(server_t *srv, int flags, char const data[], usize_t dlen, tport_t const *tp, tp_client_t *tpc){ msg_t *msg = msg_create(srv->srv_mclass, srv->srv_mflags | flags); return msg;}/* ---------------------------------------------------------------------- * 6) Server transactions */struct auth_info{ nth_site_t *site; nth_request_t *req; http_t const *http; char const *path;};static void nth_authentication_result(void *ai0, auth_status_t *as);staticvoid nth_site_request(server_t *srv, nth_site_t *site, tport_t *tport, msg_t *request, http_t *http, char const *path, msg_t *response){ auth_mod_t *am = site->site_auth; nth_request_t *req; auth_status_t *as; struct auth_info *ai; size_t size = (am ? (sizeof *as) + (sizeof *ai) : 0) + (sizeof *req); int status; req = su_zalloc(srv->srv_home, size); if (req == NULL) { server_reply(srv, tport, request, response, HTTP_500_INTERNAL_SERVER); return; } if (am) as = auth_status_init(req + 1, sizeof *as), ai = (void *)(as + 1); else as = NULL, ai = NULL; req->req_server = srv; req->req_method = http->http_request->rq_method; req->req_method_name = http->http_request->rq_method_name; req->req_url = http->http_request->rq_url; req->req_version = http->http_request->rq_version; req->req_tport = tport_incref(tport); req->req_request = request; req->req_response = response; req->req_status = 100; req->req_close = !srv->srv_persistent || http->http_request->rq_version != http_version_1_1 || (http->http_connection && msg_params_find(http->http_connection->k_items, "close")); if (am) { static auth_challenger_t const http_server_challenger[] = {{ HTTP_401_UNAUTHORIZED, http_www_authenticate_class }}; req->req_as = as; as->as_method = http->http_request->rq_method_name; as->as_uri = path; if (http->http_payload) { as->as_body = http->http_payload->pl_data; as->as_bodylen = http->http_payload->pl_len; } auth_mod_check_client(am, as, http->http_authorization, http_server_challenger); if (as->as_status == 100) { /* Stall transport - do not read more requests */ if (tport_queuelen(tport) * 2 >= srv->srv_queuesize) tport_stall(tport); as->as_callback = nth_authentication_result; as->as_magic = ai; ai->site = site; ai->req = req; ai->http = http; ai->path = path; return; } else if (as->as_status) { assert(as->as_status >= 200); nth_request_treply(req, as->as_status, as->as_phrase, HTTPTAG_HEADER((http_header_t *)as->as_response), HTTPTAG_HEADER((http_header_t *)as->as_info), TAG_END()); nth_request_destroy(req); return; } } req->req_in_callback = 1; status = site->site_callback(site->site_magic, site, req, http, path); req->req_in_callback = 0; if (status != 0 && (status < 100 || status >= 600)) status = 500; if (status != 0 && req->req_status < 200) { nth_request_treply(req, status, NULL, TAG_END()); } if (req->req_status < 100) { /* Stall transport - do not read more requests */ if (tport_queuelen(tport) * 2 >= srv->srv_queuesize) tport_stall(tport); } if (status >= 200 || req->req_destroyed) nth_request_destroy(req);}static void nth_authentication_result(void *ai0, auth_status_t *as){ struct auth_info *ai = ai0; nth_request_t *req = ai->req; int status; if (as->as_status != 0) { assert(as->as_status >= 300); nth_request_treply(req, status = as->as_status, as->as_phrase, HTTPTAG_HEADER((http_header_t *)as->as_response), TAG_END()); } else { req->req_in_callback = 1; status = ai->site->site_callback(ai->site->site_magic, ai->site, ai->req, ai->http, ai->path); req->req_in_callback = 0; if (status != 0 && (status < 100 || status >= 600)) status = 500; if (status != 0 && req->req_status < 200) { nth_request_treply(req, status, NULL, TAG_END()); } } if (status >= 200 || req->req_destroyed) nth_request_destroy(req);}void nth_request_destroy(nth_request_t *req){ if (req == NULL) return; if (req->req_status < 200) nth_request_treply(req, HTTP_500_INTERNAL_SERVER, TAG_END()); req->req_destroyed = 1; if (req->req_in_callback) return; if (req->req_as) su_home_deinit(req->req_as->as_home); tport_decref(&req->req_tport), req->req_tport = NULL; msg_destroy(req->req_request), req->req_request = NULL; msg_destroy(req->req_response), req->req_response = NULL; su_free(req->req_server->srv_home, req);}/** Return request authentication status. * * @param req pointer to HTTP request object * * @retval Status code * * @since New in @VERSION_1_12_4 */int nth_request_status(nth_request_t const *req){ return req ? req->req_status : 400;}/** Return request authentication status. * * @param req pointer to HTTP request object * * @retval Pointer to authentication status struct * * @note The authentication status struct is freed when the #nth_request_t * object is destroyed. * * @since New in @VERSION_1_12_4 * * @sa AUTH */auth_status_t *nth_request_auth(nth_request_t const *req){ return req ? req->req_as : NULL;}http_method_t nth_request_method(nth_request_t const *req){ return req ? req->req_method : http_method_invalid;}msg_t *nth_request_message(nth_request_t *req){ msg_t *retval = NULL; if (req) retval = msg_ref_create(req->req_request); return retval;}int nth_request_treply(nth_request_t *req, int status, char const *phrase, tag_type_t tag, tag_value_t value, ...){ msg_t *response, *next = NULL; http_t *http; int retval = -1; int req_close, close; ta_list ta; http_header_t const *as_info = NULL; if (req == NULL || status < 100 || status >= 600) { return -1; } response = req->req_response; http = http_object(response); if (status >= 200 && req->req_as) as_info = (http_header_t const *)req->req_as->as_info; ta_start(ta, tag, value); http_add_tl(response, http, HTTPTAG_SERVER(req->req_server->srv_server), HTTPTAG_HEADER(as_info), ta_tags(ta)); if (http->http_payload && !http->http_content_length) { http_content_length_t *l; http_payload_t *pl; size_t len = 0; for (pl = http->http_payload; pl; pl = pl->pl_next) len += pl->pl_len; if (len > UINT32_MAX) goto fail; l = http_content_length_create(msg_home(response), (uint32_t)len); msg_header_insert(response, (msg_pub_t *)http, (msg_header_t *)l); } if (req->req_method == http_method_head && http->http_payload) { http_payload_t *pl; for (pl = http->http_payload; pl; pl = pl->pl_next) msg_header_remove(response, (msg_pub_t *)http, (msg_header_t *)pl); } http_complete_response(response, status, phrase, http_object(req->req_request)); if (!http->http_date) { http_date_t date[1]; http_date_init(date)->d_time = msg_now(); msg_header_add_dup(response, (msg_pub_t *)http, (msg_header_t*)date); } if (status < 200) { close = 0; next = server_msg_create(req->req_server, 0, NULL, 0, NULL, NULL); } else { req_close = req->req_close; close = (http->http_connection && msg_params_find(http->http_connection->k_items, "close")); if (req_close && !close && status >= 200) { close = 1; http_add_tl(response, http, HTTPTAG_CONNECTION_STR("close"), TAG_END()); } } msg_serialize(response, (msg_pub_t *)http); retval = tport_tqsend(req->req_tport, response, next, TAG_IF(close, TPTAG_CLOSE_AFTER(1)), ta_tags(ta)); fail: ta_end(ta); if (retval == 0) req->req_status = status; return retval;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -