📄 protocol.c
字号:
tmp_field = last_field + last_len - 1; while (tmp_field > value && (*tmp_field == ' ' || *tmp_field == '\t')) { *tmp_field-- = '\0'; } apr_table_addn(r->headers_in, last_field, value); /* reset the alloc_len so that we'll allocate a new * buffer if we have to do any more folding: we can't * use the previous buffer because its contents are * now part of r->headers_in */ alloc_len = 0; } /* end if current line is not a continuation starting with tab */ } /* Found a blank line, stop. */ if (len == 0) { break; } /* Keep track of this line so that we can parse it on * the next loop iteration. (In the folded case, last_field * has been updated already.) */ if (!folded) { last_field = field; last_len = len; } } apr_table_compress(r->headers_in, APR_OVERLAP_TABLES_MERGE);}AP_DECLARE(void) ap_get_mime_headers(request_rec *r){ apr_bucket_brigade *tmp_bb; tmp_bb = apr_brigade_create(r->pool, r->connection->bucket_alloc); ap_get_mime_headers_core(r, tmp_bb); apr_brigade_destroy(tmp_bb);}request_rec *ap_read_request(conn_rec *conn){ request_rec *r; apr_pool_t *p; const char *expect; int access_status; apr_bucket_brigade *tmp_bb; apr_pool_create(&p, conn->pool); apr_pool_tag(p, "request"); r = apr_pcalloc(p, sizeof(request_rec)); r->pool = p; r->connection = conn; r->server = conn->base_server; r->user = NULL; r->ap_auth_type = NULL; r->allowed_methods = ap_make_method_list(p, 2); r->headers_in = apr_table_make(r->pool, 25); r->subprocess_env = apr_table_make(r->pool, 25); r->headers_out = apr_table_make(r->pool, 12); r->err_headers_out = apr_table_make(r->pool, 5); r->notes = apr_table_make(r->pool, 5); r->request_config = ap_create_request_config(r->pool); /* Must be set before we run create request hook */ r->proto_output_filters = conn->output_filters; r->output_filters = r->proto_output_filters; r->proto_input_filters = conn->input_filters; r->input_filters = r->proto_input_filters; ap_run_create_request(r); r->per_dir_config = r->server->lookup_defaults; r->sent_bodyct = 0; /* bytect isn't for body */ r->read_length = 0; r->read_body = REQUEST_NO_BODY; r->status = HTTP_REQUEST_TIME_OUT; /* Until we get a request */ r->the_request = NULL; tmp_bb = apr_brigade_create(r->pool, r->connection->bucket_alloc); /* Get the request... */ if (!read_request_line(r, tmp_bb)) { if (r->status == HTTP_REQUEST_URI_TOO_LARGE) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "request failed: URI too long (longer than %d)", r->server->limit_req_line); ap_send_error_response(r, 0); ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r); ap_run_log_transaction(r); apr_brigade_destroy(tmp_bb); return r; } apr_brigade_destroy(tmp_bb); return NULL; } if (!r->assbackwards) { ap_get_mime_headers_core(r, tmp_bb); if (r->status != HTTP_REQUEST_TIME_OUT) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "request failed: error reading the headers"); ap_send_error_response(r, 0); ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r); ap_run_log_transaction(r); apr_brigade_destroy(tmp_bb); return r; } } else { if (r->header_only) { /* * Client asked for headers only with HTTP/0.9, which doesn't send * headers! Have to dink things just to make sure the error message * comes through... */ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "client sent invalid HTTP/0.9 request: HEAD %s", r->uri); r->header_only = 0; r->status = HTTP_BAD_REQUEST; ap_send_error_response(r, 0); ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r); ap_run_log_transaction(r); apr_brigade_destroy(tmp_bb); return r; } } apr_brigade_destroy(tmp_bb); r->status = HTTP_OK; /* Until further notice. */ /* update what we think the virtual host is based on the headers we've * now read. may update status. */ ap_update_vhost_from_headers(r); /* we may have switched to another server */ r->per_dir_config = r->server->lookup_defaults; if ((!r->hostname && (r->proto_num >= HTTP_VERSION(1, 1))) || ((r->proto_num == HTTP_VERSION(1, 1)) && !apr_table_get(r->headers_in, "Host"))) { /* * Client sent us an HTTP/1.1 or later request without telling us the * hostname, either with a full URL or a Host: header. We therefore * need to (as per the 1.1 spec) send an error. As a special case, * HTTP/1.1 mentions twice (S9, S14.23) that a request MUST contain * a Host: header, and the server MUST respond with 400 if it doesn't. */ r->status = HTTP_BAD_REQUEST; ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "client sent HTTP/1.1 request without hostname " "(see RFC2616 section 14.23): %s", r->uri); } if (r->status != HTTP_OK) { ap_send_error_response(r, 0); ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r); ap_run_log_transaction(r); return r; } if (((expect = apr_table_get(r->headers_in, "Expect")) != NULL) && (expect[0] != '\0')) { /* * The Expect header field was added to HTTP/1.1 after RFC 2068 * as a means to signal when a 100 response is desired and, * unfortunately, to signal a poor man's mandatory extension that * the server must understand or return 417 Expectation Failed. */ if (strcasecmp(expect, "100-continue") == 0) { r->expecting_100 = 1; } else { r->status = HTTP_EXPECTATION_FAILED; ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, "client sent an unrecognized expectation value of " "Expect: %s", expect); ap_send_error_response(r, 0); ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r); ap_run_log_transaction(r); return r; } } ap_add_input_filter_handle(ap_http_input_filter_handle, NULL, r, r->connection); if ((access_status = ap_run_post_read_request(r))) { ap_die(access_status, r); ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r); ap_run_log_transaction(r); return NULL; } return r;}/* * A couple of other functions which initialize some of the fields of * a request structure, as appropriate for adjuncts of one kind or another * to a request in progress. Best here, rather than elsewhere, since * *someone* has to set the protocol-specific fields... */AP_DECLARE(void) ap_set_sub_req_protocol(request_rec *rnew, const request_rec *r){ rnew->the_request = r->the_request; /* Keep original request-line */ rnew->assbackwards = 1; /* Don't send headers from this. */ rnew->no_local_copy = 1; /* Don't try to send HTTP_NOT_MODIFIED for a * fragment. */ rnew->method = "GET"; rnew->method_number = M_GET; rnew->protocol = "INCLUDED"; rnew->status = HTTP_OK; rnew->headers_in = r->headers_in; rnew->subprocess_env = apr_table_copy(rnew->pool, r->subprocess_env); rnew->headers_out = apr_table_make(rnew->pool, 5); rnew->err_headers_out = apr_table_make(rnew->pool, 5); rnew->notes = apr_table_make(rnew->pool, 5); rnew->expecting_100 = r->expecting_100; rnew->read_length = r->read_length; rnew->read_body = REQUEST_NO_BODY; rnew->main = (request_rec *) r;}static void end_output_stream(request_rec *r){ conn_rec *c = r->connection; apr_bucket_brigade *bb; apr_bucket *b; bb = apr_brigade_create(r->pool, c->bucket_alloc); b = apr_bucket_eos_create(c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(bb, b); ap_pass_brigade(r->output_filters, bb);}AP_DECLARE(void) ap_finalize_sub_req_protocol(request_rec *sub){ /* tell the filter chain there is no more content coming */ if (!sub->eos_sent) { end_output_stream(sub); }}/* finalize_request_protocol is called at completion of sending the * response. Its sole purpose is to send the terminating protocol * information for any wrappers around the response message body * (i.e., transfer encodings). It should have been named finalize_response. */AP_DECLARE(void) ap_finalize_request_protocol(request_rec *r){ (void) ap_discard_request_body(r); /* tell the filter chain there is no more content coming */ if (!r->eos_sent) { end_output_stream(r); }}/* * Support for the Basic authentication protocol, and a bit for Digest. */AP_DECLARE(void) ap_note_auth_failure(request_rec *r){ const char *type = ap_auth_type(r); if (type) { if (!strcasecmp(type, "Basic")) ap_note_basic_auth_failure(r); else if (!strcasecmp(type, "Digest")) ap_note_digest_auth_failure(r); } else { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "need AuthType to note auth failure: %s", r->uri); }}AP_DECLARE(void) ap_note_basic_auth_failure(request_rec *r){ const char *type = ap_auth_type(r); /* if there is no AuthType configure or it is something other than * Basic, let ap_note_auth_failure() deal with it */ if (!type || strcasecmp(type, "Basic")) ap_note_auth_failure(r); else apr_table_setn(r->err_headers_out, (PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authenticate" : "WWW-Authenticate", apr_pstrcat(r->pool, "Basic realm=\"", ap_auth_name(r), "\"", NULL));}AP_DECLARE(void) ap_note_digest_auth_failure(request_rec *r){ apr_table_setn(r->err_headers_out, (PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authenticate" : "WWW-Authenticate", /* need APR_TIME_T_FMT_HEX */ apr_psprintf(r->pool, "Digest realm=\"%s\", nonce=\"%llx\"", ap_auth_name(r), r->request_time));}AP_DECLARE(int) ap_get_basic_auth_pw(request_rec *r, const char **pw){ const char *auth_line = apr_table_get(r->headers_in, (PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authorization" : "Authorization"); const char *t; if (!(t = ap_auth_type(r)) || strcasecmp(t, "Basic")) return DECLINED; if (!ap_auth_name(r)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "need AuthName: %s", r->uri); return HTTP_INTERNAL_SERVER_ERROR; } if (!auth_line) { ap_note_basic_auth_failure(r); return HTTP_UNAUTHORIZED; } if (strcasecmp(ap_getword(r->pool, &auth_line, ' '), "Basic")) { /* Client tried to authenticate using wrong auth scheme */ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "client used wrong authentication scheme: %s", r->uri); ap_note_basic_auth_failure(r); return HTTP_UNAUTHORIZED; } while (*auth_line == ' ' || *auth_line == '\t') { auth_line++; } t = ap_pbase64decode(r->pool, auth_line); r->user = ap_getword_nulls (r->pool, &t, ':'); r->ap_auth_type = "Basic"; *pw = t; return OK;}struct content_length_ctx { int data_sent; /* true if the C-L filter has already sent at * least one bucket on to the next output filter * for this request */};/* This filter computes the content length, but it also computes the number * of bytes sent to the client. This means that this filter will always run * through all of the buckets in all brigades */AP_CORE_DECLARE_NONSTD(apr_status_t) ap_content_length_filter( ap_filter_t *f, apr_bucket_brigade *b){ request_rec *r = f->r; struct content_length_ctx *ctx; apr_bucket *e; int eos = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -