How to upload the image in the API request through the groovy - jmeter

In my API request, with the request payload the complete image is also getting loaded. Is there any way I can script it through JMeter using Groovy?
UI Call where I am uploading image:
enter image description here
Main Request POST Call: enter image description here
Image in the request payload: enter image description here
Can it be done through groovy on JMeter.

Out of interest, why do you want to do this in Groovy? I believe using normal HTTP Request sampler would be much easier, moreover you will be able to even record the request(s) using HTTP(S) Test Script Recorder, this way you will get more metrics and won't need to handle the request and response.
If you still want to do this in Groovy I believe the best option would be calling relevant Apache HttpComponents functions, example code:
import org.apache.http.client.methods.HttpPost
import org.apache.http.entity.ContentType
import org.apache.http.entity.mime.HttpMultipartMode
import org.apache.http.entity.mime.MultipartEntityBuilder
import org.apache.http.impl.client.HttpClientBuilder
def imageFileName = "/path/to/your/image.png"
def post = new HttpPost("http://your-server");
def file = new File(imageFileName);
def builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.addBinaryBody("file", file, ContentType.DEFAULT_BINARY, imageFileName);
def entity = builder.build();
post.setEntity(entity);
def response = HttpClientBuilder.create().build().execute(post)
//do what you need with the response here
More information: How to Send Groovy HTTP and HTTPS Requests

Related

Retrieve the particular entity from the request through a web request sampler

I am new to JMeter, I want to retrieve from the request sample (it is on websocket-request-response-sampler).
The request body:
ws://localhost:8080/connect
{
"uid": "JBM1",
"agent_name": "performance_test_1"
}
I want to retrieve the agent name. Tried with normal JSSR223 post processer, not working. Any help ?
If you're tried with "normal" JSR223 Post Processor you're supposed to share your "normal" code you used and the "normal" jmeter.log file contents
I believe "normal" code should normally look like:
new groovy.json.JsonSlurper().parseText(sampler.getPropertyAsString('requestData'))[0].get('agent_name')
Demo:
More information on Groovy scripting in JMeter: Apache Groovy - Why and How You Should Use It
I have not done anything extra then #Dmitri rather few modifications, but please try it.
def requestBody = sampler.getPropertyAsString('requestData');
def jsonFormat = new groovy.json.JsonSlurper().parseText(requestBody)
def key = 'agent_name'
def agentName= jsonFormat."$key"
log.info("AgentName"+ agentName)
vars.put('AgentNameFurther',agentName)

Jmeter 440 error code. How can I resolve this error?

I am working with Jmeter and Blazemeter in a login script for a web made with Genexus.
The problem that I am having is in the POST.
Whenever I try to make a POST http petition, Jmeter throws the next thing:
As you can see, in the response body, I am having a 440 http error code. This is a login Time-out which means the client's session has expired and must log in again. I used to have a 403 error code but now, after doing some arrangements, I have 440. Do you have any suggestions on how to resolve this?
First, I'm not an expert on Genexus. All my findings are from a black-box point of view.
Genexus Security
I found that Genexus requires at least two things to authenticate on Web Application (I tested only Java and .Net generated apps).
The GXState parameter. This param is sent in post request, and from my understanding works as "Synchronizer token pattern", see more info on Cross-site request forgery. We need to send this param on every post request.
The gxajaxEvt parameter. This is very specific to Genexus Apps. In the documentation mentions this parameter is send encrypted in the URL, and this behavior is managed by the "Javascript debug mode property":
# Javascript Debug Mode: Yes
http://{server}:{port}/{webappname}/servlet/com.{kbname}.{objectname}?gxfullajaxEvt,gx-no-cache=1442811265833
# Javascript Debug Mode: No (default value)
http://{server}:{port}/{webappname}/servlet/com.{kbname}.{objectname}?64df96a2d9b8480aed416e470dae529e,gx-no-cache=1442811265833
JMeter Script
So, to get the GXState, we can use the Regular Expression Extractor:
Name of created variable: GXState
Regular expression: name="GXState" value='(.*?)'
Template: $1$
Match No.: 1
Default Value: NOT_FOUND
The GXState is a JSON, object, from it we can extract the GX_AJAX_KEY to encrypt gxajaxEvt string. Note that, I found the GX_AJAX_KEY is the key used to encrypt in this case, but some others could apply. We can debug this using Browser Web Console, with this:
gx.sec.encrypt("gxajaxEvt")
We'll see something like this:
"8722e2ea52fd44f599d35d1534485d8e206d507a46070a816ca7fcdbe812b0ad"
As we can found, all the client encryption code is in the gxgral.js file. Genexus uses the Rijndael algortihm (Sub set of AES) with block size of 128 bits.
To emulate this client behavior in the JMeter Script we can use the "JSR 233 sampler". A way to get the Rijndael results is use the Bouncy Castle library. We need to add this jar (bouncycastle:bcprov-jdk15to18:1.68) to the JMeter's lib folder to use it.
Our code script will be something like this (Language Groovy 3.0.5/Groovy Scripting Engine 2.0):
import com.jayway.jsonpath.JsonPath
import java.nio.charset.StandardCharsets
import java.util.Arrays
import org.bouncycastle.crypto.BufferedBlockCipher
import org.bouncycastle.crypto.InvalidCipherTextException
import org.bouncycastle.crypto.engines.RijndaelEngine
import org.bouncycastle.crypto.params.KeyParameter
import org.bouncycastle.util.encoders.Hex
import org.apache.jmeter.threads.JMeterContextService
import org.apache.jmeter.threads.JMeterContext
import org.apache.jmeter.threads.JMeterVariables
String gxState = vars.get('GXState')
String gxAjaxKey = JsonPath.read(gxState,'$.GX_AJAX_KEY')
byte[] input = Arrays.copyOf('gxajaxEvt'.getBytes(StandardCharsets.UTF_8), 16)
RijndaelEngine engine = new RijndaelEngine(128)
KeyParameter key = new KeyParameter(Hex.decode(gxAjaxKey))
BufferedBlockCipher cipher = new BufferedBlockCipher(engine)
cipher.init(true, key)
byte[] out = new byte[16]
int length = cipher.processBytes(input, 0, 16, out, 0)
cipher.doFinal(out, length)
String encryptedOutput= Hex.toHexString(out)
log.info 'gx.sec.encrypt("gxajaxEvt")='+encryptedOutput
String gxNoCache = String.valueOf(System.currentTimeMillis())
log.info 'gx-no-cache='+gxNoCache
vars.put('gxajaxEvt', encryptedOutput)
vars.put('gxNoCache', gxNoCache)
The script work like this:
First, We get the previos GXState variable extracted.
Second, Using JSON Path (Already available in JMeter 5.4.1) extract the GX_AJAX_KEY property.
Third, We apply the Rijndael algorithm over the gxajaxEvt using the GX_AJAX_KEY as a key.
We also create the gx-no-cache to handle the cache.
With these variables we can send the next request successfully:
We can found this sample JMeter script available here.
For complex scripts, please refer to this guide (Requires GXTest)
In case we get this exception in JMeter ( java.util.zip.ZipException: Not in GZIP format) please refer this answer too.
Any HTTP Status 4xx is a client error, to wit you're sending an incorrect request.
If custom 440 http status code means "session has expired" my expectation is that you have a recorded hard-coded session ID somewhere in your request parameters or headers
You should carefully inspect previous response(s) and look for something which appears to be a session id, once you find it - extract it using a suitable JMeter's Post-Processor and replace hard-coded session ID with the appropriate JMeter Variable. The process is known as correlation

Getting  character in JMeter Response

I am calling a login API from JMeter which return result in json format. For this API call I am getting expected result however the json response contains  character. In the request I have added, DataType:json and Content-Type: application/json;charset=utf-8.
Any advice.
Output Json Response
This is UTF-8 Byte Order Mark, your server responds this way so you might want to raise an issue against your application if this is not expected.
If your application functions as designed you can remove the BOM from the response using i.e. JSR223 PostProcessor and Groovy language, the relevant code would be something like:
def BOM = '\uFEFF'
def responseData = prev.getResponseDataAsString()
if (responseData.startsWith(BOM)) {
responseData = responseData.substring(1)
}
prev.setResponseData(responseData.getBytes('UTF-8'))
Check out Apache Groovy - Why and How You Should Use It for more information on Groovy scripting in JMeter

how to include parameters in label of Jmeter summary report

I can successfully create a summary report in jmeter but in the label column i need the full get request along with parameters passed.I am not getting the parameters passed in the url.
You can get it automatically populated with the help of Beanshell scripting.
Example:
Add Beanshell PostProcessor as a child of HTTP Request
Put the following code into the PostProcessor's "Script" area:
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy;
import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.testelement.property.PropertyIterator;
import org.apache.jmeter.testelement.property.JMeterProperty;
HTTPSamplerProxy sampler = (HTTPSamplerProxy) ctx.getCurrentSampler();
StringBuilder builder = new StringBuilder();
builder.append(sampler.getUrl());
Arguments args = sampler.getArguments();
PropertyIterator iter = args.iterator();
while (iter.hasNext()) {
builder.append (iter.next().getStringValue());
}
prev.setSampleLabel(builder.toString());
Run your test.
The code fetches URL and all parameters along with their values and updates parent sampler name with these values:
As you can see HTTP Request became http://example.com/foo=bar
You can place the PostProcessor at the same level as HTTP Request samplers to avoid copy-pasting it multiple times or use i.e. Beanshell Listener or Beanshell Assertion instead.
See How to use BeanShell: JMeter's favorite built-in component guide for comprehensive information on using scripting in JMeter and to learn what all these things like ctx and prev mean.

JMeter SHA256 in request header

I am load testing an API using Jmeter. The Header of the request has an authentication request which needs me to Base64 the url+Nonce+Unix timestamp and SHA256 the resultant value with a secret key.
The above needs to be passed in header along with Nonce and timestamp.
For the above scenario should I create a custom function or use any preprocessor ?
You can do it via Beanshell PreProcessor as follows:
Add a HTTP Header Manager as a child of your HTTP Request sampler
Add aforementioned Beanshell PreProcessor the same way
Put the following code into the PreProcessor's "Script" area:
import org.apache.commons.httpclient.auth.DigestScheme; // necessary imports
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.jmeter.protocol.http.control.Header;
String url = sampler.getUrl().toString(); // get URL
String nonce = DigestScheme.createCnonce(); // get nonce
long timestamp = System.currentTimeMillis() / 1000L;
String combined = url + nonce + timestamp; // put everything together
byte[] base64 = Base64.encodeBase64(combined.getBytes()); // encode as Base64
String headerValue = DigestUtils.sha256Hex(base64); // encode SHA256
sampler.getHeaderManager().add(new Header("headerName", headerValue)); // add generated header to request
sampler here is a shorthand reference to parent HTTP Request Sampler class which I believe is HTTPSamplerProxy so its methods are used to get URL and add generated header value.
methods to generate MD5 hash and SHA256 hex are from Apache Commons libraries which are widely used under JMeter's hood.
See How to use BeanShell: JMeter's favorite built-in component guide for more information on using Beanshell scripting in JMeter tests.
Your best bet is to use a BSF Pre-Processor in JavaScript mode to do everything the client normally would. You'll have to take the client JS and modify it to work without FORM data.
You can build the entire header in JS exactly like a client would. BSF Pre-Processor allows you to access jmeter run-time variables, so you would create a new one to store the SHA256 hash value, and use that in a HTTP Header Manager of the sample that needs the authorization.
-Addled
Downloaded eclipse.
Wrote a custom jmeter package.
Exported it as a .jar from eclipse to jmeter lib/ext folder.
Called the package function in beanshell sampler
Thanks for your answers
#dmitrit's answer is helpful but I needed to do some tweaks to the code to get it to work. Here is what I did:
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
String apiKey = vars.get("ApiKey");
String apiSecret = vars.get("ApiSecret");
long timestamp = System.currentTimeMillis() / 1000L;
String combined = apiKey + apiSecret + timestamp;
String generatedSignature = DigestUtils.sha256Hex(combined);
vars.put("GeneratedSignature", generatedSignature);
Note the main differences are:
Most important: DigestUtils.sha256Hex takes a String instead of a byte array. Converting first to bytes screwed up the hash, I think due to padding.
I added the resulting value to vars so it can be used later in Jmeter in the usual way (${GeneratedSignature}).
ApiKey and ApiSecret are defined elsewhere in a Jmeter User Defined Variables element.
With this I was able to make the following work with Mashery in accordance with their authentication instructions posted here.

Resources