2

I am using WebHooks in my API. So, once a request is processed our REST Service will POST a response back to the callback URL sent in the request.

Client             Server
  |(request)         |
  |----------------->|     
  |<-----------------|     ||
  |        (response)|     ||
  |                  |    _||_ Time
  |        (callback)|    \  /
  |<-----------------|     \/
  |----------------->|
  |(response)        |
  |                  |

How can this be stress tested with JMeter?

Dominic Cabral
  • 962
  • 9
  • 21

3 Answers3

2

You have to listen to incomming connections of certain port. Make sure you machine can be connected from outside. In JMeter you can use JSR223 Sampler and following Groovy script

def server = new ServerSocket(8080)
while (true) {
    server.accept { socket ->
        socket.withStreams { input, output ->
            def reader = input.newReader()
            log.info('Received request:')
            while ((line = reader.readLine()) != null) {
                log.info(line)
            }
        }
    }
}
Evgeny Makarov
  • 1,417
  • 1
  • 21
  • 41
2

It depends on WebHook implementation, if it is a matter of polling - you can just use While Controller to wait for callback in loops. The whole duration of the sequence can be measured using i.e. Transaction Controller

If the callback comes a a Server-Sent Event you can use i.e. JAX RS API which provides SseEventSource class which can be used for waiting for server-side events either in JSR223 Sampler or in Java Request sampler like described in Stress/Load-Testing of Asynchronous HTTP/REST Services with JMeter article

Dmitri T
  • 159,985
  • 5
  • 83
  • 133
0

My solution for webhook is here (JSR223 sampler)

import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

/* extract Content-Length: NUMBER */
def int extractContentLength(StringBuilder sb) {
    int length = 0;
    String[] lines = sb.toString().split("\\n"); 
    for (int i = 0; i < lines.length; i++) {
        String s = lines[i];
        // check if we have next line, thus ensuring we the whole number 
        if (s.toLowerCase().startsWith("Content-Length:".toLowerCase()) && i <= lines.length - 2 ) {
            String slength = s.substring(s.indexOf(":") + 1, s.length()).trim();
            length = Integer.parseInt(slength);
            //System.out.println("Length = " + length);
            log.info("Length = " + length)
            return length;
        }
    }
    return 0;
}

int port = Integer.parseInt(args[0]);
int delay = Integer.parseInt(args[1]);
log.info("Starting HTTP Server on port " + port + " and delay of " + delay);

StringBuilder outputString = new StringBuilder(1000);

ServerSocket serverSocket = new ServerSocket(port);
serverSocket.setSoTimeout(delay); // 3 minutes timeout
while (true) {

    outputString.setLength(0); // reset buff

    Socket clientSocket = serverSocket.accept(); // blocking
    PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);

    try {

        boolean isBodyRead = false;
        int dataBuffer;
        while ((dataBuffer = clientSocket.getInputStream().read()) != -1) {

            if (dataBuffer == 13) { // CR
                if (clientSocket.getInputStream().read() == 10) { // LF
                    outputString.append("\n");
                }
            } else {
                outputString.append((char) dataBuffer);
            }
            
            // do we have Content length
            int len = extractContentLength(outputString);
            if (len > 0) {
                int actualLength = len - 1; // Ker je treba odštet \r\n
                for (int i = 0; i < actualLength; i++) {
                    int body = clientSocket.getInputStream().read();
                    outputString.append((char) body);
                }
                isBodyRead = true;
                break;
            }

        } // end of reading while

        if (isBodyRead) {
            out.println("HTTP/1.1 200 OK");
            out.println("Connection: close");
            out.println(); // must have empty line for HTTP
            out.flush(); 
            out.close(); // close clients connection
        }

    } catch (IOException ioEx) {
        log.info(ioEx.getMessage());
    }

    log.info(outputString.toString());
    break; // stop server - break while true
    
} // end of outer while true

serverSocket.close();

Test CURL script

curl -X POST -H "Content-Type: application/json" -H "Connection: close" -d '{"name": "gustinmi", "email": "gustinmi at google dot com "}' -v http://localhost:8081/

Java version: Simple HTTP server in Java using only Java SE API

Configuration for JSR223 Sampler

enter image description here

Mitja Gustin
  • 1,723
  • 13
  • 17