Hi Felix, Thanks for investigations ! Is it an issue due to our code or a bug in hc4?
ps: didn’t look deeply yet qt your findings Regards On Friday, December 14, 2018, Felix Schumacher < [email protected]> wrote: > > Am 14.12.18 um 13:17 schrieb Felix Schumacher: > >> >> Am 13.12.18 um 23:28 schrieb Philippe Mouawad: >> >>> Hello, >>> >>> We have a confirmed bug report : >>> >>> - https://bz.apache.org/bugzilla/show_bug.cgi?id=62852 >>> >>> It appears that when using proxy for a request, the method >>> request.getRequestHeaders() called on the request returned >>> HttpContext#getAttribute(HttpCoreContext.HTTP_REQUEST) returns only >>> part of >>> the headers. >>> >>> While it returns them all if not using proxy. >>> >> >> The headers (context) gets changed on line 189 in >> org.apache.http.impl.execchain.ProtcolExec. >> >> final CloseableHttpResponse response = >> this.requestExecutor.execute(route, request, >> context, execAware); >> try { >> // Run response protocol interceptors >> context.setAttribute(HttpCoreContext.HTTP_RESPONSE, >> response); <-- Here >> this.httpProcessor.process(response, context); >> return response; >> } catch (final RuntimeException ex) { >> >> Will debug further. >> > > Thread [Thread Group 1-1] (Suspended) > org.apache.jmeter.protocol.http.sampler.HTTPHC4Impl$5(org. > apache.http.protocol.HttpRequestExecutor).preProcess(org.apache.http.HttpRequest, > org.apache.http.protocol.HttpProcessor, org.apache.http.protocol.HttpContext) > line: 163 > org.apache.http.impl.execchain.MainClientExec.createTunnelTo > Target(org.apache.http.auth.AuthState, org.apache.http.HttpClientConnection, > org.apache.http.conn.routing.HttpRoute, org.apache.http.HttpRequest, > org.apache.http.client.protocol.HttpClientContext) line: 472 > org.apache.http.impl.execchain.MainClientExec.establishRoute > (org.apache.http.auth.AuthState, org.apache.http.HttpClientConnection, > org.apache.http.conn.routing.HttpRoute, org.apache.http.HttpRequest, > org.apache.http.client.protocol.HttpClientContext) line: 411 > org.apache.http.impl.execchain.MainClientExec.execute(org. > apache.http.conn.routing.HttpRoute, > org.apache.http.client.methods.HttpRequestWrapper, > org.apache.http.client.protocol.HttpClientContext, > org.apache.http.client.methods.HttpExecutionAware) line: 237 > org.apache.http.impl.execchain.ProtocolExec.execute(org. > apache.http.conn.routing.HttpRoute, > org.apache.http.client.methods.HttpRequestWrapper, > org.apache.http.client.protocol.HttpClientContext, > org.apache.http.client.methods.HttpExecutionAware) line: 185 > org.apache.http.impl.execchain.RetryExec.execute(org.apache.http.conn.routing.HttpRoute, > org.apache.http.client.methods.HttpRequestWrapper, > org.apache.http.client.protocol.HttpClientContext, > org.apache.http.client.methods.HttpExecutionAware) line: 89 > org.apache.http.impl.execchain.RedirectExec.execute(org. > apache.http.conn.routing.HttpRoute, > org.apache.http.client.methods.HttpRequestWrapper, > org.apache.http.client.protocol.HttpClientContext, > org.apache.http.client.methods.HttpExecutionAware) line: 110 > org.apache.http.impl.client.InternalHttpClient.doExecute(org.apache.http.HttpHost, > org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) line: > 185 > org.apache.http.impl.client.InternalHttpClient(org.apache.ht > tp.impl.client.CloseableHttpClient).execute(org.apache.http.client.methods.HttpUriRequest, > org.apache.http.protocol.HttpContext) line: 83 > org.apache.jmeter.protocol.http.sampler.HTTPHC4Impl.executeR > equest(org.apache.http.impl.client.CloseableHttpClient, > org.apache.http.client.methods.HttpRequestBase, > org.apache.http.protocol.HttpContext, java.net.URL) line: 840 > org.apache.jmeter.protocol.http.sampler.HTTPHC4Impl.sample(java.net.URL, > java.lang.String, boolean, int) line: 576 > org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy.sample(java.net.URL, > java.lang.String, boolean, int) line: 67 > org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy(org > .apache.jmeter.protocol.http.sampler.HTTPSamplerBase).sample() line: 1231 > org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy(org > .apache.jmeter.protocol.http.sampler.HTTPSamplerBase).sampl > e(org.apache.jmeter.samplers.Entry) line: 1220 > org.apache.jmeter.threads.JMeterThread.doSampling(org.apache.jmeter.threads.JMeterContext, > org.apache.jmeter.samplers.Sampler) line: 622 > org.apache.jmeter.threads.JMeterThread.executeSamplePackage( > org.apache.jmeter.samplers.Sampler, > org.apache.jmeter.control.TransactionSampler, > org.apache.jmeter.threads.SamplePackage, > org.apache.jmeter.threads.JMeterContext) > line: 546 > org.apache.jmeter.threads.JMeterThread.processSampler(org. > apache.jmeter.samplers.Sampler, org.apache.jmeter.samplers.Sampler, > org.apache.jmeter.threads.JMeterContext) line: 486 > org.apache.jmeter.threads.JMeterThread.run() line: 253 > java.lang.Thread.run() line: 748 > > It seems that httpclient initiates the replacement of the "correct" > request. I have managed to revert that behaviour by adding a save/restore > functionality in our REQUEST_EXECUTOR that is implemented in HTTPHC4Impl. I > implemented the method preProcess and saved the old request before calling > the super method and restoring the request after the call. > > That looks quite ugly and I have no idea, if it is correct. But it works > for the simple test plan. > > Felix > > >> Felix >> >> >>> See: >>> >>> - >>> https://github.com/apache/jmeter/blob/trunk/src/protocol/ >>> http/org/apache/jmeter/protocol/http/sampler/HTTPHC4Impl.java#L580 >>> >>> >>> I tried to reproduce behavior with HTTPClient only but couldn't , so it >>> seems issue is somewhere in our code possibly due to interceptors or >>> request executor. >>> >>> /* >>> * ==================================================================== >>> * Licensed to the Apache Software Foundation (ASF) under one >>> * or more contributor license agreements. See the NOTICE file >>> * distributed with this work for additional information >>> * regarding copyright ownership. The ASF licenses this file >>> * to you under the Apache License, Version 2.0 (the >>> * "License"); you may not use this file except in compliance >>> * with the License. You may obtain a copy of the License at >>> * >>> * http://www.apache.org/licenses/LICENSE-2.0 >>> * >>> * Unless required by applicable law or agreed to in writing, >>> * software distributed under the License is distributed on an >>> * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY >>> * KIND, either express or implied. See the License for the >>> * specific language governing permissions and limitations >>> * under the License. >>> * ==================================================================== >>> * >>> * This software consists of voluntary contributions made by many >>> * individuals on behalf of the Apache Software Foundation. For more >>> * information on the Apache Software Foundation, please see >>> * <http://www.apache.org/>. >>> * >>> */ >>> >>> package org.apache.jmeter.protocol.http.proxy; >>> >>> import java.util.Arrays; >>> >>> import org.apache.http.HttpHost; >>> import org.apache.http.HttpRequest; >>> import org.apache.http.client.config.RequestConfig; >>> import org.apache.http.client.methods.CloseableHttpResponse; >>> import org.apache.http.client.methods.HttpGet; >>> import org.apache.http.impl.client.CloseableHttpClient; >>> import org.apache.http.impl.client.HttpClients; >>> import org.apache.http.protocol.BasicHttpContext; >>> import org.apache.http.protocol.HttpContext; >>> import org.apache.http.protocol.HttpCoreContext; >>> >>> /** >>> * How to send a request via proxy. >>> * >>> * @since 4.0 >>> */ >>> public class TestProxy { >>> >>> public static void main(String[] args)throws Exception { >>> CloseableHttpClient httpclient = HttpClients.createDefault(); >>> try { >>> >>> HttpHost target = new HttpHost("jmeter.apache.org", 80, >>> "http"); >>> HttpHost proxy = new HttpHost("localhost", 8888, "http"); >>> >>> RequestConfig config = RequestConfig.custom() >>> .setProxy(proxy) >>> .build(); >>> HttpGet request = new HttpGet("/"); >>> request.addHeader("X-sleep", "5"); >>> request.setConfig(config); >>> >>> System.out.println("Executing request " + >>> request.getRequestLine() + " to " + target + " via " + proxy); >>> HttpContext localContext = new BasicHttpContext(); >>> CloseableHttpResponse response = httpclient.execute(target, >>> request, localContext); >>> final HttpRequest httpRequestFromLocalContext = >>> (HttpRequest) >>> localContext.getAttribute(HttpCoreContext.HTTP_REQUEST); >>> try { >>> >>> System.out.println("----------------------------------------"); >>> System.out.println(response.getStatusLine()); >>> System.out.println(Arrays.asList(request.getAllHeaders())); >>> >>> System.out.println(Arrays.asList(httpRequestFromLocalContext.getAllHeaders())); >>> >>> System.out.println(Arrays.asList(response.getAllHeaders())); >>> >>> //System.out.println(EntityUtils.toString(response.getEntity())); >>> } finally { >>> response.close(); >>> } >>> } finally { >>> httpclient.close(); >>> } >>> } >>> >>> } >>> >>> OUTPUT: >>> ------------------------------------------------------------ >>> ---------------------------------------- >>> Executing request GET / HTTP/1.1 to http://jmeter.apache.org:80 via >>> http://localhost:8888 >>> ---------------------------------------- >>> HTTP/1.1 200 OK >>> [X-sleep: 5] >>> [X-sleep: 5, Host: jmeter.apache.org:80, Proxy-Connection: Keep-Alive, >>> User-Agent: Apache-HttpClient/4.5.6 (Java/1.8.0_161), Accept-Encoding: >>> gzip,deflate] >>> [Date: Thu, 13 Dec 2018 22:23:23 GMT, Server: Apache/2.4.18 (Ubuntu), >>> Last-Modified: Sun, 09 Sep 2018 15:25:54 GMT, ETag: >>> "3159-57571db50c67a-gzip", Accept-Ranges: bytes, Vary: Accept-Encoding, >>> Keep-Alive: timeout=30, max=100, Connection: Keep-Alive, Content-Type: >>> text/html, Content-Length: 12633] >>> ------------------------------------------------------------ >>> ---------------------------------------- >>> >>> >>> Regards >>> Philippe M. >>> <https://www.openstreetmap.org/#map=18/50.69454/3.16455> >>> >>> -- Cordialement. Philippe Mouawad.
