All Downloads are FREE. Search and download functionalities are using the official Maven repository.

us.abstracta.jmeter.javadsl.http.DslBaseHttpSampler Maven / Gradle / Ivy

Go to download

Simple API to run JMeter performance tests in an VCS and programmers friendly way.

There is a newer version: 028
Show newest version
package us.abstracta.jmeter.javadsl.http;

import static us.abstracta.jmeter.javadsl.JmeterDsl.jsr223PreProcessor;

import java.lang.reflect.Method;
import java.util.List;
import java.util.function.Function;
import org.apache.http.entity.ContentType;
import org.apache.jmeter.gui.JMeterGUIComponent;
import org.apache.jmeter.protocol.http.control.Header;
import org.apache.jmeter.protocol.http.control.HeaderManager;
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerBase;
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy;
import org.apache.jmeter.protocol.http.util.HTTPConstants;
import org.apache.jmeter.testelement.TestElement;
import org.apache.jorphan.collections.HashTree;
import us.abstracta.jmeter.javadsl.JmeterDsl;
import us.abstracta.jmeter.javadsl.codegeneration.MethodCall;
import us.abstracta.jmeter.javadsl.codegeneration.MethodCallContext;
import us.abstracta.jmeter.javadsl.codegeneration.MethodParam.IntParam;
import us.abstracta.jmeter.javadsl.codegeneration.MethodParam.StringParam;
import us.abstracta.jmeter.javadsl.codegeneration.SingleGuiClassCallBuilder;
import us.abstracta.jmeter.javadsl.codegeneration.TestElementParamBuilder;
import us.abstracta.jmeter.javadsl.core.BuildTreeContext;
import us.abstracta.jmeter.javadsl.core.preprocessors.DslJsr223PreProcessor.PreProcessorScript;
import us.abstracta.jmeter.javadsl.core.preprocessors.DslJsr223PreProcessor.PreProcessorVars;
import us.abstracta.jmeter.javadsl.core.samplers.BaseSampler;

/**
 * Abstracts common logic used by HTTP based samplers.
 *
 * @param  type of the sampler used to provide proper fluent API methods.
 * @since 0.52
 */
public abstract class DslBaseHttpSampler> extends BaseSampler {

  protected String path;
  protected final HttpHeaders headers = new HttpHeaders();
  private String protocol;
  private String host;
  private String port;

  public DslBaseHttpSampler(String name, String url, Class guiClass) {
    super(name, guiClass);
    if (url == null) {
      return;
    }
    JmeterUrl parsedUrl = JmeterUrl.valueOf(url);
    protocol = parsedUrl.protocol();
    host = parsedUrl.host();
    port = parsedUrl.port();
    path = parsedUrl.path();
  }

  /**
   * Specifies the HTTP Sampler protocol to be used in the HTTP request generated by the sampler.
   * 

* You can specify entire url when creating a sampler, but this method allows you to override the * protocol if needed. For example, if you have defaults element with url and just need in one * sampler to have a different protocol. *

* In general prefer using java variables and methods, to get shorter and more maintainable code, * and use this method sparingly. * * @param protocol contains protocol value to be used (e.g.: http, https, etc). * @return the altered sampler to allow for fluent API usage. */ public T protocol(String protocol) { this.protocol = protocol; return (T) this; } /** * Specifies the server host (domain) to be used in the HTTP request generated by the sampler. *

* You can specify entire url when creating a sampler, but this method allows you to override the * host if needed. For example, if you have defaults element with url and just need in one sampler * to have a different host. *

* In general prefer using java variables and methods, to get shorter and more maintainable code, * and use this method sparingly. * * @param host contains server name without protocol (no http/https) and path. * @return the altered sampler to allow for fluent API usage. */ public T host(String host) { this.host = host; return (T) this; } /** * Specifies the HTTP Sampler port to be used in the HTTP request generated by the sampler. *

* You can specify entire url when creating a sampler, but this method allows you to override the * port if needed. For example, if you have defaults element with url and just need in one sampler * to have a different port. *

* In general prefer using java variables and methods, to get shorter and more maintainable code, * and use this method sparingly. * * @param port contains port value to be used. * @return the altered sampler to allow for fluent API usage. */ public T port(int port) { this.port = String.valueOf(port); return (T) this; } /** * Specifies an HTTP header to be sent by the sampler. *

* To specify multiple headers just invoke this method several times with the different header * names and values. * * @param name of the HTTP header. * @param value of the HTTP header. * @return the altered sampler to allow for fluent API usage. */ public T header(String name, String value) { headers.header(name, value); return (T) this; } /** * Same as {@link #header(String, String)} but allows using dynamically calculated HTTP header * value. *

* This method is just an abstraction that uses a JMeter variable as HTTP header value and * calculates the variable with a jsr223PreProcessor. *

* WARNING: As this method internally uses * {@link JmeterDsl#jsr223PreProcessor(PreProcessorScript)}, same limitations and considerations * apply. Check its documentation. To avoid such limitations you may use {@link #header(String, * String)} with a JMeter variable instead, and dynamically set the variable with {@link * JmeterDsl#jsr223PreProcessor(String)}. * * @param name of the HTTP header. * @param valueSupplier builds the header value. * @return the altered sampler to allow for fluent API usage. */ public T header(String name, Function valueSupplier) { String variableNamePrefix = "PRE_PROCESSOR_HEADER~"; headers.header(name, "${" + variableNamePrefix + name + "}"); return children( jsr223PreProcessor(s -> s.vars.put(variableNamePrefix + name, valueSupplier.apply(s))) ); } /** * Allows to easily specify the Content-Type HTTP header to be used by the sampler. * * @param contentType value to send as Content-Type header. * @return the altered sampler to allow for fluent API usage. */ public T contentType(ContentType contentType) { headers.contentType(contentType); return (T) this; } @Override protected TestElement buildTestElement() { HTTPSamplerProxy ret = new HTTPSamplerProxy(); if (protocol != null) { ret.setProtocol(protocol); } if (host != null) { ret.setDomain(host); } if (port != null) { /* need to use this method instead of setPort since we want to be able to set expressions on port (like ${port}). */ ret.setProperty(HTTPSamplerBase.PORT, port); } if (path != null) { ret.setPath(path); } return configureHttpTestElement(ret); } protected abstract HTTPSamplerProxy configureHttpTestElement(HTTPSamplerProxy elem); @Override public HashTree buildTreeUnder(HashTree parent, BuildTreeContext context) { HashTree ret = super.buildTreeUnder(parent, context); if (!headers.isEmpty()) { context.buildChild(headers, ret); } new DslCookieManager().registerDependency(context); new DslCacheManager().registerDependency(context); return ret; } protected abstract static class BaseHttpSamplerCodeBuilder extends SingleGuiClassCallBuilder { private final String defaultName; protected BaseHttpSamplerCodeBuilder(String defaultName, Class guiClass, List builderMethods) { super(guiClass, builderMethods); this.defaultName = defaultName; } @Override protected MethodCall buildMethodCall(MethodCallContext context) { HTTPSamplerProxy testElement = (HTTPSamplerProxy) context.getTestElement(); TestElementParamBuilder paramBuilder = new TestElementParamBuilder(testElement); StringParam name = paramBuilder.nameParam(defaultName); StringParam protocol = paramBuilder.stringParam(HTTPSamplerBase.PROTOCOL); StringParam domain = paramBuilder.stringParam(HTTPSamplerBase.DOMAIN); IntParam port = paramBuilder.intParam(HTTPSamplerBase.PORT); StringParam path = paramBuilder.stringParam(HTTPSamplerBase.PATH, "/"); StringParam url = buildUrlParam(protocol, domain, port, path); MethodCall ret = buildBaseHttpMethodCall(name, url, paramBuilder); context.findBuilder(DslCacheManager.CodeBuilder.class) .registerDependency(context, ret); context.findBuilder(DslCookieManager.CodeBuilder.class) .registerDependency(context, ret); if (url == path) { ret.chain("protocol", protocol) .chain("host", domain) .chain("port", port); } buildRequestCall(ret, testElement, context); setAdditionalOptions(ret, paramBuilder); return ret; } protected abstract MethodCall buildBaseHttpMethodCall(StringParam name, StringParam url, TestElementParamBuilder paramBuilder); private StringParam buildUrlParam(StringParam protocol, StringParam domain, IntParam port, StringParam path) { if (!domain.isDefault()) { return new StringParam( (protocol.isDefault() ? "http" : protocol.getValue()) + "://" + domain.getValue() + (port.isDefault() ? "" : ":" + port.getValue()) + (path.isDefault() ? "" : path.getValue())); } else { return path; } } protected abstract void buildRequestCall(MethodCall ret, HTTPSamplerProxy testElement, MethodCallContext context); protected String removeContentTypeHeader(MethodCallContext context) { if (context == null) { return null; } String headerName = HTTPConstants.HEADER_CONTENT_TYPE; HeaderManager headers = (HeaderManager) context.getTestElement(); Header header = headers.getFirstHeaderNamed(headerName); headers.removeHeaderNamed(headerName); return header == null ? null : header.getValue(); } protected void chainContentType(MethodCall ret, String contentType) { ret.chain("contentType", new ContentTypeParam(contentType)); } protected void chainHeaders(MethodCall ret, MethodCallContext headers) { if (headers != null) { ret.reChain(headers.buildMethodCall()); } } protected abstract void setAdditionalOptions(MethodCall ret, TestElementParamBuilder paramBuilder); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy