com.blazemeter.jmeter.http2.sampler.HTTP2Connection Maven / Gradle / Ivy
The newest version!
package com.blazemeter.jmeter.http2.sampler;
import org.apache.jmeter.protocol.http.control.CookieManager;
import org.apache.jmeter.protocol.http.control.Header;
import org.apache.jmeter.protocol.http.control.HeaderManager;
import org.apache.jmeter.protocol.http.util.HTTPConstants;
import org.apache.jmeter.testelement.property.CollectionProperty;
import org.apache.jmeter.testelement.property.JMeterProperty;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpURI;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.http.MetaData;
import org.eclipse.jetty.http2.api.Session;
import org.eclipse.jetty.http2.api.Stream;
import org.eclipse.jetty.http2.client.HTTP2Client;
import org.eclipse.jetty.http2.frames.DataFrame;
import org.eclipse.jetty.http2.frames.HeadersFrame;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.FuturePromise;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import java.net.InetSocketAddress;
import java.net.URL;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HTTP2Connection {
private static Logger LOG = LoggerFactory.getLogger(HTTP2Connection.class);
private String connectionId;
private Session session;
private HTTP2Client client;
private SslContextFactory sslContextFactory;
private Queue streamHandlers = new ConcurrentLinkedQueue<>();
public void setSession(Session session) {
this.session = session;
}
public HTTP2Connection(String connectionId, boolean isSSL) throws Exception {
this.session = null;
this.connectionId = connectionId;
this.client = new HTTP2Client();
this.sslContextFactory = null;
if (isSSL) {
this.sslContextFactory = new SslContextFactory(true);
}
this.client.addBean(sslContextFactory);
this.client.start();
}
public String getConnectionId() {
return connectionId;
}
public void connect(String hostname, int port) throws InterruptedException, ExecutionException, TimeoutException {
FuturePromise sessionFuture = new FuturePromise<>();
this.client.connect(this.sslContextFactory, new InetSocketAddress(hostname, port),
new Session.Listener.Adapter(), sessionFuture);
setSession(sessionFuture.get(10, TimeUnit.SECONDS));
}
public boolean isClosed() {
return this.session.isClosed();
}
private synchronized void sendMutExc(String method, HeadersFrame headersFrame, FuturePromise streamPromise,
HTTP2StreamHandler http2StreamHandler, RequestBody requestBody) throws Exception {
session.newStream(headersFrame, streamPromise, http2StreamHandler);
if (HTTPConstants.POST.equals(method)) {
Stream actualStream = streamPromise.get();
int streamID = actualStream.getId();
DataFrame data = new DataFrame(streamID, ByteBuffer.wrap(requestBody.getPayloadBytes()), true);
actualStream.data(data, Callback.NOOP);
}
}
public void send(String method, URL url, HeaderManager headerManager, CookieManager cookieManager,
RequestBody requestBody, HTTP2SampleResult sampleResult, int timeout) throws Exception {
HttpFields headers = buildHeaders(url, headerManager, cookieManager);
if (requestBody != null) {
headers.put(HTTPConstants.HEADER_CONTENT_LENGTH, Long.toString(requestBody.getPayloadBytes().length));
// Check if the header manager had a content type header
// This allows the user to specify his own content-type for a POST request
String contentTypeHeader = headers.get(HTTPConstants.HEADER_CONTENT_TYPE);
if (contentTypeHeader == null || contentTypeHeader.isEmpty()) {
headers.put(HTTPConstants.HEADER_CONTENT_TYPE, HTTPConstants.APPLICATION_X_WWW_FORM_URLENCODED);
}
sampleResult.setQueryString(requestBody.getPayload());
}
MetaData.Request metaData = null;
boolean endOfStream = true;
switch (method) {
case "GET":
metaData = new MetaData.Request("GET", new HttpURI(url.toString()), HttpVersion.HTTP_2,
headers);
break;
case "POST":
metaData = new MetaData.Request("POST", new HttpURI(url.toString()), HttpVersion.HTTP_2,
headers);
endOfStream = false;
break;
default:
break;
}
HeadersFrame headersFrame = new HeadersFrame(metaData, null, endOfStream);
// we do this replacement and remove final char to be consistent with jmeter HTTP request sampler
String headersString = headers.toString().replaceAll("\r\n", "\n");
sampleResult.setRequestHeaders(headersString.substring(0, headersString.length() - 1));
HTTP2StreamHandler http2StreamHandler = new HTTP2StreamHandler(this, headerManager, cookieManager,
sampleResult);
http2StreamHandler.setTimeout(timeout);
sampleResult.setCookies(headers.get(HTTPConstants.HEADER_COOKIE));
addStreamHandler(http2StreamHandler);
sampleResult.sampleStart();
sendMutExc(method, headersFrame, new FuturePromise<>(), http2StreamHandler, requestBody);
}
private HttpFields buildHeaders(URL url, HeaderManager headerManager, CookieManager cookieManager) {
HttpFields headers = new HttpFields();
if (headerManager != null) {
CollectionProperty headersProps = headerManager.getHeaders();
if (headersProps != null) {
for (JMeterProperty prop : headersProps) {
Header header = (Header) prop.getObjectValue();
String n = header.getName();
if(n.startsWith(":")){
LOG.warn("The specified pseudo header {} is not allowed "
+ "and will be ignored", n);
}
else if (!HTTPConstants.HEADER_CONTENT_LENGTH.equalsIgnoreCase(n)) {
String v = header.getValue();
v = v.replaceFirst(":\\d+$", ""); // remove any port
headers.put(n, v);
}
}
}
// TODO CacheManager
}
if (cookieManager != null) {
String cookieHeader = cookieManager.getCookieHeaderForURL(url);
if (cookieHeader != null) {
headers.put(HTTPConstants.HEADER_COOKIE, cookieHeader);
}
}
return headers;
}
public void addStreamHandler(HTTP2StreamHandler http2StreamHandler) {
streamHandlers.add(http2StreamHandler);
}
public void disconnect() throws Exception {
client.stop();
}
public List awaitResponses() throws InterruptedException {
List results = new ArrayList<>();
while (!streamHandlers.isEmpty()) {
HTTP2StreamHandler h = streamHandlers.poll();
results.add(h.getHTTP2SampleResult());
try {
// wait to receive all the response of the request
h.getCompletedFuture().get(h.getTimeout(), TimeUnit.MILLISECONDS);
} catch (ExecutionException | TimeoutException e) {
HTTP2SampleResult sample = h.getHTTP2SampleResult();
sample.setErrorResult("Error while await for response", e);
sample.setResponseHeaders("");
}
}
return results;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy