How to POST GZip Request with Apache JMeter - jmeter

I have a question for using Apach JMeter.
Our project, Android apps post json data with "Gzip Compression" to API server.
The Android apps using "Apache HttpClient" and it's "GzipCompressingEntity" class.
For performance testing of API server, I tryed to recording the request by JMeter's Proxy (="HTTP(S) Test Script Recorder").
But the recorded request body was empty.
What I want to do is to send "Gziped HTTP request data" from Apache JMeter to server.
Is there any way for that?
Following is sample of our Android app's request header.
POST /api/test HTTP/1.1
Content-Type: application/json
Transfer-Encoding: chunked
Content-Encoding: gzip
Host: 192.168.11.11:8080
Connection: Keep-Alive
User-Agent: Apache-HttpClient/UNAVAILABLE (java 1.5)
Accept-Encoding: gzip,deflate
RequestBody is Gziped binary data.
What I had done is
Run the "HTTP(S) Test Script Recorder(Proxy Server)" on JMeter.
Set http proxy of Android to use that proxy server.
Execute Android test code of HTTP Client (the post data is compressed by Gzip).
then, that test code finished with failure. (no response from server)
If access directly (without JMeter's Proxy Server), that test succeeded.
Can I send the compressed request data from JMeter just like this?

Add HTTP Header Manager to your test plan and add at least the following headers:
Content-Type: application/json
Content-Encoding: gzip
Add Beanshell PreProcessor as a child of the request which you need to encode and add the following code to it's "Script" area:
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));
It will get your request body, compress it and substitute on the fly so the request will be gzipped.

Encoding is wrong, you need to save it in body like this
sampler.getArguments().getArgument(0).setValue(new String(compressedBody, 0));

Related

Not able to submit image with POST method using jmeter

My Http Request
My Header Manger
I am getting error code as 400 - BAD REQUEST
Thread Name:Thread Group 1-1
Sample Start:2021-03-20 06:20:18 GMT
Load time:551
Connect Time:40
Latency:551
Size in bytes:336
Sent bytes:652
Headers size in bytes:144
Body size in bytes:192
Sample Count:1
Error Count:1
Data type ("text"|"bin"|""):text
Response code:400
Response message:BAD REQUEST
HTTPSampleResult fields:
ContentType: text/html; charset=utf-8
DataEncoding: utf-8
As per 400 Bad Request description:
The HyperText Transfer Protocol (HTTP) 400 Bad Request response status code indicates that the server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing).
The client should not repeat this request without modification.
so it means that the request you're sending is malformed somehow, i.e. incorrect path or missing header or invalid/incorrect/missing parameter(s)
If you can execute the request manually using browser you should be able to record the request using JMeter's HTTP(S) Test Script Recorder, just make sure to copy the file you're uploading into the "bin" folder of your JMeter installation, this way JMeter will be able to properly generate the HTTP Request sampler and HTTP Header Manager.
See Recording File Uploads with JMeter article for more details.

How to change Content Length in Jmeter

I am stuck at very critical junction of my scripting in Jmeter, I have a requirement to upload a file on Azure storage and a Microservice which analyze the blob data to process further but it looks for certain size, example 8081920 bytes. I am successfully able to upload the the file of same size on Azure storage but the service returns size Mismatch.
If I upload the same file using Postman, service is able to process the image successfully. Below is the Postman request Header
x-ms-blob-type: BlockBlob
Content-Type: image/raw
User-Agent: PostmanRuntime/7.26.10
Accept: /
Postman-Token: b9384ac9-7fbe-4ab8-834b-aef0d8114588
Host: xxxxxxx.blob.xxxxxx.windows.net
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Length: 8081920
Jmeter Request Header:
Connection: keep-alive
Content-Type: image/raw
Accept-Encoding: gzip, deflate, br
Accept: /
x-ms-blob-type: BlockBlob
Content-Length: 8082155
Host: xxxxxxx.blob.xxxxxx.windows.net
User-Agent: PostmanRuntime/7.26.10
Any idea how to resolve this from where jmeter sending additional 235 Bytes but Postman doesn't.
Thanks,
Akshat
Content-Length header is being automatically calculated by both tools as:
sum of request headers (bytes) + request body (bytes)
Given you haven't provided the body we cannot state where the inconsistency lives, from what I can see is that Postman sends Postman-Token and JMeter doesn't so JMeter's Content-Length should be less
In case of multipart file upload the discrepancy can be caused by different boundaries but it shouldn't have any impact on the image processing.
In any case given you're able to successfully upload the file using Postman and cannot do this using JMeter - you can just record the request from Postman using JMeter's HTTP(S) Test Script Recorder - this way you will get confidence that requests are exactly the same. Just make sure to copy the file you're uploading to "bin" folder of your JMeter installation, this way JMeter will be able to properly capture the request.
More information: How to Convert Your Postman API Tests to JMeter for Scaling

Jmeter - sends requests fine using parameter but not using body

I am load testing my website API. i try and send a request to the website for login which requires username and password. I initially set up http header manager, cookie manager and http request.
I enter name(username,password) and value parameter(say vis,new respectively)in parameters, then hit start and the tests completes successfully. On the other hand, if i type the key value pairs as dictionary {"username":"vis","password":"new"} in body tab and then run again, then request header has the post data(as seen from view results tree) but my server is not recognizing the post data. It just returns error as if no post data was sent.
I also made the Content-Type as application/json for the body tab method but i still get the same error.
Some error screenprints:
Header setting
Request parameters
View results in tree - request header:
Connection: keep-alive
Content-Type: application/json
Content-Length: 35
Host: url.com
User-Agent: Apache-HttpClient/4.5.6 (Java/1.8.0_191)
request-body:
POST https://url.com/accounts/login.json
POST data:
{"username":"vis","password":"new"}
[no cookies]
So, my request works when i send it under parameters tab but not while using body data tab.
You're not able to login because your application doesn't support the way you're providing the credentials.
If Python request works fine for your - just record it using JMeter's HTTP(S) Test Script Recorder
Prepare JMeter for recording. The fastest way is using JMeter Templates feature.
From JMeter's main menu choose File -> Templates -> Recording and click "Create"
Open HTTP(S) Test Script Recorder and click "Start"
Amend your Python script to use JMeter as the proxy:
import requests
jmeter = {
'http': 'http://localhost:8888',
'https' : 'http://localhost:8888'
}
requests.post("https://url.com/accounts/login.json",data={"username":"vis","password":"new"}, proxies=jmeter)
Execute your Python script
JMeter will capture it under the Recording Controller. This would be the request you should be using for your testing:

Running test script recorder error in JMeter

I have to perform load testing of a particular application and am using JMeter for that.
In my application, I have a unique access token which will be obtained on successful login and this token has to be passed to the consecutive requests to obtain the response.
Now I have added a recorder for my test plan and ran the HTTP test script recorder.all the browser action is recorded in the recorder of the test plan.
the structure of my test plan and workbench is as mentioned below.
**Testplan-**
*Threadgroup*
Recorder-
//inside the recorder
[Request1-login
Request2-To load the uploaded images by the corresponding user]
//Outside the recorder inside the thread group,
View Results Tree
HTTP Cache Manager
HTTP Coockie Manager
**WorkBench**
HTTP(s) Test Script Recorder
By default, there is a header manager for each request when recorded what I did was to add the extracted token obtained using json extracter of the request1 to the header manager of the request2 in the recorded script.
The token is getting passed along with the request header as shown below but the response obtained is unauthorised.
Request Headers:
Connection: keep-alive
Referer: http://localhost/
Accept-Language: en-US,en;q=0.5
Origin: http://localhost
Content-Type: application/json;charset=utf-8
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0
Accept: application/json, text/plain, */*
Authorisation:91kLM68tdMBoDFRURArvdmwYgWV9Nr2sHYDwivTM.91kLM68tdMBoDFRURArvdmwYgWV9Nr2sHYDwivTM.Arvdm_M68-BoDFRURArvdmwYgWV9Nr2sHYDwivTM
Content-Length: 0
Host: http://localhost/phpmyadmin/index.php
I have checked the same token in postman and am obtaining the correct response.
am I missing out something?Is there anything else I have to take care of before running the recorded test script?Please help
Compare exactly (Header + Body) requests :
sent by postman
vs request sent by JMeter
There must be a difference somewhere.
And in CookieManager ensure you have set Policy to "standard" if using JMeter 3.x
As per your comment:
Authorization was misspelled (Authorisation)

Microsoft Speech API with Python requests?

I'm trying to use the requests package in Python to make a call to the Microsoft Bing Speech Transcription API. I can make the call work when I use Postman, but this requires manually selecting a file to upload (Postman provides a GUI to select the file), but I'm not sure how this file selection gets mapped onto the actual HTTP request (and by extension the Python requests request). Postman can convert its internal queries into code, and according to Postman the http request it's making is:
POST /recognize?scenarios=smd&appid=[REDACTED]&locale=en-US&device.os=wp7&version=3.0&format=json&form=BCSSTT&instanceid=[REDACTED]&requestid=[REDACTED] HTTP/1.1
Host: speech.platform.bing.com
Authorization: [REDACTED]
Content-Type: application/x-www-form-urlencoded
Cache-Control: no-cache
Postman-Token: [REDACTED]
undefined
And the equivalent request if made through the Python requests library would be:
import requests
url = "https://speech.platform.bing.com/recognize"
querystring = {"scenarios":"smd","appid":[REDACTED],"locale":"en-US","device.os":"wp7","version":"3.0","format":"json","form":"BCSSTT","instanceid":[REDACTED],"requestid":[REDACTED]}
headers = {
'authorization': [REDACTED],
'content-type': "application/x-www-form-urlencoded",
'cache-control': "no-cache",
'postman-token': [REDACTED]
}
response = requests.request("POST", url, headers=headers, params=querystring)
print(response.text)
However note that in neither case does the generated code actually pass in the audio file to be transcribed (clearly Postman doesn't know how to display raw audio data), so I'm not sure how to add this crucial information to the request. I assume that in the case of the HTTP request code the audio stream goes in the spot displayed as "undefined". In the Python requests command, from reading the documentation it seems like the response = requests.request(...) line should be replaced by:
response = requests.request("POST", url, headers=headers, params=querystring, files={'file': open('PATH/TO/AUDIO/FILE', 'rb')})
But when I run this query I get "Request timed out (> 14000 ms)". Any idea for how I can successfully call the Microsoft Speech API through Python? Any help would be much appreciated, thanks.
Make this line your post request:
r = requests.post(url, headers=headers, params=querystring, data=open('PATH/TO/WAV/FILE', 'rb').read())
And that should do the trick.
In the Microsoft Documentation, the audio file binary data is the body of the POST request and must be sent using the data parameter of the requests library.

Resources