You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jmeter.apache.org by pm...@apache.org on 2016/05/04 19:49:51 UTC

svn commit: r1742324 - /jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPHC4Impl.java

Author: pmouawad
Date: Wed May  4 19:49:51 2016
New Revision: 1742324

URL: http://svn.apache.org/viewvc?rev=1742324&view=rev
Log:
Bug 59401 - The HttpClient4 implementation uncompresses the compressed response but removes Content-Encoding response header when request has header "Accept-Encoding = gzip, deflate" 
Bugzilla Id: 59401

Modified:
    jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPHC4Impl.java

Modified: jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPHC4Impl.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPHC4Impl.java?rev=1742324&r1=1742323&r2=1742324&view=diff
==============================================================================
--- jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPHC4Impl.java (original)
+++ jmeter/trunk/src/protocol/http/org/apache/jmeter/protocol/http/sampler/HTTPHC4Impl.java Wed May  4 19:49:51 2016
@@ -59,6 +59,7 @@ import org.apache.http.client.Credential
 import org.apache.http.client.HttpClient;
 import org.apache.http.client.HttpRequestRetryHandler;
 import org.apache.http.client.config.CookieSpecs;
+import org.apache.http.client.config.RequestConfig;
 import org.apache.http.client.entity.UrlEncodedFormEntity;
 import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
 import org.apache.http.client.methods.HttpGet;
@@ -186,6 +187,48 @@ public class HTTPHC4Impl extends HTTPHCA
     };
 
     /**
+     * Attribute name used to store headers in {@link BasicHttpContext}
+     */
+    private static final String JMETER_RESPONSE_BACKUP_HEADERS = "__jmeter.RESPONSE_BACKUP_HEADERS";
+
+    /**
+     * Headers to save
+     */
+    private static final String[] HEADERS_TO_SAVE = new String[]{
+                    "content-length",
+                    "content-encoding",
+                    "content-md5"
+            };
+    
+    /**
+     * Custom implementation that backups headers related to Compressed responses 
+     * that HC core {@link ResponseContentEncoding} removes after uncompressing
+     */
+    private static final HttpResponseInterceptor RESPONSE_CONTENT_ENCODING = new ResponseContentEncoding() {
+        @Override
+        public void process(HttpResponse response, HttpContext context)
+                throws HttpException, IOException {
+            
+            context.removeAttribute(JMETER_RESPONSE_BACKUP_HEADERS);
+            final HttpEntity entity = response.getEntity();
+            final HttpClientContext clientContext = HttpClientContext.adapt(context);
+            final RequestConfig requestConfig = clientContext.getRequestConfig();
+            if (requestConfig.isContentCompressionEnabled() && entity != null && entity.getContentLength() != 0) {
+                final Header ceheader = entity.getContentEncoding();
+                if (ceheader != null) {
+                    ArrayList<Header[]> headersToSave = new ArrayList<>(3);
+                    for(String name : HEADERS_TO_SAVE) {
+                        Header[] hdr = response.getHeaders(name); // empty if none
+                        headersToSave.add(hdr);
+                    }
+                   context.setAttribute(JMETER_RESPONSE_BACKUP_HEADERS, headersToSave);
+                }
+            }
+            super.process(response, clientContext);
+        }
+    };
+    
+    /**
      * 1 HttpClient instance per combination of (HttpClient,HttpClientKey)
      */
     private static final ThreadLocal<Map<HttpClientKey, HttpClient>> HTTPCLIENTS_CACHE_PER_THREAD_AND_HTTPCLIENTKEY = 
@@ -357,7 +400,7 @@ public class HTTPHC4Impl extends HTTPHCA
             res.setResponseMessage(statusLine.getReasonPhrase());
             res.setSuccessful(isSuccessCode(statusCode));
 
-            res.setResponseHeaders(getResponseHeaders(httpResponse));
+            res.setResponseHeaders(getResponseHeaders(httpResponse, localContext));
             if (res.isRedirect()) {
                 final Header headerLocation = httpResponse.getLastHeader(HTTPConstants.HEADER_LOCATION);
                 if (headerLocation == null) { // HTTP protocol violation, but avoids NPE
@@ -750,7 +793,7 @@ public class HTTPHC4Impl extends HTTPHCA
             }
             // see https://issues.apache.org/jira/browse/HTTPCORE-397
             ((AbstractHttpClient) httpClient).setReuseStrategy(DefaultClientConnectionReuseStrategy.INSTANCE);
-            ((AbstractHttpClient) httpClient).addResponseInterceptor(new ResponseContentEncoding());
+            ((AbstractHttpClient) httpClient).addResponseInterceptor(RESPONSE_CONTENT_ENCODING);
             ((AbstractHttpClient) httpClient).addResponseInterceptor(METRICS_SAVER); // HACK
             ((AbstractHttpClient) httpClient).addRequestInterceptor(METRICS_RESETTER); 
             
@@ -894,24 +937,47 @@ public class HTTPHC4Impl extends HTTPHCA
      *
      * @param response
      *            containing the headers
+     * @param localContext {@link HttpContext}
      * @return string containing the headers, one per line
      */
-    private String getResponseHeaders(HttpResponse response) {
+    private String getResponseHeaders(HttpResponse response, HttpContext localContext) {
         StringBuilder headerBuf = new StringBuilder();
-        Header[] rh = response.getAllHeaders();
         headerBuf.append(response.getStatusLine());// header[0] is not the status line...
         headerBuf.append("\n"); // $NON-NLS-1$
 
+        Header[] rh = response.getAllHeaders();
         for (Header responseHeader : rh) {
-            headerBuf.append(responseHeader.getName());
-            headerBuf.append(": "); // $NON-NLS-1$
-            headerBuf.append(responseHeader.getValue());
-            headerBuf.append("\n"); // $NON-NLS-1$
+            writeResponseHeader(headerBuf, responseHeader);
         }
+        List<Header[]> backupHeaders = (List<Header[]>) localContext.getAttribute(JMETER_RESPONSE_BACKUP_HEADERS);
+        if(backupHeaders != null) {
+            for (Header[] headers : backupHeaders) {
+                for (Header responseHeader: headers) {
+                    if (response.containsHeader(responseHeader.getName())) {
+                        break; // it was not deleted, so don't store it again
+                    }
+                    writeResponseHeader(headerBuf, responseHeader);
+                }
+            }
+        }
+
         return headerBuf.toString();
     }
 
     /**
+     * Write responseHeader to headerBuffer
+     * @param headerBuffer {@link StringBuilder}
+     * @param responseHeader {@link Header}
+     */
+    private void writeResponseHeader(StringBuilder headerBuffer,
+            Header responseHeader) {
+        headerBuffer.append(responseHeader.getName())
+            .append(": ") // $NON-NLS-1$
+            .append(responseHeader.getValue())
+            .append("\n"); // $NON-NLS-1$
+    }
+
+    /**
      * Extracts all the required cookies for that particular URL request and
      * sets them in the <code>HttpMethod</code> passed in.
      *
@@ -1016,10 +1082,7 @@ public class HTTPHC4Impl extends HTTPHCA
             for (Header requestHeader : requestHeaders) {
                 // Exclude the COOKIE header, since cookie is reported separately in the sample
                 if (!HTTPConstants.HEADER_COOKIE.equalsIgnoreCase(requestHeader.getName())) {
-                    hdrs.append(requestHeader.getName());
-                    hdrs.append(": "); // $NON-NLS-1$
-                    hdrs.append(requestHeader.getValue());
-                    hdrs.append("\n"); // $NON-NLS-1$
+                    writeResponseHeader(hdrs, requestHeader);
                 }
             }