Search code examples
jmeterbrotli

How to use Brotli in JMeter?


I am setting up a load test in which I need to send a compressed brotli csv file to the backend in the body of the request.

I tried to add the compressed data that comes from the frontend directly to the body of the request. Compress the data in python and add it to the body of the request. Insert uncompressed data into request body and add Content-Encoding: br header. Nothing worked, server responded, wrong compressed data.

Is there any way to send pre-compressed data to jmeter/compress in jmeter itself using brotli?


Solution

  • Body may be compressed using jmeter preprocessors. This has an advantage, that you have your files in plain text readable and editable format - it gets compressed, when sending request. See also, how to gzip request body

    As for brotli compression, 3rd party library should be used (no default brotli support in java as opposed to gzip). So first you need to add brotli lib to jmeter:

    mvn org.apache.maven.plugins:maven-dependency-plugin:2.1:get \
    -DrepoUrl=http://download.java.net/maven/2/ \
    -Dartifact=com.nixxcode.jvmbrotli:jvmbrotli:0.2.0
    
    mvn org.apache.maven.plugins:maven-dependency-plugin:2.1:get \
    -DrepoUrl=http://download.java.net/maven/2/ \
    -Dartifact=com.nixxcode.jvmbrotli:jvmbrotli-linux-x86-amd64:0.2.0
    
    cp ~/.m2/repository/com/nixxcode/jvmbrotli/jvmbrotli-linux-x86-amd64/0.2.0/jvmbrotli-linux-x86-amd64-0.2.0.jar  $jmeter_home/lib/
    cp ~/.m2/repository/com/nixxcode/jvmbrotli/jvmbrotli/0.2.0/jvmbrotli-0.2.0.jar $jmeter_home/lib/
    

    As you can see, I used com.nixxcode.jvmbrotli:jvmbrotli:0.2.0 lib. This lib doesn't implement compression logic, it relies on JNI and compression logic in C, that's why it has platform-dependent part in a separate jar. Pick that one right.

    Setup groovy jmeter preprocessor, and put brotli body compression code in:

    import com.nixxcode.jvmbrotli.enc.BrotliOutputStream;
    import com.nixxcode.jvmbrotli.enc.Encoder;
    import com.nixxcode.jvmbrotli.common.BrotliLoader;
    
    
    String bodyString = sampler.getArguments().getArgument(0).getValue();
    byte[] bodyBytes = bodyString.getBytes();
    
    log.info("Attempt to load brotli: ${BrotliLoader.isBrotliAvailable()}");
    ByteArrayOutputStream compressedBodyBytes = new ByteArrayOutputStream(bodyBytes.length);
    OutputStream brotliOutput = new BrotliOutputStream(compressedBodyBytes, new Encoder.Parameters().setQuality(6).setWindow(22));
    brotliOutput.write(bodyBytes);
    brotliOutput.close();
    
    sampler.getArguments().getArgument(0).setValue(compressedBodyBytes.toString(0));
    

    It will get your request body, compress it and substitute on the fly so the request will be brotli-compressed.

    If you really want to use pre-compressed data, see how to send byte array in jmeter.