Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.blazemeter.jmeter.http2.core;

import org.apache.commons.lang3.StringUtils;
import org.apache.jmeter.protocol.http.util.HTTPConstants;
import org.apache.jmeter.util.JMeterUtils;
import org.eclipse.jetty.client.Request;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeader;
Expand All @@ -16,6 +18,11 @@ final class JmeterRequestHeadersSupport {

static final String ATTR_USE_KEEPALIVE = "bzm.useKeepAlive";

static final String DEFAULT_USER_AGENT_PROPERTY =
"httpclient4.default_user_agent_disabled";

private static final String DEFAULT_USER_AGENT = buildDefaultUserAgent();

private JmeterRequestHeadersSupport() {
}

Expand All @@ -28,8 +35,7 @@ static void prepareFromSampler(Request request, boolean useKeepAlive) {
}
request.attribute(ATTR_USE_KEEPALIVE, useKeepAlive);
applyConnectionHeader(request, useKeepAlive);
// TODO: HC4 sends explicit empty User-Agent when none is configured (disableDefaultUserAgent).
// prepareEmptyUserAgentHeader(request);
applyDefaultUserAgentHeader(request);
}

/**
Expand All @@ -54,7 +60,6 @@ static HttpFields headersForSampleResult(Request request) {
}
HttpFields.Mutable merged = HttpFields.build(request.getHeaders());
restoreConnectionHeaderForSample(request, merged);
// restoreEmptyUserAgentForSample(request, merged);
return merged;
}

Expand All @@ -73,6 +78,39 @@ private static void applyConnectionHeader(Request request, boolean useKeepAlive)
}
}


/**
* Matches {@code HTTPHC4Impl}: when no {@code User-Agent} is configured, send a plugin default
* unless {@code httpclient4.default_user_agent_disabled=true}.
*/
private static void applyDefaultUserAgentHeader(Request request) {
if (isDefaultUserAgentDisabled()) {
return;
}
HttpFields.Mutable mutableHeaders = mutableHeaders(request);
if (mutableHeaders == null || mutableHeaders.contains(HttpHeader.USER_AGENT)) {
return;
}
mutableHeaders.put(HttpHeader.USER_AGENT, DEFAULT_USER_AGENT);
}

static boolean isDefaultUserAgentDisabled() {
return JMeterUtils.getPropDefault(DEFAULT_USER_AGENT_PROPERTY, false);
}

static String defaultUserAgent() {
return DEFAULT_USER_AGENT;
}

private static String buildDefaultUserAgent() {
Package pkg = JmeterRequestHeadersSupport.class.getPackage();
String version = pkg != null ? pkg.getImplementationVersion() : null;
if (StringUtils.isBlank(version)) {
return "BlazeMeter HTTP";
}
return "BlazeMeter HTTP/" + version;
}

private static void restoreConnectionHeaderForSample(
Request request, HttpFields.Mutable headers) {
Object useKeepAlive = request.getAttributes().get(ATTR_USE_KEEPALIVE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,28 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;

import com.blazemeter.jmeter.http2.HTTP2TestBase;
import java.util.HashMap;
import java.util.Map;
import org.apache.jmeter.protocol.http.util.HTTPConstants;
import org.apache.jmeter.util.JMeterUtils;
import org.eclipse.jetty.client.Request;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpVersion;
import org.junit.After;
import org.junit.Test;
import org.mockito.Mockito;

public class JmeterRequestHeadersSupportTest {
public class JmeterRequestHeadersSupportTest extends HTTP2TestBase {

private static final String UA_DISABLED_PROP =
JmeterRequestHeadersSupport.DEFAULT_USER_AGENT_PROPERTY;

@After
public void clearUserAgentProperty() {
JMeterUtils.getJMeterProperties().remove(UA_DISABLED_PROP);
}

private static Request mockRequest(HttpFields.Mutable headers) {
Map<String, Object> attributes = new HashMap<>();
Expand Down Expand Up @@ -74,4 +85,50 @@ public void prepareFromSamplerDoesNotOverrideExplicitConnectionHeader() {

assertThat(headers.get(HttpHeader.CONNECTION)).isEqualTo("Upgrade");
}
}

@Test
public void prepareFromSamplerAddsDefaultUserAgentWhenMissing() {
HttpFields.Mutable headers = HttpFields.build();
Request request = mockRequest(headers);

JmeterRequestHeadersSupport.prepareFromSampler(request, true);

assertThat(headers.get(HttpHeader.USER_AGENT))
.isEqualTo(JmeterRequestHeadersSupport.defaultUserAgent());
assertThat(headers.get(HttpHeader.USER_AGENT)).startsWith("BlazeMeter HTTP");
}

@Test
public void prepareFromSamplerDoesNotOverrideConfiguredUserAgent() {
HttpFields.Mutable headers = HttpFields.build()
.add(HttpHeader.USER_AGENT, "CustomAgent/1.0");
Request request = mockRequest(headers);

JmeterRequestHeadersSupport.prepareFromSampler(request, true);

assertThat(headers.get(HttpHeader.USER_AGENT)).isEqualTo("CustomAgent/1.0");
}

@Test
public void prepareFromSamplerKeepsEmptyUserAgentFromHeaderManager() {
HttpFields.Mutable headers = HttpFields.build()
.add(HttpHeader.USER_AGENT, "");
Request request = mockRequest(headers);

JmeterRequestHeadersSupport.prepareFromSampler(request, true);

assertThat(headers.contains(HttpHeader.USER_AGENT)).isTrue();
assertThat(headers.get(HttpHeader.USER_AGENT)).isEmpty();
}

@Test
public void prepareFromSamplerOmitsDefaultUserAgentWhenPropertyDisabled() {
JMeterUtils.setProperty(UA_DISABLED_PROP, "true");
HttpFields.Mutable headers = HttpFields.build();
Request request = mockRequest(headers);

JmeterRequestHeadersSupport.prepareFromSampler(request, true);

assertThat(headers.contains(HttpHeader.USER_AGENT)).isFalse();
}
}