Jmeter Websocket: Wait for all frames in a response - websocket

I am using the Jmeter WebSocket Sampler. I have successfully connected to the websocket, and can send a text request. It is a chat bot, and I will be validating it's response.
However, I have observed in Fiddler, the websocket responds to the text request with a short confirmation response before the chat bot's response.
for example, the first response is {"ok":true, "replyto":1151810327491, "type":"ack"} where replyto is a message ID. I don't really need this information.
Only then is the real response sent (as I observed in Fiddler), the one I would actually like to read and put Assertions on.
I have tried Websocket request-response Sampler, Websocket Single Write Sampler (followed by a Single Read Sampler), and I have tried the general Websocket Sampler.
TL;DR: The websocket responses come in "frames", each having a JSON response, my samplers are closing right after the first frame.

If the server is sending frames you are not interested in, there are two possible solutions.
If you know in advance which frame you want to discard (e.g. the first that is received after sending a message), you can simply use a Single Read Sampler to read the message you want to discard and have a second Single Read Sampler read the "real" message.
If the sequence of messages is not that easy to predict, you can use a Frame Filter to discard the messages for you, so they don't show up in the (Read) Sampler. For example, configure a Text Frame Filter with condition "starts with text" and use the string '{"ok":true, "replyto":' as match value, this will discard all frames that start with that string. If this doesn't work because the message you are interested in start with the same string, you can create more complex conditions, even with regular expressions.

Related

Jmeter - Websocket plugin - unable to find solution to constantly read incoming messages

Good afternoon.
I have implemented websockets in my project using the plugin "WebSocket Samplers by Peter Doornbosch" in Jmeter.
So far the requirements were simply to send and receive some payload, or simply send and forget.
However I got a new requirement where the server will constantly send back websocket message to client at every 5 second interval.
Ex: I send ABC , XYZ, ABD at every 3 second interval and I need to read XYC, YTZ at every 5 second interval both should happen simultaneously
I'm unable to use Parallel Controller as each item within the controller is a separate thread and thus I will loose web socket connection for the second one.
Is there any way I can achieve this using some listeners or something.
Thanks for your response in advance
As per documentation:
Fragmentation
WebSocket messages may be fragmented into several frames. In such cases the first frame is an ordinary text or binary frame, but it will have the final bit cleared. The succeeding frames will be continuation frames (whether they are text or binary is inferred by the first frame) and the last continuation frame will have the final bit set. The plugin supports continuation frames, but as the plugin is frame-oriented, you'll have to read them yourself. In cases where the number of fragments is known beforehand, this is as easy as adding an extra WebSocketReadSampler for each continuation frame you expect. If the number of continuation frames is not known, you need to create a loop to read all the continuation frames. For this purpose, the plugin provides a new JMeter variable called websocket.last_frame_final that indicates whether the last frame read was final. This enables you to write a simple loop with a standard JMeter While Controller; use the expression ${__javaScript(! ${websocket.last_frame_final},)} as condition. With a JMeter If Controller, the condition can be simplified to ! ${websocket.last_frame_final} because that controller automatically interprets the condition as JavaScript. See the sample Read continuation frames.jmx test plan for examples of using the While or the If controller to read continuation frames.
If you are unsure whether continuation frames are sent by your server or how much, switch on debug logging: samplers reading a frame will log whether the received frame is a "normal" single frame, a non-final frame (i.e. 1st fragment), a continuation frame or a final continuation frame (last fragment).

JMeter ignore specific types of responses in all Receive samplers (Websocket)

Is there a way for all Receive samplers to ignore specific responses in JMeter and wait for the one that we are interested?
To be more precise, we have created a jmx file that contains a large flow like a user would create on the browser. Each request sent is followed by a response, so we use a request handler followed by the corresponding receive handler for each call. And everything seems to work fine.
But there are cases that another kind of response may arrive, which is not the one we expect in our flow, but it is triggered by another independent mechanism. You can think of it like notifications sent to the user that is doing the flow and are independent of the flow itself, but theu are received in the channel (for us inside the websocket connection).
So we are trying to find a way to ignore a specific set of responses that may come while we are running the tests.
We firstly tried to add a While Controller in each receive sampler that checks if the content is of the desired type and if not loops again. But this solution has 3 disadvantages :
we have to add the sampler for the specific receive twice - one before the while element and one inside the element because we have to first extract the received data and while does not execute its contents before doing the while condition check
we have so many pairs of send-receive in our jmeter test script , that we have to add so many while controllers inside the script
since the received message may not be of the type we expect but another one that we want to ignore, then we cannot add a Response Assertion because it will fail if the notification arrives, so we have to verify the content indirect -> in the condition of the while loop
We use apache-jmeter-5.3.
So we are wondering if we could do another kind of configuration in order to avoid all these while loops.
It may be irrelevant to the solution, but we use websocket through "WebSocket Samplers by Peter Doornbosch".
Thanks
You don't have to, just amend your While Controller's condition to accept undefined variable as well
Sounds like a potential use case for using Module Controller to avoid code duplication
If you're getting the response you don't expect you can change the response body using JSR223 PostProcessor to the one you expect, example code
if (!prev.getResponseDataAsString().contains('foo')) {
prev.setResponseData('foo', 'UTF-8')
}

Possible to access TCP packet details with a go HTTP client?

I have a need to be able to validate TOS/DSCP marks on response data from a set of HTTP servers. Would it be possible, given a list of target URLs to test, if there is a way in go to generate the HTTP request, and then be able to examine the response's TCP packet details in order to obtain the TOS value?
My assumption at this point is that it may require creating a socket, and then dynamically generating a TCP packet that contains the HTTP request payload. I've been searching around to see if there were any libraries that would aid in this task, but haven't found anything specific yet.
Note: a simple TCP connection will not provide enough data - the target servers in question will alter TOS/DSCP marks dynamically based on the HTTP server name (so essentially, a single physical server will respond with different TOS marks depending on the vHost requested), so it is important to be able to verify the TOS on actual HTTP response packets, and not something simple like a ping. The TOS values in the TCP 3-way handshake cannot be trusted either - it must be a packet containing the HTTP data.
I did end up solving this problem using gopacket/pcap and net/http.
In a nutshell, what I ended up doing is writing a function that creates a channel, and then calls a goroutine that does the actual packet capture and parsing. The goroutine passes the captured TOS value back to the channel, and then the original function does the http request, and then reads the channel to get the TOS result. Still a bit of a work-in-progress, but so far, this solution seems to be working fairly well.

How do you know when all the data has been received by the Winsock control that has issued a POST or GET to an Web Server?

I'm using the VB6 Winsock control. When I do a POST to a server I get back the response as multiple Data arrival events.
How do you know when all the data has arrived?
(I'm guessing it's when the Winsock_Close event fires)
I have used VB6 Winsock controls in the past, and what I did was format my messages in a certain way to know when all the data has arrived.
Example: Each message starts with a "[" and ends with a "]".
"[Message Text]"
When data comes in from the DataArrival event check for the end of the message "]". If it is there you received at least one whole message, and possibly the start of a new one. If more of the message is waiting, store your message data in a form level variable and append to it when the DataArrival event fires the next time.
In HTTP, you have to parse and analyze the reply data that the server is sending back to you in order to know how to read it all.
First, the server sends back a list of CRLF-delimited header lines, which are terminated by a blank CRLF-delimited line by itself. You then have to look at the actual values of the 'Content-Length' and 'Transfer-Encoding' headers to know how to read the remaining data.
If there is no 'Transfer-Encoding' header, or if it does not contain a 'chunked' item in it, then the 'Content-Length' header specifies how many remaining bytes to read. But if the 'Transfer-Encoding' header contains a 'chunked' item, then you have to read and parse the remaining data in chunks, one at a time, in order to know when the data ends (each chunk reports its own size, and the last chunk reports a size of 0).
And no, you cannot rely on the connection being closed after the reply has been sent, unless the 'Connection' header explicitally says 'close'. For HTTP 1.1, that header is usually set to 'keep-alive' instead, which means the socket is left open so the client can send more requests on the same socket.
Read RFC 2616 for more details.
No, the Close event doesn't fire when all the data has arrived, it fires when you close the connection. It's not the Winsock control's job to know when all the data has been transmitted, it's yours. As part of your client/server communication protocol implementation, you have to tell the client what to expect.
Suppose your client wants the contents of a file from the server. The client doesn't know how much data is in the file. The exchange might go something like this:
client sends request for the data in the file
the server reads the file, determines the size, attaches the size to the beginning of the data (let's say it uses 4 bytes) that tells the client how much data to expect, and starts sending it
your client code knows to strip the first 4 bytes off any data that arrives after a file request and store it as the amount of data that is to follow, then accumulate the subsequent data, through any number of DataArrival events, until it has that amount
Ideally, the server would append a checksum to the data as well, and you'll have to implement some sort of timeout mechanism, figure out what to do if you don't get the expected amount of data, etc.

http-on-examine-response observer - possible to block response from further processing?

I am attempting to implement a firefox extension which filters incoming HTTP responses and handles them accordingly.
I wish to block HTTP responses containing a specific header. Having read through some of the MDC articles, it appears the most common way of observing HTTP responses is by registering an http-on-examine-response observer.
My question is: Using this observer, is it possible to block the HTTP request from further processing (as a by-product, the page will continue to wait for a response)? Or do I need to use some other facet of XPCOM (if so, care to point me in the right direction)?
Thanks in advance,Mike
Should be possible: the "subject" of that notification is a HTTP channel, on which you can call nsIRequest::cancel().
the page will not continue to wait for a response, though, since you blocked the response. Perhaps you've been actually looking for a way to alter an HTTP response?

Resources