how can I encode JWT with jmeter - jmeter

this is my payload
field1=valueField1&field2=valueField2&request=jwtEncodedRequest
Where jwtEncodedRequest is indeed a request encoded via jwt.
currently I'm using jwt.io to create an encoded request.
is it possible automatize this with jmeter?

Yes you can:
Use a JSR223 PreProcessor with Groovy
Compute token using this java library
Add the above library to jmeter/lib folder

Add Apache Ivy jar to JMeter Classpath
Restart JMeter to pick the .jar up
Add JSR223 Sampler to your Test Plan
Put the following code to "Script" area:
#Grab(group='io.jsonwebtoken', module='jjwt', version='0.9.1')
import io.jsonwebtoken.*
import java.security.PrivateKey
import java.util.Base64
import java.util.Base64.Decoder
import java.nio.charset.StandardCharsets
import java.security.interfaces.ECPrivateKey
import java.security.KeyFactory
import java.security.NoSuchAlgorithmException
import java.security.spec.PKCS8EncodedKeySpec
// Generating Tokens for API Requests
// https://developer.apple.com/documentation/appstoreconnectapi/generating_tokens_for_api_requests
def exp = (System.currentTimeMillis() / 1000 + 1200).intValue()
//20 minutes from now
//JWT Payload (update with your Issuer ID)
String jsonString = """{"iss":"57246542-96fe-1a63-e053-0824d011072a","exp":${exp},"aud":"appstoreconnect-v1"}""";
//Content of the AuthKey_2X9R4HXF34.p8
/*
-----BEGIN PRIVATE KEY-----
MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQg74+aaeYnqEIewDn8
Xh0rQXaQqAHSLGDyL9fV0p1hhxGgCgYIKoZIzj0DAQehRANCHOTEUjCMi4Vt7JGZ
jsRP1zF765oerCqfvHZYGqSeJl8AmK0awchcqAaMlw7hROoA2MToqx+llo2p9lZC
QYbeerau
-----END PRIVATE KEY-----
*/
//Key concatenated in a single line
//You better not hard code this key
def base64EncodedPrivateKey = "MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQg74+aaeYnqEIewDn8Xh0rQXaQqAHSLGDyL9fV0p1hhxGgCgYIKoZIzj0DAQehRANCHOTEUjCMi4Vt7JGZjsRP1zF765oerCqfvHZYGqSeJl8AmK0awchcqAaMlw7hROoA2MToqx+llo2p9lZCQYbeerau"
ECPrivateKey signingKey
Base64.Decoder dec= Base64.getDecoder();
keyBytes = dec.decode(base64EncodedPrivateKey.getBytes(StandardCharsets.US_ASCII));
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("EC");
signingKey = keyFactory.generatePrivate(keySpec);
//Notice you don't need to encode the header nor the payload
String jwtToken = Jwts.builder()
//JWT Header
.setHeaderParam("typ","JWT")
.setHeaderParam("alg","ES256")
.setHeaderParam("kid","2X9R4HXF34") //UPDATE with your Key Identifier
.setPayload(jsonString)
.signWith(SignatureAlgorithm.ES256, signingKey)
.compact();
log.info(jwtToken)
You should see JWT token printed to jmeter.log file:
More information:
JSON Web Token Quickstart
Apache Groovy - Why and How You Should Use It

Related

How to pass a value/keyword/argument on search box of a website while creating Jmeter Script from the API using Java?

I already created a Jmeter Script from API using Java.
I want to emulate the action where we search a value/keyword/argument in a search box of an eCommerce website.
The below script consists of the following samplers:
Load Url(Invoke the sample ecommerce URL)
Login(Used AuthManager to use Login Credentials)
Search(Search a value/keyword/argument on the search box of the sample website)
Here is my code snippet:
package com.blazemeter.demo;
import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.config.gui.ArgumentsPanel;
import org.apache.jmeter.control.LoopController;
import org.apache.jmeter.control.gui.LoopControlPanel;
import org.apache.jmeter.control.gui.TestPlanGui;
import org.apache.jmeter.engine.StandardJMeterEngine;
import org.apache.jmeter.protocol.http.control.AuthManager;
import org.apache.jmeter.protocol.http.control.Authorization;
import org.apache.jmeter.protocol.http.control.gui.HttpTestSampleGui;
import org.apache.jmeter.protocol.http.gui.AuthPanel;
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy;
import org.apache.jmeter.reporters.ResultCollector;
import org.apache.jmeter.reporters.Summariser;
import org.apache.jmeter.save.SaveService;
import org.apache.jmeter.testelement.TestElement;
import org.apache.jmeter.testelement.TestPlan;
import org.apache.jmeter.threads.ThreadGroup;
import org.apache.jmeter.threads.gui.ThreadGroupGui;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jorphan.collections.HashTree;
import java.io.FileOutputStream;
public class JMeterFromAPI {
public static void main(String[] args) throws Exception {
String jmeterHome = "Path of Jmeter Home";
StandardJMeterEngine jmeter = new StandardJMeterEngine();
//JMeter initialization (properties, log levels, locale, etc)
JMeterUtils.setJMeterHome(jmeterHome);
JMeterUtils.loadJMeterProperties("Path of Jmeter Properties Files");
JMeterUtils.initLocale();
// JMeter Test Plan, basically JOrphan HashTree
HashTree testPlanTree = new HashTree();
// HTTP Sampler - Load URL
HTTPSamplerProxy LoadUrl = new HTTPSamplerProxy();
LoadUrl.setDomain("www.samplewebsite.com");
LoadUrl.setPort(80);
LoadUrl.setPath("/");
LoadUrl.setMethod("GET");
LoadUrl.setName("Load Url");
LoadUrl.setProperty(TestElement.TEST_CLASS, HTTPSamplerProxy.class.getName());
LoadUrl.setProperty(TestElement.GUI_CLASS, HttpTestSampleGui.class.getName());
// Create HTTP Authorization Manager
AuthManager manager = new AuthManager();
Authorization authorization = new Authorization();
authorization.setURL("https://www.samplewebsite.com");
authorization.setUser("sampleusername");
authorization.setPass("samepassword");
manager.addAuth(authorization);
manager.setName(JMeterUtils.getResString("auth_manager_title")); // $NON-NLS-1$
manager.setProperty(TestElement.TEST_CLASS, AuthManager.class.getName());
manager.setProperty(TestElement.GUI_CLASS, AuthPanel.class.getName());
// HTTP Sampler - Login
HTTPSamplerProxy Login = new HTTPSamplerProxy();
Login.setDomain("www.samplewebsite.com");
Login.setPort(80);
Login.setPath("/account/login");
Login.setMethod("GET");
Login.setName("Login");
Login.setProperty(TestElement.TEST_CLASS, HTTPSamplerProxy.class.getName());
Login.setProperty(TestElement.GUI_CLASS, HttpTestSampleGui.class.getName());
// HTTP Sampler - Search
HTTPSamplerProxy Search = new HTTPSamplerProxy();
Search.setDomain("www.samplewebsite.com"");
Search.setPort(80);
Search.setPath("/search?q=mobiles");
Search.setMethod("GET");
Search.setName("Search");
Search.setProperty(TestElement.TEST_CLASS, HTTPSamplerProxy.class.getName());
Search.setProperty(TestElement.GUI_CLASS, HttpTestSampleGui.class.getName());
// Loop Controller
LoopController loopController = new LoopController();
loopController.setLoops(1);
loopController.setFirst(true);
loopController.setProperty(TestElement.TEST_CLASS, LoopController.class.getName());
loopController.setProperty(TestElement.GUI_CLASS, LoopControlPanel.class.getName());
loopController.initialize();
// Thread Group
ThreadGroup threadGroup = new ThreadGroup();
threadGroup.setName("Thread Group");
threadGroup.setNumThreads(3);
threadGroup.setRampUp(1);
threadGroup.setSamplerController(loopController);
threadGroup.setProperty(TestElement.TEST_CLASS, ThreadGroup.class.getName());
threadGroup.setProperty(TestElement.GUI_CLASS, ThreadGroupGui.class.getName());
// Test Plan
TestPlan testPlan = new TestPlan("Ecommerce Website");
testPlan.setProperty(TestElement.TEST_CLASS, TestPlan.class.getName());
testPlan.setProperty(TestElement.GUI_CLASS, TestPlanGui.class.getName());
testPlan.setUserDefinedVariables((Arguments) new ArgumentsPanel().createTestElement());
// HTTP Request Sampler and Header Manager
HashTree httpRequestTree = new HashTree();
httpRequestTree.add(Login, manager);
// Construct Test Plan from previously initialized elements
testPlanTree.add(testPlan);
HashTree threadGroupHashTree = testPlanTree.add(testPlan, threadGroup);
threadGroupHashTree.add(LoadUrl);
threadGroupHashTree.add(httpRequestTree);
threadGroupHashTree.add(Search);
SaveService.saveTree(testPlanTree, new FileOutputStream(jmeterHome + "/bin/test.jmx"));
//Add Summarizer output
Summariser summer = null;
String summariserName = JMeterUtils.getPropDefault("summariser.name", "summary");
if (summariserName.length() > 0) {
summer = new Summariser(summariserName);
}
// Store Execution Results into a .jtl file
String logFile = jmeterHome + "/bin/result.jtl";
ResultCollector logger = new ResultCollector(summer);
logger.setFilename(logFile);
testPlanTree.add(testPlanTree.getArray()[0], logger);
// Run Test Plan
jmeter.configure(testPlanTree);
jmeter.run();
System.exit(0);
}
}
So, I want to use the Search Sampler to search a value/keyword/argument for the search box given on the sample website.
Most probably you won't be able to login using HTTP Authorization Manager as it is designed to deal with external authentication systems like Basic, NTLM and Kerberos. If you need to type your credentials into a HTML Form - most likely you need to use HTTP Request sampler and send a POST request with the credentials.
For example this code:
HTTPSamplerProxy loginSampler = new HTTPSamplerProxy();
loginSampler.setDomain("example.com");
loginSampler.setPort(80);
loginSampler.setPath("/login");
loginSampler.setMethod("POST");
loginSampler.setName("Perform Login");
loginSampler.addArgument("username", "johndoe");
loginSampler.addArgument("password", "secret");
loginSampler.setProperty(TestElement.TEST_CLASS, HTTPSamplerProxy.class.getName());
loginSampler.setProperty(TestElement.GUI_CLASS, HttpTestSampleGui.class.getName());
will result into the following configuration:
With regards to search terms - my expectation is that you need to stick to the same approach.
In general creating JMeter test plans using API is not recommended/supported way so I would suggest the following alternative approach:
Record your Test Plan skeleton using JMeter's HTTP(S) Test Script Recorder
Perform correlation if required
Check if your test is doing what it is supposed to be doing by inspecting requests/responses using View Results Tree listener
Once your .jmx script is ready use JMeter API to generate exactly the same test plan programatically.
P.S. An easier way of creating JMeter scripts without the GUI is using Taurus tool where you can develop a test plan using declarative YAML-based syntax.

AWS Cognito JWT token validation

I am trying to enforce security based on AWS Cognito JWT token, the source is at https://github.com/IxorTalk/ixortalk.aws.cognito.jwt.security.filter.
But I have concern, which is per documentation http://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html#amazon-cognito-identity-user-pools-using-id-and-access-tokens-in-web-api
It says "The ID token expires one hour after the user authenticates. You should not process the ID token in your client or web API after it has expired."
Which is the error I am seeing in my logs,
com.nimbusds.jwt.proc.BadJWTException: Expired JWT. I assume, that the JWT token has already expired, what would be my steps to successfully enforce token based authorization?
If you are using Java, The way I have programmed is this,
// Parse the Cognito Keys and get the key by kid
// Key is just a class that is used for parsing JSON to POJO
Key key = this.keyService.getKeyByKeyId(JWT.decode(token).getKeyId());
// Use Key's N and E
BigInteger modulus = new BigInteger(1, Base64.decodeBase64(key.getN()));
BigInteger exponent = new BigInteger(1, Base64.decodeBase64(key.getE()));
// Create a publick key
PublicKey publicKey = null;
try {
publicKey = KeyFactory.getInstance("RSA").generatePublic(new RSAPublicKeySpec(modulus, exponent));
} catch (InvalidKeySpecException e) {
// Throw error
} catch (NoSuchAlgorithmException e) {
// Throw error
}
// get an algorithm instance
Algorithm algorithm = Algorithm.RSA256((RSAPublicKey) publicKey, null);
// I verify ISS field of the token to make sure it's from the Cognito source
String iss = String.format("https://cognito-idp.%s.amazonaws.com/%s", REGION, POOL_ID);
JWTVerifier verifier = JWT.require(algorithm)
.withIssuer(iss)
.withClaim("token_use", "id") // make sure you're verifying id token
.build();
// Verify the token
DecodedJWT jwt = verifier.verify(token);
// Parse various fields
String username = jwt.getClaim("sub").asString();
String email = jwt.getClaim("email").asString();
String phone = jwt.getClaim("phone_number").asString();
String[] groups = jwt.getClaim("cognito:groups").asArray(String.class);
I am using this repo to verify and parsing of the tokens,
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.1</version>
</dependency>
Make sure you are importing the following,
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPublicKeySpec;
import org.apache.commons.codec.binary.Base64;
If the token is expired, it won't be varified.
You need the refresh token, that helps you get new identity and access tokens. The Cognito JS SDK refreshes the token automatically.
Now in your case, seems like you need to call the RefreshToken and add a check to see if the token is expired.
The identity/access tokens come with a expiration time so this is something you can do locally in your application before you use them.

jmeter - how to make a groovy script easier to maintain for extentreports

Below is a script that helps me build an extentreport for jmeter. It is a JSR223 PostProcessor element. It's working nicely however, the problem is that I have it duplicated after every HTTP Request in the script. I have several scripts with 100's of HTTP requests that would need essentially a copy of the same PostProcessor groovy script. This = hard to maintain!
I have tried splitting common parts into an external groovy script that I tried calling on the JSR223 PostProcessor. I also tried chunking up the bits of the script and putting the values into a csv so that I could just update the csv values if anything changed.
I'm sure there's a cleaner/better way to do this but I'm still learning so I'm not sure of the best way to make this easier to maintain. Here's the JSR223 PostProcessor. The only bit that changes with each http request is the "//test result" section
import com.relevantcodes.extentreports.ExtentReports;
import com.relevantcodes.extentreports.ExtentTest;
import com.relevantcodes.extentreports.LogStatus;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
//configure object for response data
def response = prev.getResponseDataAsString();
//configure extentreports objects
ExtentReports report;
ExtentTest testLogger;
//set location for file and report config
String resultsPath = "C:/portalQA/Automation/Results/";
String configPath = "C:/portalQA/Automation/JMeter/TestReportConfig/";
String reportPath =
resultsPath+"Login_Results_${reportDate}_${currentTime}_${testenv}.html";
File file = new File(reportPath);
if (!file.exists()) {
//if file does not exist, create it
report = new ExtentReports(reportPath, true);
report.loadConfig( new File(configPath+"extent-config.xml"));
} else {
//else append to existing report
report = new ExtentReports(reportPath, false);
report.loadConfig( new File(configPath+"extent-config.xml"));
}
//test result
testLogger = report.startTest("Authenticate");
testLogger.assignCategory("Initialize Session");
if (response.contains("com.blah.portal.model.User")) {
testLogger.log(LogStatus.PASS, "Logged in with: ${username}");
testLogger.log(LogStatus.INFO, response);
} else {
testLogger.log(LogStatus.FAIL, "Could not authenticate session");
testLogger.log(LogStatus.INFO, response);
}
log.info("Authenticate");
print("Authenticate print");
report.endTest(testLogger);
report.flush();
I see two options:
I suggest using JSR223 Listener instead. First of all, that way you will only have 1 listener in your script, which resolves your original problem, but it is a better option for writing into file in general, since listener has only one instance for all running threads, so you won't be creating a race condition when writing to file.
If you rather have a post-processor, you can put it on higher level (not under any particular sampler) which will cause it to run after each request within the same scope or below.
For example, configuration like
Thread Group
Post-processor
Sampler 1
...
Sampler N
Will cause Post-processor to run after each Sampler 1...Sampler N
In both cases you may need to check which sampler you are processing, and skip those you don't want to add to your report (easiest way to do it, is to come up with some name convention for excluded samplers)
I also faced the same challenge. In my case I need to check if JSON response from REST service was correct. I solved it in the following way.
I've created a JSR223 PreProcessor under the script root. It contains my custom class to handle JSON parsing and asserts.
import groovy.json.JsonSlurper
import org.apache.jmeter.assertions.AssertionResult
class CustomAssert {
def parseResponse(json) {
def jsonSlurper = new JsonSlurper()
return jsonSlurper.parseText(json)
}
def assertResult(assertionResult, expectedResult, actualResult) {
if (!expectedResult.equals(actualResult)) {
assertionResult.setFailure(true);
assertionResult.setFailureMessage("Expected ${expectedResult} but was ${actualResult}");
}
}
}
vars.putObject('customAssert', new CustomAssert())
Note the last line:
vars.putObject('customAssert', new CustomAssert())
I put an instance of my CustomAssert to vars.
Then under my HTTP Requests I've added JSR233 Assertion
def a = vars.getObject('customAssert')
def response = a.parseResponse(prev.getResponseDataAsString())
a.assertResult(AssertionResult, 'DRY', response.sensorResultHolderUIs[0].result.toString())
a.assertResult(AssertionResult, 'DRY', response.sensorResultHolderUIs[1].result.toString())
a.assertResult(AssertionResult, 'DRY', response.sensorResultHolderUIs[2].result.toString())
It basically retrieves the instance of CustomAssert from vars and calls its methods. I can put as many JSR233 Assertions as I want. The only code that is copied is those two lines on top:
def a = vars.getObject('customAssert')
def response = a.parseResponse(prev.getResponseDataAsString())
To sum up:
Take the common part of your code (that doesn't have to be copied).
Wrap it in a class.
Put the class in JSR233 PreProcessor under the root and export its instance via vars
Take the rest of your code and adjust it to use class defined in 2.
Put that code in as many JSR233 Assertions as you want remembering to retrieve the instance created in 3. from vars
Thank you user1053510. Your advice lead me to build my own JSR223 Listener that renders the report. Below is the code in my JSR223 Listener:
import com.aventstack.extentreports.*;
import com.aventstack.extentreports.reporter.*;
import com.aventstack.extentreports.markuputils.*;
ExtentHtmlReporter htmlReporter;
ExtentReports extent;
ExtentTest test;
// create the HtmlReporter
htmlReporter = new ExtentHtmlReporter("C:/AUTO_Results/Results_${testApp}_${reportDate}_${currentTime}_${testenv}.html");
//configure report
htmlReporter.config().setCreateOfflineReport(true);
htmlReporter.config().setChartVisibilityOnOpen(true);
htmlReporter.config().setDocumentTitle("${testApp} Results");
htmlReporter.config().setEncoding("utf-8");
htmlReporter.config().setReportName("${testApp} Results ${reportDate}_${currentTime}_${testenv}");
htmlReporter.setAppendExisting(true);
// create ExtentReports
extent = new ExtentReports();
// attach reporter to ExtentReports
extent.attachReporter(htmlReporter);
extent.setReportUsesManualConfiguration(true);
// Show Env section and set data on dashboard
extent.setSystemInfo("Tool","JMeter");
extent.setSystemInfo("Test Env","${testenv}");
extent.setSystemInfo("Test Date","${reportDate}");
extent.setSystemInfo("Test Time","${currentTime}");
//stringify test info
String threadName = sampler.getThreadName();
String samplerName = sampler.getName();
String requestData = props.get("propRequestData");
String respCode = props.get("propRespCode");
String respMessage = props.get("propRespMessage");
String responseData = props.get("propResponse");
// create test
test = extent.createTest(threadName+" - "+samplerName);
//test.assignCategory("API Testing");
// analyze sampler result
if (vars.get("JMeterThread.last_sample_ok") == "false") {
log.error("FAILED: "+samplerName);
print("FAILED: "+samplerName);
test.fail(MarkupHelper.createLabel("FAILED: "+sampler.getName(),ExtentColor.RED));
} else if (vars.get("JMeterThread.last_sample_ok") == "true") {
if(responseData.contains("#error")) {
log.info("FAILED: "+sampler.getName());
print("FAILED: "+sampler.getName());
test.fail(MarkupHelper.createLabel("FAILED: "+sampler.getName(),ExtentColor.RED));
} else if (responseData.contains("{")) {
log.info("Passed: "+sampler.getName());
print("Passed: "+sampler.getName());
test.pass(MarkupHelper.createLabel("Passed: "+sampler.getName(),ExtentColor.GREEN));
}
} else {
log.error("Something is really wonky");
print("Something is really wonky");
test.fatal("Something is really wonky");
}
//info messages
test.info("RequestData: "+requestData);
test.info("Response Code and Message: "+respCode+" "+respMessage);
test.info("ResponseData: "+responseData);
//playing around
//markupify json into code blocks
//Markup m = MarkupHelper.createCodeBlock(requestData);
//test.info(MarkupHelper.createModal("Modal text"));
//Markup mCard = MarkupHelper.createCard(requestData, ExtentColor.CYAN);
// test.info("Request "+m);
// test.info(mCard);
// test.info("Response Data: "+MarkupHelper.createCodeBlock(props.get("propResponse")));
// test.info("ASSERTION MESSAGE: "+props.get("propAssertion"));
// end the reporting and save the file
extent.flush();
Then in each threadgroup I have a BeanShell Assertion with these lines:
//request data
String requestData = new String(prev.SamplerData);
//String requestData = new String(requestData);
props.put("propRequestData", requestData);
//response data
String respData = new String(prev.ResponseData);
//String respData = new String(prev.getResponseDataAsString());
props.put("propResponse", respData);
//response code
String respCode = new String(prev.ResponseCode);
props.put("propRespCode",respCode);
//response message
String respMessage = new String(prev.ResponseMessage);
props.put("propRespMessage",respMessage);

JMeter how to authenticate login with two passwords

I am creating a jmeter scritp and the scnerio where i am struck is as follows:
First Try login to an application with Password 1, if login fails then try with password 2, if login fails with password2 aswell then the result should be fail otherwise pass.
I have created a HTTP request and Password1, password2 are user defined variables.
Have two requests Req_1 and Req_2 and configure them with 'login' action one with each password. Use 'Regular Expression Extractor' or other to parse the response to Req_1 and use 'If Controller' to see if it passed or not and submit Req_2 only if Req_1 login fails.
Add BeanShell Sampler to the Test Plan and add the following code (working code for the given website):
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import java.util.List;
import java.util.ArrayList;
HttpClient httpclient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost("http://httpbin.org/post");
List nvps = new ArrayList();
nvps.add(new BasicNameValuePair("username", "vip"));
nvps.add(new BasicNameValuePair("password", "secret"));
httpPost.setEntity(new UrlEncodedFormEntity(nvps));
HttpResponse response = httpclient.execute(httpPost);
String responseString = EntityUtils.toString(response.getEntity());
String responseCode = String.valueOf(response.getStatusLine().getStatusCode());
String errorMessage = "secret";
if(responseString.contains(errorMessage)){
log.info("first time failed");
HttpClient httpclient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost("http://httpbin.org/post");
List nvps = new ArrayList();
nvps.add(new BasicNameValuePair("username", "vip"));
nvps.add(new BasicNameValuePair("password", "secret"));
httpPost.setEntity(new UrlEncodedFormEntity(nvps));
HttpResponse response = httpclient.execute(httpPost);
String responseString = EntityUtils.toString(response.getEntity());
String responseCode = String.valueOf(response.getStatusLine().getStatusCode());
if(responseString.contains(errorMessage)){
log.info("second time failed");
IsSuccess = false;
ResponseCode = "403";
ResponseMessage = "Login failed with both the passwords";
}
}
return responseString;
Add above script to "Script" text area in the BeanShell sampler.
Image reference:
Note: replace the URL, username, password and error message as per your requirements. Add any headers if crucial.
If you want to use HTTP Sampler, follow the process as suggested by #SaiMatam.
Add If controller, compare whether the error message is received (write condition in Condition field).
Keep the same sampler (change only the password) inside If Controller. this sampler would get execute only if the condition is satisfied.
Add Response Assertion for the sampler in If Controller. Add the error message in "Pattern to test" field. select "Not" checkbox in "Pattern Matching Rules". This will make sure that, if the error message is received, the second request is marked as FAIL by JMeter (we are checking that the response should not contain the given string/pattern), otherwise will mark it as PASS.
References:
http://jmeter.apache.org/usermanual/component_reference.html#If_Controller
http://jmeter.apache.org/usermanual/component_reference.html#Response_Assertion

How to config a HTTP Request Method GET with JSON BODY in JMeter?

I'm facing the issue while writing the scenario in JMeter. It's API using GET Method and requires JSON BODY.
It's very easy if the method is POST/PUT. But I don't know how to do with method GET. I tried: Add HTTP Header Manager with Content-Type:application/json, but nothing help.
As I know, using BODY with GET request is the not the good way, but the developer team has implemented like that, and it can be worked with curl.
So I would like to know can we config this in JMeter or not? and How?
Thanks in advance.
In fact sending request body with HTTP GET request is not supported by Apache HttpComponents and hence in JMeter, you should be able to send a GET request with JSON body using JSR223 Sampler and the following code (assumes Groovy language):
import org.apache.http.HttpResponse
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase
import org.apache.http.entity.StringEntity
import org.apache.http.impl.client.CloseableHttpClient
import org.apache.http.impl.client.HttpClientBuilder
import org.apache.http.util.EntityUtils
public class HttpGetWithBody extends HttpEntityEnclosingRequestBase {
public final static String METHOD_NAME = "GET";
#Override
public String getMethod() {
return METHOD_NAME;
}
}
def client = HttpClientBuilder.create().build();
def getRequest = new HttpGetWithBody();
getRequest.setURI(new URL("http://example.com").toURI());
def json = "{\"employees\":[\n" +
" {\"firstName\":\"John\", \"lastName\":\"Doe\"},\n" +
" {\"firstName\":\"Anna\", \"lastName\":\"Smith\"},\n" +
" {\"firstName\":\"Peter\", \"lastName\":\"Jones\"}\n" +
"]}";
def body = new StringEntity(json, "application/json", "UTF-8");
getRequest.addHeader("Content-Type", "application/json");
getRequest.setEntity(body);
def response = client.execute(getRequest);
def result = EntityUtils.toString(response.getEntity());
log.info(result);
See Beanshell vs JSR223 vs Java JMeter Scripting: The Performance-Off You've Been Waiting For! article for more information on using JSR223 test elements and groovy language and scripting best practices.
There is a reported bug in JMeter for this https://bz.apache.org/bugzilla/show_bug.cgi?id=60358 and looks like the fix is on the way. Hopefully this issue would be fixed soon.

Resources