This is an automated email from the ASF dual-hosted git repository.

masaori pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new 5810f13  Optimize HTTPHdr conversion of HTTP/2 to HTTP/1.1
5810f13 is described below

commit 5810f1307eb6ae6c877020280dc31f83397c9f88
Author: Masaori Koshiba <masa...@apache.org>
AuthorDate: Thu Mar 19 16:29:28 2020 +0900

    Optimize HTTPHdr conversion of HTTP/2 to HTTP/1.1
    
    - Avoid memcpy & parse for setting URL
    - Avoid unnecessary MIMEField search
---
 proxy/http2/HTTP2.cc | 90 ++++++++++++++++++++++++----------------------------
 1 file changed, 42 insertions(+), 48 deletions(-)

diff --git a/proxy/http2/HTTP2.cc b/proxy/http2/HTTP2.cc
index e23c44d..ec5a5fb 100644
--- a/proxy/http2/HTTP2.cc
+++ b/proxy/http2/HTTP2.cc
@@ -406,88 +406,82 @@ http2_parse_window_update(IOVec iov, uint32_t &size)
 ParseResult
 http2_convert_header_from_2_to_1_1(HTTPHdr *headers)
 {
-  MIMEField *field;
-
   ink_assert(http_hdr_type_get(headers->m_http) != HTTP_TYPE_UNKNOWN);
 
+  // HTTP Version
+  headers->version_set(HTTPVersion(1, 1));
+
   if (http_hdr_type_get(headers->m_http) == HTTP_TYPE_REQUEST) {
-    const char *scheme, *authority, *path;
-    int scheme_len, authority_len, path_len;
+    // :scheme
+    if (MIMEField *field = headers->field_find(HTTP2_VALUE_SCHEME, 
HTTP2_LEN_SCHEME); field != nullptr && field->value_is_valid()) {
+      int scheme_len;
+      const char *scheme = field->value_get(&scheme_len);
 
-    // Get values of :scheme, :authority and :path to assemble requested URL
-    if ((field = headers->field_find(HTTP2_VALUE_SCHEME, HTTP2_LEN_SCHEME)) != 
nullptr && field->value_is_valid()) {
-      scheme = field->value_get(&scheme_len);
+      int scheme_wks_idx = hdrtoken_tokenize(scheme, scheme_len);
+      url_scheme_set(headers->m_heap, headers->m_http->u.req.m_url_impl, 
scheme, scheme_wks_idx, scheme_len, true);
+
+      headers->field_delete(field);
     } else {
       return PARSE_RESULT_ERROR;
     }
 
-    if ((field = headers->field_find(HTTP2_VALUE_AUTHORITY, 
HTTP2_LEN_AUTHORITY)) != nullptr && field->value_is_valid()) {
-      authority = field->value_get(&authority_len);
+    // :authority
+    if (MIMEField *field = headers->field_find(HTTP2_VALUE_AUTHORITY, 
HTTP2_LEN_AUTHORITY);
+        field != nullptr && field->value_is_valid()) {
+      int authority_len;
+      const char *authority = field->value_get(&authority_len);
+
+      url_host_set(headers->m_heap, headers->m_http->u.req.m_url_impl, 
authority, authority_len, true);
+
+      headers->field_delete(field);
     } else {
       return PARSE_RESULT_ERROR;
     }
 
-    if ((field = headers->field_find(HTTP2_VALUE_PATH, HTTP2_LEN_PATH)) != 
nullptr && field->value_is_valid()) {
-      path = field->value_get(&path_len);
+    // :path
+    if (MIMEField *field = headers->field_find(HTTP2_VALUE_PATH, 
HTTP2_LEN_PATH); field != nullptr && field->value_is_valid()) {
+      int path_len;
+      const char *path = field->value_get(&path_len);
+
+      // cut first '/' if there, because `url_print()` add '/' before printing 
path
+      if (path_len >= 1 && path[0] == '/') {
+        ++path;
+        --path_len;
+      }
+
+      url_path_set(headers->m_heap, headers->m_http->u.req.m_url_impl, path, 
path_len, true);
+
+      headers->field_delete(field);
     } else {
       return PARSE_RESULT_ERROR;
     }
 
-    // Parse URL
-    Arena arena;
-    size_t url_length     = scheme_len + 3 + authority_len + path_len;
-    char *url             = arena.str_alloc(url_length);
-    const char *url_start = url;
-
-    memcpy(url, scheme, scheme_len);
-    memcpy(url + scheme_len, "://", 3);
-    memcpy(url + scheme_len + 3, authority, authority_len);
-    memcpy(url + scheme_len + 3 + authority_len, path, path_len);
-    url_parse(headers->m_heap, headers->m_http->u.req.m_url_impl, &url_start, 
url + url_length, true);
-    arena.str_free(url);
-
-    // Get value of :method
-    if ((field = headers->field_find(HTTP2_VALUE_METHOD, HTTP2_LEN_METHOD)) != 
nullptr && field->value_is_valid()) {
+    // :method
+    if (MIMEField *field = headers->field_find(HTTP2_VALUE_METHOD, 
HTTP2_LEN_METHOD); field != nullptr && field->value_is_valid()) {
       int method_len;
       const char *method = field->value_get(&method_len);
 
-      int method_wks_idx = hdrtoken_tokenize(method, method_len);
-      http_hdr_method_set(headers->m_heap, headers->m_http, method, 
method_wks_idx, method_len, false);
+      headers->method_set(method, method_len);
+      headers->field_delete(field);
     } else {
       return PARSE_RESULT_ERROR;
     }
 
     // Combine Cookie headers ([RFC 7540] 8.1.2.5.)
-    field = headers->field_find(MIME_FIELD_COOKIE, MIME_LEN_COOKIE);
-    if (field) {
+    if (MIMEField *field = headers->field_find(MIME_FIELD_COOKIE, 
MIME_LEN_COOKIE); field != nullptr) {
       headers->field_combine_dups(field, true, ';');
     }
-
-    // Convert HTTP version to 1.1
-    int32_t version = HTTP_VERSION(1, 1);
-    http_hdr_version_set(headers->m_http, version);
-
-    // Remove HTTP/2 style headers
-    headers->field_delete(HTTP2_VALUE_SCHEME, HTTP2_LEN_SCHEME);
-    headers->field_delete(HTTP2_VALUE_METHOD, HTTP2_LEN_METHOD);
-    headers->field_delete(HTTP2_VALUE_AUTHORITY, HTTP2_LEN_AUTHORITY);
-    headers->field_delete(HTTP2_VALUE_PATH, HTTP2_LEN_PATH);
   } else {
-    // Set HTTP Version 1.1
-    int32_t version = HTTP_VERSION(1, 1);
-    http_hdr_version_set(headers->m_http, version);
-
     // Set status from :status
-    if ((field = headers->field_find(HTTP2_VALUE_STATUS, HTTP2_LEN_STATUS)) != 
nullptr) {
+    if (MIMEField *field = headers->field_find(HTTP2_VALUE_STATUS, 
HTTP2_LEN_STATUS); field != nullptr) {
       int status_len;
       const char *status = field->value_get(&status_len);
+
       headers->status_set(http_parse_status(status, status + status_len));
+      headers->field_delete(field);
     } else {
       return PARSE_RESULT_ERROR;
     }
-
-    // Remove HTTP/2 style headers
-    headers->field_delete(HTTP2_VALUE_STATUS, HTTP2_LEN_STATUS);
   }
 
   // Check validity of all names and values

Reply via email to