Error while uploading a file with gzipped content via HTTP POST - jmeter

I am trying to upload a file using HTTP POST sampler, at the same time compressing the file content. For this, I have added Content-Encoding:gzip in the Header Manager and in the pre processor of the sampler added following code
import org.apache.commons.io.IOUtils;
import java.util.zip.GZIPOutputStream;
String bodyString = sampler.getArguments().getArgument(0).getValue();
byte [] requestBody = bodyString.getBytes();
ByteArrayOutputStream out = new ByteArrayOutputStream(requestBody.length);
GZIPOutputStream gzip = new GZIPOutputStream(out);
gzip.write(requestBody);
gzip.close();
sampler.getArguments().getArgument(0).setValue(out.toString(0));
This was not working and it was throwing following exception
2019-08-07 14:08:21,970 ERROR o.a.j.m.JSR223PreProcessor: Problem in JSR223 script, JSR223 PreProcessor
javax.script.ScriptException: Sourced file: inline evaluation of: ``import org.apache.commons.io.IOUtils; import java.util.zip.GZIPOutputStream; S . . . '' : Typed variable declaration : at Line: 5 : in file: inline evaluation of: ``import org.apache.commons.io.IOUtils; import java.util.zip.GZIPOutputStream; S . . . '' : .getValue ( )
Target exception: java.lang.NullPointerException: Attempt to invoke method getValue on null value
in inline evaluation of: ``import org.apache.commons.io.IOUtils; import java.util.zip.GZIPOutputStream; S . . . '' at line number 5
at bsh.engine.BshScriptEngine.evalSource(BshScriptEngine.java:87) ~[bsh-2.0b6.jar:2.0b6 2016-02-05 05:16:19]
at bsh.engine.BshScriptEngine.eval(BshScriptEngine.java:46) ~[bsh-2.0b6.jar:2.0b6 2016-02-05 05:16:19]
at javax.script.AbstractScriptEngine.eval(Unknown Source) ~[?:1.8.0_73]
at org.apache.jmeter.util.JSR223TestElement.processFileOrScript(JSR223TestElement.java:225) ~[ApacheJMeter_core.jar:5.1.1 r1855137]
at org.apache.jmeter.modifiers.JSR223PreProcessor.process(JSR223PreProcessor.java:44) [ApacheJMeter_components.jar:5.1.1 r1855137]
at org.apache.jmeter.threads.JMeterThread.runPreProcessors(JMeterThread.java:935) [ApacheJMeter_core.jar:5.1.1 r1855137]
at org.apache.jmeter.threads.JMeterThread.executeSamplePackage(JMeterThread.java:537) [ApacheJMeter_core.jar:5.1.1 r1855137]
at org.apache.jmeter.threads.JMeterThread.processSampler(JMeterThread.java:486) [ApacheJMeter_core.jar:5.1.1 r1855137]
at org.apache.jmeter.threads.JMeterThread.run(JMeterThread.java:253) [ApacheJMeter_core.jar:5.1.1 r1855137]
at java.lang.Thread.run(Unknown Source) [?:1.8.0_73]
Now to debug added log.info("sampler-------:"+sampler) before getValue like
log.info("sampler-------:"+sampler);
String bodyString = sampler.getArguments().getArgument(0).getValue();
But in the logs sampler returned empty
Query Data:
So how should I access the file content in the HTTP Request and at the same time gzip it and send?

To gzip the file and its contents use the following code and put it in JSR223 Sampler [this should be before calling POST API] and the assumption is payload data is already copied to a file.
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.GZIPOutputStream;
String source_filepath = "C:/Sample/Input.txt";
String destinaton_zip_filepath = "C:/Sample/Input.gzip";
byte[] buffer = new byte[1024];
try {
FileOutputStream fileOutputStream =new FileOutputStream(destinaton_zip_filepath);
GZIPOutputStream gzipOuputStream = new GZIPOutputStream(fileOutputStream);
FileInputStream fileInput = new FileInputStream(source_filepath);
int bytes_read;
while ((bytes_read = fileInput.read(buffer)) > 0) {
gzipOuputStream.write(buffer, 0, bytes_read);
}
fileInput.close();
gzipOuputStream.finish();
gzipOuputStream.close();
} catch (IOException ex) {
ex.printStackTrace();
}
vars.put("ZipFileLocation",destinaton_zip_filepath);
Now the gzip file can be used via ${ZipFileLocation} variable.
It is up to how the API is called, following can be the solution:
Directly send this gzip file in the API
Declare a variable and hold all your payload data into it and then call the API -> gzip it
Note : Correct MIME type and Headers need to be used wherever applicable

If you're doing a file upload with JMeter, to wit your file is being passed via "Files Upload" section - you will not be able to get anything using getArguments() function, you will need to use getHTTPFiles() instead, suggested algorithm:
Get the required file path like:
def plainFile = sampler.getHTTPFiles()[0].path
Compress the file according to your server expectations
Replace the original file path with compressed file path
sampler.getHTTPFiles()[0].setPath("/path/to/compressed/file.gz")

Related

Jmeter decompress gzip response

I write performance test script with JMeter, but the target site using gzip to compress response. So Jmeter can't display any response and only show EOFException.
java.io.EOFException
at java.base/java.util.zip.GZIPInputStream.readUByte(GZIPInputStream.java:269)
To solve this problem. I write JSR223 PostProcessor for decompress response, but my script always show "Not in GZIP format" message.
java.util.zip.ZipException: Not in GZIP format
I don't have any idea about this message. Please help me.
This is my "JSR223 PostProcessor" script.
import java.util.zip.GZIPInputStream;
import java.io.InputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
byte[] responseBody = prev.getResponseData();
ByteArrayOutputStream decompressBaos = new ByteArrayOutputStream();
try(InputStream gzip = new GZIPInputStream(new ByteArrayInputStream(responseBody))) {
int b;
while ((b = gzip.read()) != -1) {
decompressBaos.write(b);
}
}catch(Exception ex){
log.info("Exception:"+ex);
}
byte[] decompressed = decompressBaos.toByteArray();
prev.setResponseData(decompressed);
Are you sure the response is in GZIP format? In order to be able to request it in GZIP you need to add HTTP Header Manager and configure it to send Accept-Encoding header with the value of gzip,deflate

Get first json object from response rest service by Beanshell in jmeter

I get this JSON response from my web service:
[
{
"type": "022",
"sendDate": "2020-11-09 12:43:07",
"message": "test1",
"id": 8035,
},
{
"notificationType": "023",
"sendDate": "2020-11-09 11:40:02",
"message": "test2 ",
"id": 8034,
},...
]
Now by Beanshell in JMeter I want to pass first id into new request so in JSR223 PostProcessor i write a simple print like this:
import com.eclipsesource.json.*;
String jsonString = prev.getResponseDataAsString();
log.info("value=" + jsonString);
JsonArray inbox = Json.parse(jsonString).asArray();
//String id_BSH = ((JSONObject) storeArray.get(0)).getAsString("id");
//vars.put("id_BSH", pickup);
but i got this error :
2020-11-10 17:59:55,245 ERROR o.a.j.e.JSR223PostProcessor: Problem in JSR223 script, JSR223 PostProcessor
javax.script.ScriptException: Sourced file: inline evaluation of: ``import com.eclipsesource.json.*; String jsonString = prev.getResponseDataAsStrin . . . '' : Typed variable declaration : Class: JsonArray not found in namespace : at Line: 4 : in file: inline evaluation of: ``import com.eclipsesource.json.*; String jsonString = prev.getResponseDataAsStrin . . . '' : JsonArray
in inline evaluation of: ``import com.eclipsesource.json.*; String jsonString = prev.getResponseDataAsStrin . . . '' at line number 4
at bsh.engine.BshScriptEngine.evalSource(BshScriptEngine.java:93) ~[bsh-2.0b6.jar:2.0b6 2016-02-05 05:16:19]
at bsh.engine.BshScriptEngine.eval(BshScriptEngine.java:46) ~[bsh-2.0b6.jar:2.0b6 2016-02-05 05:16:19]
at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:233) ~[?:1.8.0_202]
at org.apache.jmeter.util.JSR223TestElement.processFileOrScript(JSR223TestElement.java:224) ~[ApacheJMeter_core.jar:5.3]
at org.apache.jmeter.extractor.JSR223PostProcessor.process(JSR223PostProcessor.java:45) [ApacheJMeter_components.jar:5.3]
at org.apache.jmeter.threads.JMeterThread.runPostProcessors(JMeterThread.java:940) [ApacheJMeter_core.jar:5.3]
at org.apache.jmeter.threads.JMeterThread.executeSamplePackage(JMeterThread.java:572) [ApacheJMeter_core.jar:5.3]
at org.apache.jmeter.threads.JMeterThread.processSampler(JMeterThread.java:489) [ApacheJMeter_core.jar:5.3]
at org.apache.jmeter.threads.JMeterThread.run(JMeterThread.java:256) [ApacheJMeter_core.jar:5.3]
at java.lang.Thread.run(Thread.java:748) [?:1.8.0_202]
I've heard Groovy "is the new black", moreover you should not be using Beanshell since JMeter 3.1 so you can go for Groovy's JsonSlurper class and store the first ID into a variable with this one-liner:
vars.put("id_BSH", new groovy.json.JsonSlurper().parse(prev.getResponseData()).get(0).id as String)
More information: Apache Groovy - Parsing and Producing JSON

JMeter - How to read JSON file?

I used the CSV format for the data files in JMeter. Our VP wants to change the format to JSON. How can I read a JSON file from the disk?
You have at least 2 options:
Use HTTP Request sampler and file protocol like:
JSON files are basically plain-text files so you will be able to use JSON Extractor or JSON Path Extractor to parse JSON data and store the result into JMeter Variables for later reuse
References:
Jayway JsonPath - Getting Started
Advanced Usage of the JSON Path Extractor in JMeter
Use JSR223 Test Elements and Groovy language. Groovy has built-in JSON support via JsonSlurper so you will be able to parse the JSON file programmatically.
References:
The Groovy programming language - Parsing and producing JSON
Groovy - JSON
The best solution for this problem is to use JSR223 Sampler to read JSON file and load into the vars or props and use it wherever it is required.
For this,
Add a JSR223 Sampler in JMeter
Add the below code
import java.io.File
import java.util.Base64
def propertiesFromMap(map, prefix) {
for (item in map) {
id = prefix+item.key;
if (item.value instanceof Map) {
propertiesFromMap(item.value, id+".");
} else {
value = item.value.toString();
log.info("Loading property " + id + ": " + value);
if(value.startsWith("ENC:")) {
props.put(id, new String(Base64.getDecoder().decode(value.substring(4, value.length()))));
} else {
props.put(id, value);
}
}
}
}
def baseDir = org.apache.jmeter.services.FileServer.getFileServer().getBaseDir();
def jsonFilePath= baseDir + "/configs/" + "configuration-dev" + ".json";
log.info("Loading properties from " + jsonFilePath);
def jsonMap = new groovy.json.JsonSlurper().parse(new java.io.File(jsonFilePath));
propertiesFromMap(jsonMap, '');
Create a directory named configs where you placed the .jmx file
Create a file named configuration-dev.json in configs directory
Add JSON content e.g. in the file:
{
"key1": "value1",
"key2": "value2",
"key3": "ENC:base64_encoded_value"
"group1": {
"grp1_key": "value"
}
Access values in Samplers e.g. ${__P(key1)}, it will return value of key1. For group1 variables access e.g. ${__P(group1.grp1_key)}
For accessing the values into JSR223 use props e.g. props.get("key1")
You can pass base64 encoded values into JSON by adding ENC: as value prefix which will be resolved automatically when accessing values from props or __P()

Aws integration spring: Cannot download a file within a folder

The below code is trying downloaded a single file from within a folder on S3. It is using the message handler below.
NOTE: The code below works for a file that is placed within the root directory of the S3 bucket. It does not work for a file placed in a folder.
#Bean
#ServiceActivator(inputChannel = "s3Channel")
public MessageHandler s3Handler() {
ExpressionParser PARSER = new SpelExpressionParser();
S3MessageHandler s3MessageHandler = new S3MessageHandler(amazonS3(), "test.queue", true);
s3MessageHandler.setOutputChannel(this.channel);
s3MessageHandler.setCommand(S3MessageHandler.Command.DOWNLOAD);
s3MessageHandler.setKeyExpression(PARSER.parseExpression("payload instanceof T(java.io.File) ? payload.name : headers.key"));
s3MessageHandler.setObjectAclExpression(new ValueExpression<>(CannedAccessControlList.PublicReadWrite));
return s3MessageHandler;
}
Using the payload:
Message<?> payload = MessageBuilder.withPayload(new File("test/s3testfile.xml")).build();
this.s3ProcessChannel.send(payload);
The following stack trace occurs downloading a file from with a folder.
org.springframework.messaging.MessageHandlingException: error occurred in message handler [s3MessageHandler]; nested exception is com.amazonaws.services.s3.model.AmazonS3Exception: Not Found (Service: Amazon S3; Status Code: 404; Error Code: 404 Not Found;)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:139) ~[spring-integration-core-4.2.5.RELEASE.jar:na]
at org.springframework.messaging.support.ExecutorSubscribableChannel$SendTask.run(ExecutorSubscribableChannel.java:135) ~[spring-messaging-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.messaging.support.ExecutorSubscribableChannel.sendInternal(ExecutorSubscribableChannel.java:91) ~[spring-messaging-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:117) ~[spring-messaging-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:104) ~[spring-messaging-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at com.rapid7.live.assessment.aws.inbound.channels.SqsAssessmentMessageChannel.send(SqsAssessmentMessageChannel.java:44) ~[classes/:na]
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:115) ~[spring-messaging-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:45) ~[spring-messaging-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:105) ~[spring-messaging-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.integration.endpoint.MessageProducerSupport.sendMessage(MessageProducerSupport.java:105) ~[spring-integration-core-4.2.5.RELEASE.jar:na]
at org.springframework.integration.aws.inbound.SqsMessageDrivenChannelAdapter.access$400(SqsMessageDrivenChannelAdapter.java:53) ~[spring-integration-aws-1.0.0.M1.jar:na]
at org.springframework.integration.aws.inbound.SqsMessageDrivenChannelAdapter$IntegrationQueueMessageHandler.handleMessageInternal(SqsMessageDrivenChannelAdapter.java:154) ~[spring-integration-aws-1.0.0.M1.jar:na]
at org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMessage(AbstractMethodMessageHandler.java:389) ~[spring-messaging-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.cloud.aws.messaging.listener.SimpleMessageListenerContainer.executeMessage(SimpleMessageListenerContainer.java:181) ~[spring-cloud-aws-messaging-1.1.0.RC1.jar:1.1.0.RC1]
at org.springframework.cloud.aws.messaging.listener.SimpleMessageListenerContainer$MessageExecutor.run(SimpleMessageListenerContainer.java:314) ~[spring-cloud-aws-messaging-1.1.0.RC1.jar:1.1.0.RC1]
at org.springframework.cloud.aws.messaging.listener.SimpleMessageListenerContainer$SignalExecutingRunnable.run(SimpleMessageListenerContainer.java:368) [spring-cloud-aws-messaging-1.1.0.RC1.jar:1.1.0.RC1]
at org.springframework.core.task.SimpleAsyncTaskExecutor$ConcurrencyThrottlingRunnable.run(SimpleAsyncTaskExecutor.java:251) [spring-core-4.2.5.RELEASE.jar:4.2.5.RELEASE]
The file does exist in the correct bucket.
Well, the problem is here that File.getName() returns only file name, without any parent dirs.
Consider change your keyExpression to the :
"payload instanceof T(java.io.File) ? payload.path : headers.key"
Or just don't reply on the File payload but always specify the proper key in the headers.

Trying to create connection betwee jmeter and xmpp server

Trying to create connection but displayed error . Below are the Beanshell sampler code .
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.ConnectionListener;
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
import org.jivesoftware.smack.SASLAuthentication;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
String jabberId = "admin";
String jabberPass = "12345";
String SERVER_ADDRESS = "xxx.xxx.xxx.xxx";
int PORT = 5222; // or any other port
String ServiceName = "Smack";
SASLAuthentication.blacklistSASLMechanism("DIGEST-MD5");
SASLAuthentication.unBlacklistSASLMechanism("PLAIN");
XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder()
.setCompressionEnabled(false)
.setHost(SERVER_ADDRESS)
.setServiceName(ServiceName)
.setPort(DEFAULT_PORT)
.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled)
.setSendPresence(true)
.setDebuggerEnabled(true)
.build();
XMPPTCPConnection con = new XMPPTCPConnection(config);
int REPLY_TIMEOUT = 50000; // 50 seconds, but can be shorter
con.setPacketReplyTimeout(REPLY_TIMEOUT);
//con = getConnection();
con.connect();
//con.login(jabberId,jabberPass);
Below are the error..
Response code: 500 Response message:
org.apache.jorphan.util.JMeterException: Error invoking bsh method: eval
In file: inline evaluation of: ``public XMPPConnection doConnect(String userName,String password) { XMPPConne . . . '' Encountered "( xxx.xxx .xxx" at line 7, column 60.
please tell me what's wrong with it . or give me correct code to connect jmeter to xmpp server .

Resources