You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by zw...@apache.org on 2013/03/31 03:14:35 UTC
[16/51] git commit: TS-1627: Support requests with payload
TS-1627: Support requests with payload
Allow payload in all request methods (except TRACE).
Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/3c51b612
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/3c51b612
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/3c51b612
Branch: refs/heads/3.3.x
Commit: 3c51b612f65ab8e65d913ac168decb8c162b1431
Parents: 1475f86
Author: Uri Shachar <us...@apache.org>
Authored: Wed Mar 20 12:44:09 2013 +0200
Committer: Uri Shachar <us...@apache.org>
Committed: Wed Mar 20 12:44:09 2013 +0200
----------------------------------------------------------------------
CHANGES | 2 +
proxy/http/HttpSM.cc | 15 ++-
proxy/http/HttpTransact.cc | 254 ++++++++++++++++-----------------------
3 files changed, 118 insertions(+), 153 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/3c51b612/CHANGES
----------------------------------------------------------------------
diff --git a/CHANGES b/CHANGES
index 3c24117..a60d138 100644
--- a/CHANGES
+++ b/CHANGES
@@ -2,6 +2,8 @@
Changes with Apache Traffic Server 3.3.2
+ *) [TS-1627] Support requests with payload
+
*) [TS-1763] add Arch Linux config.layout
Author: Galen Sampson <ga...@gmail.com>
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/3c51b612/proxy/http/HttpSM.cc
----------------------------------------------------------------------
diff --git a/proxy/http/HttpSM.cc b/proxy/http/HttpSM.cc
index 27a687a..bbd6495 100644
--- a/proxy/http/HttpSM.cc
+++ b/proxy/http/HttpSM.cc
@@ -783,7 +783,10 @@ HttpSM::state_read_client_request_header(int event, void *data)
ua_session->m_active = true;
HTTP_INCREMENT_DYN_STAT(http_current_active_client_connections_stat);
}
- if (t_state.hdr_info.client_request.method_get_wksidx() == HTTP_WKSIDX_GET) {
+ if (t_state.hdr_info.client_request.method_get_wksidx() == HTTP_WKSIDX_TRACE ||
+ (t_state.hdr_info.request_content_length == 0 &&
+ t_state.client_info.transfer_encoding != HttpTransact::CHUNKED_ENCODING)) {
+
// Enable further IO to watch for client aborts
ua_entry->read_vio->reenable();
} else {
@@ -1888,9 +1891,9 @@ HttpSM::state_send_server_request_header(int event, void *data)
server_entry->write_buffer = NULL;
method = t_state.hdr_info.server_request.method_get_wksidx();
if (!t_state.api_server_request_body_set &&
- (method != HTTP_WKSIDX_GET) &&
- (method == HTTP_WKSIDX_POST || method == HTTP_WKSIDX_PUT ||
- (t_state.hdr_info.extension_method && t_state.hdr_info.request_content_length > 0))) {
+ method != HTTP_WKSIDX_TRACE &&
+ (t_state.hdr_info.request_content_length > 0 || t_state.client_info.transfer_encoding == HttpTransact::CHUNKED_ENCODING)) {
+
if (post_transform_info.vc) {
setup_transform_to_server_transfer();
} else {
@@ -4900,7 +4903,9 @@ HttpSM::handle_http_server_open()
}
int method = t_state.hdr_info.server_request.method_get_wksidx();
- if ((method == HTTP_WKSIDX_POST || method == HTTP_WKSIDX_PUT) && do_post_transform_open()) {
+ if (method != HTTP_WKSIDX_TRACE &&
+ (t_state.hdr_info.request_content_length > 0 || t_state.client_info.transfer_encoding == HttpTransact::CHUNKED_ENCODING) &&
+ do_post_transform_open()) {
do_setup_post_tunnel(HTTP_TRANSFORM_VC);
} else {
setup_server_send_request_api();
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/3c51b612/proxy/http/HttpTransact.cc
----------------------------------------------------------------------
diff --git a/proxy/http/HttpTransact.cc b/proxy/http/HttpTransact.cc
index 6626c1d..e5f2394 100644
--- a/proxy/http/HttpTransact.cc
+++ b/proxy/http/HttpTransact.cc
@@ -5261,6 +5261,23 @@ HttpTransact::RequestError_t HttpTransact::check_request_validity(State* s, HTTP
int scheme = incoming_url->scheme_get_wksidx();
int method = incoming_hdr->method_get_wksidx();
+ // Check for chunked encoding
+ if (incoming_hdr->presence(MIME_PRESENCE_TRANSFER_ENCODING)) {
+ MIMEField *field = incoming_hdr->field_find(MIME_FIELD_TRANSFER_ENCODING, MIME_LEN_TRANSFER_ENCODING);
+ HdrCsvIter enc_val_iter;
+ int enc_val_len;
+ const char *enc_value = enc_val_iter.get_first(field, &enc_val_len);
+
+ while (enc_value) {
+ const char *wks_value = hdrtoken_string_to_wks(enc_value, enc_val_len);
+ if (wks_value == HTTP_VALUE_CHUNKED) {
+ s->client_info.transfer_encoding = CHUNKED_ENCODING;
+ break;
+ }
+ enc_value = enc_val_iter.get_next(&enc_val_len);
+ }
+ }
+
if (!((scheme == URL_WKSIDX_HTTP) && (method == HTTP_WKSIDX_GET))) {
if (scheme != URL_WKSIDX_HTTP && scheme != URL_WKSIDX_HTTPS &&
method != HTTP_WKSIDX_CONNECT) {
@@ -5278,33 +5295,13 @@ HttpTransact::RequestError_t HttpTransact::check_request_validity(State* s, HTTP
return BAD_CONNECT_PORT;
}
+ // Require Content-Length/Transfer-Encoding for POST/PUSH/PUT
if ((scheme == URL_WKSIDX_HTTP || scheme == URL_WKSIDX_HTTPS) &&
- (method == HTTP_WKSIDX_POST || method == HTTP_WKSIDX_PUSH || method == HTTP_WKSIDX_PUT)) {
- if (!incoming_hdr->presence(MIME_PRESENCE_CONTENT_LENGTH)) {
- bool chunked_encoding = false;
-
- if (incoming_hdr->presence(MIME_PRESENCE_TRANSFER_ENCODING)) {
- MIMEField *field = incoming_hdr->field_find(MIME_FIELD_TRANSFER_ENCODING, MIME_LEN_TRANSFER_ENCODING);
- HdrCsvIter enc_val_iter;
- int enc_val_len;
- const char *enc_value = enc_val_iter.get_first(field, &enc_val_len);
-
- while (enc_value) {
- const char *wks_value = hdrtoken_string_to_wks(enc_value, enc_val_len);
-
- if (wks_value == HTTP_VALUE_CHUNKED) {
- chunked_encoding = true;
- break;
- }
- enc_value = enc_val_iter.get_next(&enc_val_len);
- }
- }
+ (method == HTTP_WKSIDX_POST || method == HTTP_WKSIDX_PUSH || method == HTTP_WKSIDX_PUT) &&
+ ! incoming_hdr->presence(MIME_PRESENCE_CONTENT_LENGTH) &&
+ ! s->client_info.transfer_encoding == CHUNKED_ENCODING) {
- if (!chunked_encoding)
return NO_POST_CONTENT_LENGTH;
- else
- s->client_info.transfer_encoding = CHUNKED_ENCODING;
- }
}
}
// Check whether a Host header field is missing in the request.
@@ -5656,12 +5653,10 @@ HttpTransact::initialize_state_variables_from_request(State* s, HTTPHdr* obsolet
s->hdr_info.extension_method = true;
}
- ////////////////////////////////////////////////
- // get request content length for POST or PUT //
- ////////////////////////////////////////////////
- if ((s->method != HTTP_WKSIDX_GET) &&
- (s->method == HTTP_WKSIDX_POST || s->method == HTTP_WKSIDX_PUT ||
- s->method == HTTP_WKSIDX_PUSH || s->hdr_info.extension_method)) {
+ //////////////////////////////////////////////////
+ // get request content length //
+ //////////////////////////////////////////////////
+ if (s->method != HTTP_WKSIDX_TRACE) {
int64_t length = incoming_request->get_content_length();
s->hdr_info.request_content_length = (length >= 0) ? length : HTTP_UNDEFINED_CL; // content length less than zero is invalid
@@ -5672,19 +5667,8 @@ HttpTransact::initialize_state_variables_from_request(State* s, HTTPHdr* obsolet
s->hdr_info.request_content_length = 0;
}
// if transfer encoding is chunked content length is undefined
- if (incoming_request->presence(MIME_PRESENCE_TRANSFER_ENCODING)) {
- MIMEField *field = incoming_request->field_find(MIME_FIELD_TRANSFER_ENCODING, MIME_LEN_TRANSFER_ENCODING);
- HdrCsvIter enc_val_iter;
- int enc_val_len;
- const char *enc_value = enc_val_iter.get_first(field, &enc_val_len);
-
- while (enc_value) {
- const char *wks_value = hdrtoken_string_to_wks(enc_value, enc_val_len);
-
- if (wks_value == HTTP_VALUE_CHUNKED)
- s->hdr_info.request_content_length = HTTP_UNDEFINED_CL;
- enc_value = enc_val_iter.get_next(&enc_val_len);
- }
+ if (s->client_info.transfer_encoding == CHUNKED_ENCODING) {
+ s->hdr_info.request_content_length = HTTP_UNDEFINED_CL;
}
s->request_data.hdr = &s->hdr_info.client_request;
s->request_data.hostname_str = s->arena.str_store(host_name, host_len);
@@ -6699,126 +6683,100 @@ HttpTransact::will_this_request_self_loop(State* s)
void
HttpTransact::handle_content_length_header(State* s, HTTPHdr* header, HTTPHdr* base)
{
- if (header->type_get() == HTTP_TYPE_RESPONSE) {
- // This isn't used.
- // int status_code = base->status_get();
- int64_t cl = HTTP_UNDEFINED_CL;
- if (base->presence(MIME_PRESENCE_CONTENT_LENGTH)) {
- cl = base->get_content_length();
- if (cl >= 0) {
- // header->set_content_length(cl);
- ink_debug_assert(header->get_content_length() == cl);
-
- switch (s->source) {
- case SOURCE_HTTP_ORIGIN_SERVER:
- // We made our decision about whether to trust the
- // response content length in init_state_vars_from_response()
- if (s->range_setup != HttpTransact::RANGE_NOT_TRANSFORM_REQUESTED)
- break;
- case SOURCE_CACHE:
-
- // if we are doing a single Range: request, calculate the new
- // C-L: header
- if (s->range_setup == HttpTransact::RANGE_NOT_TRANSFORM_REQUESTED) {
- Debug("http_trans", "Partial content requested, re-calculating content-length");
- change_response_header_because_of_range_request(s,header);
- s->hdr_info.trust_response_cl = true;
- }
- ////////////////////////////////////////////////
- // Make sure that the cache's object size //
- // agrees with the Content-Length //
- // Otherwise, set the state's machine view //
- // of c-l to undefined to turn off K-A //
- ////////////////////////////////////////////////
- else if ((int64_t) s->cache_info.object_read->object_size_get() == cl) {
- s->hdr_info.trust_response_cl = true;
- } else {
- DebugTxn("http_trans", "Content Length header and cache object size mismatch." "Disabling keep-alive");
- s->hdr_info.trust_response_cl = false;
- }
- break;
- case SOURCE_TRANSFORM:
- if (s->hdr_info.transform_response_cl == HTTP_UNDEFINED_CL) {
- s->hdr_info.trust_response_cl = false;
- } else {
- s->hdr_info.trust_response_cl = true;
- }
- break;
- default:
- ink_release_assert(0);
+ int64_t cl = HTTP_UNDEFINED_CL;
+ ink_debug_assert(header->type_get() == HTTP_TYPE_RESPONSE);
+ if (base->presence(MIME_PRESENCE_CONTENT_LENGTH)) {
+ cl = base->get_content_length();
+ if (cl >= 0) {
+ // header->set_content_length(cl);
+ ink_debug_assert(header->get_content_length() == cl);
+
+ switch (s->source) {
+ case SOURCE_HTTP_ORIGIN_SERVER:
+ // We made our decision about whether to trust the
+ // response content length in init_state_vars_from_response()
+ if (s->range_setup != HttpTransact::RANGE_NOT_TRANSFORM_REQUESTED)
break;
- }
- } else {
- header->field_delete(MIME_FIELD_CONTENT_LENGTH, MIME_LEN_CONTENT_LENGTH);
- s->hdr_info.trust_response_cl = false;
- }
- Debug("http_trans", "[handle_content_length_header] RESPONSE cont len in hdr is %" PRId64, header->get_content_length());
- } else {
- // No content length header
- if (s->source == SOURCE_CACHE) {
- // If there is no content-length header, we can
- // insert one since the cache knows definately
- // how long the object is unless we're in a
- // read-while-write mode and object hasn't been
- // written into a cache completely.
- cl = s->cache_info.object_read->object_size_get();
- if (cl == INT64_MAX) { //INT64_MAX cl in cache indicates rww in progress
- header->field_delete(MIME_FIELD_CONTENT_LENGTH, MIME_LEN_CONTENT_LENGTH);
- s->hdr_info.trust_response_cl = false;
- s->hdr_info.request_content_length = HTTP_UNDEFINED_CL;
- ink_assert(s->range_setup == RANGE_NONE);
- }
- else if (s->range_setup == RANGE_NOT_TRANSFORM_REQUESTED) {
- // if we are doing a single Range: request, calculate the new
- // C-L: header
+ case SOURCE_CACHE:
+
+ // if we are doing a single Range: request, calculate the new
+ // C-L: header
+ if (s->range_setup == HttpTransact::RANGE_NOT_TRANSFORM_REQUESTED) {
Debug("http_trans", "Partial content requested, re-calculating content-length");
change_response_header_because_of_range_request(s,header);
s->hdr_info.trust_response_cl = true;
}
- else {
- header->set_content_length(cl);
- s->hdr_info.trust_response_cl = true;
- }
- } else {
- // Check to see if there is no content length
- // header because the response precludes a
- // body
- if (is_response_body_precluded(header->status_get(), s->method)) {
- // We want to be able to do keep-alive here since
- // there can't be body so we don't have any
- // issues about trusting the body length
+ ////////////////////////////////////////////////
+ // Make sure that the cache's object size //
+ // agrees with the Content-Length //
+ // Otherwise, set the state's machine view //
+ // of c-l to undefined to turn off K-A //
+ ////////////////////////////////////////////////
+ else if ((int64_t) s->cache_info.object_read->object_size_get() == cl) {
s->hdr_info.trust_response_cl = true;
} else {
+ DebugTxn("http_trans", "Content Length header and cache object size mismatch." "Disabling keep-alive");
s->hdr_info.trust_response_cl = false;
}
- header->field_delete(MIME_FIELD_CONTENT_LENGTH, MIME_LEN_CONTENT_LENGTH);
- ink_assert(s->range_setup != RANGE_NOT_TRANSFORM_REQUESTED);
+ break;
+ case SOURCE_TRANSFORM:
+ if (s->hdr_info.transform_response_cl == HTTP_UNDEFINED_CL) {
+ s->hdr_info.trust_response_cl = false;
+ } else {
+ s->hdr_info.trust_response_cl = true;
+ }
+ break;
+ default:
+ ink_release_assert(0);
+ break;
}
- }
- } else if (header->type_get() == HTTP_TYPE_REQUEST) {
- int method = header->method_get_wksidx();
-
- if (method == HTTP_WKSIDX_GET || method == HTTP_WKSIDX_HEAD || method == HTTP_WKSIDX_OPTIONS || method == HTTP_WKSIDX_TRACE) { /* No body, no content-length */
-
+ } else {
header->field_delete(MIME_FIELD_CONTENT_LENGTH, MIME_LEN_CONTENT_LENGTH);
- s->hdr_info.request_content_length = 0;
-
- } else if (base && base->presence(MIME_PRESENCE_CONTENT_LENGTH)) {
- /* Copy over the content length if its set */
- ink_debug_assert(s->hdr_info.request_content_length == base->get_content_length());
- ink_debug_assert(header->get_content_length() == base->get_content_length());
+ s->hdr_info.trust_response_cl = false;
+ }
+ Debug("http_trans", "[handle_content_length_header] RESPONSE cont len in hdr is %" PRId64, header->get_content_length());
+ } else {
+ // No content length header
+ if (s->source == SOURCE_CACHE) {
+ // If there is no content-length header, we can
+ // insert one since the cache knows definately
+ // how long the object is unless we're in a
+ // read-while-write mode and object hasn't been
+ // written into a cache completely.
+ cl = s->cache_info.object_read->object_size_get();
+ if (cl == INT64_MAX) { //INT64_MAX cl in cache indicates rww in progress
+ header->field_delete(MIME_FIELD_CONTENT_LENGTH, MIME_LEN_CONTENT_LENGTH);
+ s->hdr_info.trust_response_cl = false;
+ s->hdr_info.request_content_length = HTTP_UNDEFINED_CL;
+ ink_assert(s->range_setup == RANGE_NONE);
+ }
+ else if (s->range_setup == RANGE_NOT_TRANSFORM_REQUESTED) {
+ // if we are doing a single Range: request, calculate the new
+ // C-L: header
+ Debug("http_trans", "Partial content requested, re-calculating content-length");
+ change_response_header_because_of_range_request(s,header);
+ s->hdr_info.trust_response_cl = true;
+ }
+ else {
+ header->set_content_length(cl);
+ s->hdr_info.trust_response_cl = true;
+ }
} else {
- /*
- * Otherwise we are in a method with a potential cl, so unset
- * the header and flag the cl as undefined for the state machine.
- */
+ // Check to see if there is no content length
+ // header because the response precludes a
+ // body
+ if (is_response_body_precluded(header->status_get(), s->method)) {
+ // We want to be able to do keep-alive here since
+ // there can't be body so we don't have any
+ // issues about trusting the body length
+ s->hdr_info.trust_response_cl = true;
+ } else {
+ s->hdr_info.trust_response_cl = false;
+ }
header->field_delete(MIME_FIELD_CONTENT_LENGTH, MIME_LEN_CONTENT_LENGTH);
- s->hdr_info.request_content_length = HTTP_UNDEFINED_CL;
+ ink_assert(s->range_setup != RANGE_NOT_TRANSFORM_REQUESTED);
}
- DebugTxn("http_trans", "[handle_content_length_header] cont len in hdr is %" PRId64", stat var is %" PRId64,
- header->get_content_length(), s->hdr_info.request_content_length);
}
-
return;
} /* End HttpTransact::handle_content_length_header */