in src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/proxy/Proxy.java [166:318]
public void run() {
// Check which HTTPSampler class we should use
String httpSamplerName = target.getSamplerTypeName();
HttpRequestHdr request = new HttpRequestHdr(target.getPrefixHTTPSampleName(), httpSamplerName,
target.getHTTPSampleNamingMode(), target.getHttpSampleNameFormat());
request.setDetectGraphQLRequest(target.getDetectGraphQLRequest());
SampleResult result = null;
HeaderManager headers = null;
HTTPSamplerBase sampler = null;
final boolean isDebug = log.isDebugEnabled();
log.debug("{} ====================================================================", port);
SamplerCreator samplerCreator = null;
try {
JMeterContextService.getContext().setRecording(true);
// Now, parse initial request (in case it is a CONNECT request)
byte[] ba = request.parse(new BufferedInputStream(clientSocket.getInputStream()));
if (ba.length == 0) {
log.debug("{} Empty request, ignored", port);
throw new JMeterException(); // hack to skip processing
}
if (isDebug) {
@SuppressWarnings("DefaultCharset")
final String reparsed = new String(ba); // NOSONAR False positive
log.debug("{} Initial request: {}", port, reparsed);
}
// Use with SSL connection
OutputStream outStreamClient = clientSocket.getOutputStream();
if (request.getMethod().startsWith(HTTPConstants.CONNECT) && (outStreamClient != null)) {
log.debug("{} Method CONNECT => SSL", port);
// write a OK response to browser, to engage SSL exchange
outStreamClient.write(
"HTTP/1.0 200 OK\r\n\r\n".getBytes(SampleResult.DEFAULT_HTTP_ENCODING)); // $NON-NLS-1$
outStreamClient.flush();
// With ssl request, url is host:port (without https:// or path)
String[] param = request.getUrl().split(":"); // $NON-NLS-1$
if (param.length == 2) {
log.debug("{} Start to negotiate SSL connection, host: {}", port ,param[0]);
clientSocket = startSSL(clientSocket, param[0]);
} else {
// Should not happen, but if it does we don't want to continue
log.error("In SSL request, unable to find host and port in CONNECT request: {}", request.getUrl());
throw new JMeterException(); // hack to skip processing
}
// Re-parse (now it's the http request over SSL)
try {
ba = request.parse(new BufferedInputStream(clientSocket.getInputStream()));
} catch (IOException ioe) { // most likely this is because of a certificate error
// param.length is 2 here
final String url = " for '"+ param[0] +"'";
log.warn("{} Problem with SSL certificate for url {}? Ensure browser is set to accept the JMeter proxy cert: {}",
port, url,ioe.getMessage());
// Generate result (if nec.) and populate it
result = generateErrorResult(result, request, ioe, "\n**ensure browser is set to accept the JMeter proxy certificate**");
throw new JMeterException(); // hack to skip processing
}
if (isDebug) {
@SuppressWarnings("DefaultCharset")
final String reparsed = new String(ba); // NOSONAR False positive
log.debug("{} Reparse: {}", port, reparsed);
}
if (ba.length == 0) {
log.warn("{} Empty response to http over SSL. Probably waiting for user to authorize the certificate for {}",
port, request.getUrl());
throw new JMeterException(); // hack to skip processing
}
}
samplerCreator = SAMPLERFACTORY.getSamplerCreator(request, pageEncodings, formEncodings);
sampler = samplerCreator.createAndPopulateSampler(request, pageEncodings, formEncodings);
sampler.setUseKeepAlive(false);
/*
* Create a Header Manager to ensure that the browsers headers are
* captured and sent to the server
*/
headers = request.getHeaderManager();
sampler.setHeaderManager(headers);
sampler.threadStarted(); // Needed for HTTPSampler2
if (isDebug) {
log.debug("{} Execute sample: {} and url {}",port, sampler.getMethod(), sampler.getUrl());
}
result = sampler.sample();
// Find the page encoding and possibly encodings for forms in the page
// in the response from the web server
String pageEncoding = addPageEncoding(result);
addFormEncodings(result, pageEncoding);
writeToClient(result, new BufferedOutputStream(clientSocket.getOutputStream()));
samplerCreator.postProcessSampler(sampler, result);
} catch (JMeterException jme) {
// ignored, already processed
} catch (UnknownHostException uhe) {
log.warn("{} Server Not Found.", port, uhe);
writeErrorToClient(HttpReplyHdr.formServerNotFound());
result = generateErrorResult(result, request, uhe); // Generate result (if nec.) and populate it
} catch (IllegalArgumentException e) {
log.error("{} Not implemented (probably used https)", port, e);
writeErrorToClient(HttpReplyHdr.formNotImplemented("Probably used https instead of http. "
+ "To record https requests, see "
+ "<a href=\"http://jmeter.apache.org/usermanual/component_reference.html#HTTP(S)_Test_Script_Recorder\">"
+ "HTTP(S) Test Script Recorder documentation</a>"));
result = generateErrorResult(result, request, e); // Generate result (if nec.) and populate it
} catch (Exception e) {
log.error("{} Exception when processing sample", port, e);
writeErrorToClient(HttpReplyHdr.formInternalError());
result = generateErrorResult(result, request, e); // Generate result (if nec.) and populate it
} finally {
if(sampler != null && isDebug) {
log.debug("{} Will deliver sample {}", port, sampler.getName());
}
/*
* We don't want to store any cookies in the generated test plan
*/
if (headers != null) {
headers.removeHeaderNamed(HTTPConstants.HEADER_COOKIE);// Always remove cookies
// See https://bz.apache.org/bugzilla/show_bug.cgi?id=25430
// HEADER_AUTHORIZATION won't be removed, it will be used
// for creating Authorization Manager
// Remove additional headers
for(String hdr : HEADERS_TO_REMOVE){
headers.removeHeaderNamed(hdr);
}
}
if(result != null) // deliverSampler allows sampler to be null, but result must not be null
{
List<TestElement> children = new ArrayList<>();
if(captureHttpHeaders) {
children.add(headers);
}
if(samplerCreator != null) {
children.addAll(samplerCreator.createChildren(sampler, result));
}
target.deliverSampler(sampler,
children
.toArray(new TestElement[children.size()]),
result);
}
try {
clientSocket.close();
} catch (Exception e) {
log.error("{} Failed to close client socket", port, e);
}
if(sampler != null) {
sampler.threadFinished(); // Needed for HTTPSampler2
}
JMeterContextService.getContext().setRecording(false);
}
}