I'm calling a api serice that requires a http header with the hash value of the request body.
I'm trying to use a beanshell post processor in JMeter to automatically create the sha-256 hash of the request body. The hash value is right up until I introduce a line break in the request body (which is a pain as the JSON message spans several lines!)
I assume it's something to do with hidden characters however I can't work out what is going wrong! :(
When I compare the hash generated by JMeter to seperate Hash generator tools it is an exact match until there are line breaks, then JMeter is wrong.
Why is JMeter generating an incorrect hash when there are line breaks?
My code is:
[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;
import org.apache.jmeter.services.FileServer;
import javax.xml.bind.DatatypeConverter;
import java.security.*;
String body = sampler.getArguments().getArgument(0).getValue();
String hash = DigestUtils.sha256Hex(body);
log.info(hash);
What is your input data and what output do you expect?
Since JMeter 3.1 it is recommended to switch to JSR223 Test Elements and Groovy language so:
Given the following request body:
{
"foo": "bar"
}
And the next Groovy code to generate a SHA-256 hex string:
def sha256Hex = { input ->
java.security.MessageDigest.getInstance("SHA-256")
.digest(input.getBytes("UTF-8")).encodeHex().toString()
}
log.info(sha256Hex(sampler.getArguments().getArgument(0).getValue()))
I'm getting dbc67f71c921b5b7649481a5123d94dfa919748d2962889681d96438033c548f value which is basically the same I can see using https://hash.online-convert.com/sha256-generator generator.
Related
The "Payload" picture below shows 3 line items for GROUND_SERVICE and all the values such as SERVICE_TYPE_CODE, ORIG_ZIP, DEST_ZIP, UNITS_SHIPPED, START_DATE will have to be parameterized. I cannot always send request for 3 GROUND_SERVICE line items. I need to send random number of GROUND_SERVICE lines, in this case between 1 to 3. In reality I will have about 20 line items. How can I do that while parameterizing all the values within GROUND_SERVICE element?
Payload
EDITED QUESTION BELOW AFTER RECEIVING DMITRI'S SUGGESTION:
I think the suggested code allows me to send random number of GROUND_SERVICE blocks, and if so solves half of my problem. However, I cannot randomize the data elements such as ORIG_ZIP, UNITS_SHIPPED, etc. They have to be pulled from CSV file. How can I do that? Just to be clear, I made up these data elements to protect sensitive data. In reality the Request contains different kind of data elements with test data that go through a rule engine, and therefore I must pull actual data from CSV file.
Add JSR223 PreProcessor as a child of the HTTP Request sampler you want to parameterize
Put the following code into "Script" area:
import groovy.xml.MarkupBuilder
import org.apache.commons.lang3.RandomUtils
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy
def writer = new StringWriter()
def xml = new MarkupBuilder(writer)
static def getRandomGroundServices(MarkupBuilder xml) {
1.upto(RandomUtils.nextInt(1, 4), { number ->
xml.GROUND_SERVICES() {
GROUND_SERVICE() {
SERVICE_TYPE_CODE(number + "DAY")
ORIG_ZIP(RandomUtils.nextInt(11111, 99999))
UNITS_SHIPPED(RandomUtils.nextInt(1, 10))
START_DATE(new Date().plus(number).format('yyyy-MM-dd'))
}
}
})
};
getRandomGroundServices(xml)
vars.put('payload', writer.toString())
That's it, now you can refer the random payload as ${payload} where required:
Each time you run the request different number of GROUND_SERVICE elements will be sent to the backend with random UNITS_SHIPPED and ORIG_ZIP
References:
Groovy: Creating XML
Apache Groovy - Why and How You Should Use It
Problem with usage __base64Encode function to encode Random Variable.
I use Random Variable to generate unique email for user. (in each iteration of test scenario)
I want to use :
${__base64Encode(${randomvar})} which generate encoded ${randomvar}
Real example user defined variable 'babretr' defined below:
babretr=${__base64Encode(${randomMail}${timeStamp}#jmeter.soi:Kazek2017#)}
after base64 encode looks:
babretr=JHtyYW5kb21NYWlsfTIwMTcwNTE5MDg0MTI0NDcyWkBqbWV0ZXIuc29pOkthemVrMjAxN0A=
after base64 decode looks:
${randomMail}20170519084124472Z#jmeter.soi:Kazek2017#
Jmeter Random Variable ${randomMail} is not encoded.
With different variables problem does not exist.
You could add Beanshell PreProcessor on your sampler and put something like:
import java.util.Base64;
import org.apache.commons.lang3.RandomStringUtils;
String sufix = "#jmeter.soi:Kazek2017#";
String address = Base64.getEncoder().encodeToString(new String(
RandomStringUtils.random(10) + vars.get("timeStamp") + sufix).getBytes());
vars.put("encodedAddress", address);
After that, just use ${encodedAddress} in your sampler.
I am using Jmeter for performance testing and stuck at following point:
I am getting a JSON response from Webapi as follows:
PersonInfoList:
Person
[0]
{
id: 1
name: Steve
}
[1]
Person
{
id: 2
name: Mark
}
I need to get the ids based on the count of this JSON array and create a comma separated string as ("Expected value" = 1,2)
I know how to read a particular element using JSON Post processor or Regex processor but am unable to loop through the array and create a string as explained so that I can use this value in my next sampler request.
Please help me out with this: I am using Jmeter 3.0 and if this could be achieved without using external third party libs that would be great. Sorry for the JSON syntax above
Actually similar functionality comes with JSON Path PostProcessor which appeared in JMeter 3.0. In order to get all the values in a single variable configure JSON Path PostProcessor as follows:
Variable Names: anything meaningful, i.e. id
JSON Path Expressions: $..id or whatever you use to extract the ids
Match Numbers: -1
Compute concatenation var (suffix _ALL): check
As a result you'll get id_ALL variable which will contain all JSON Path expression matches (comma-separated)
More "universal" answer which will be applicable for any other extractor types and in fact will allow to concatenate any arbitrary JMeter Variables is using scripting (besides if you need this "expected value and parentheses)
In order to concatenate all variables which names start with "id" into a single string add Beanshell PostProcessor somewhere after JSON Path PostProcessor and put the following code into "Script" area
StringBuilder result = new StringBuilder();
result.append("(\"Expected value\" = ");
Iterator iterator = vars.getIterator();
while (iterator.hasNext()) {
Map.Entry e = (Map.Entry) iterator.next();
if (e.getKey().matches("id_(\\d+)")) {
result.append(e.getValue());
result.append(",");
}
}
result.append(")");
vars.put("expected_value", result.toString());
Above code will store the resulting string into ${expected value} JMeter Variable. See How to Use BeanShell: JMeter's Favorite Built-in Component article for more information regarding bypassing JMeter limitations using scripting and using JMeter and Java API from Beanshell test elements.
Demo:
Currently developing a script in jMeter, I need to retrieve x amount of values from a response then push those values into another HTTP request, here is the tricky part the response is a table which always changes (e.g. rows increase or decrease each time the test is run) so far I've created a Regex extractor which retrieves anything between the table now I need to create a beanshell post processor which retrieves the certain values from the variable retrieved by the Regex extractor and applies them to the HTTP request. I'm not to sure if this is the best way to do this so I am open to suggestions on doing this another way.
You need Beanshell PreProcessor applied to 2nd request, not PostProcessor applied to 1st request
I don't think that using Regular Expressions is a very good idea to parse HTML, I would suggest going for CSS/JQuery Extractor or XPath Extractor instead
Once you have required values in form of
var_1=foo
var_2=bar
var_MatchNr=2
You will be able to add these values to the 2nd HTTP Request like:
import java.util.Iterator;
import java.util.Map;
Iterator iter = vars.getIterator();
int counter = 1;
while (iter.hasNext())
{
Map.Entry e = (Map.Entry)iter.next();
if (e.getValue() != null)
{
if (e.getKey().toString().startsWith("var_") && e.getValue().toString().length() >0)
{
sampler.addArgument("param" + counter, e.getValue().toString());
counter++;
}
}
}
I made a test with JMeter and I made a regex which takes a ticketid from a response. That works when loop count = 1. But when loop count = 2, in next loop we have a new ticketid, but regex don't takes it and test fails. How make a regex which in every next loop takes a new ticketid that appears?
You will have to write java code using Beanshell Sampler to save extracted data to CSV file
Extract your data using Regex Extractor
See the sample code below to write your data to CSV file
import java.io.FileWriter;
import java.io.IOException;
String ID = vars.get("ticketid");
//Change the file path below
FileWriter writer = new FileWriter("F:\test_20140529.csv", true);
if (ID != "")
{
writer.append(ID);
writer.append('\n');
writer.flush();
}
writer.close();`
Use CSV Data Set Config, use "test_20140526.csv" created.
pass CSV data as parameters for the next request.
Hope this will help.