Effective Methods to Verify HTTP Keep-Alive Functionality from Client-Side: Tools and Code Examples


1 views

When testing HTTP keep-alive functionality from the client side, we need to examine both the connection behavior and the actual HTTP headers. Here are several professional approaches:

Modern browsers provide network inspection capabilities:

// Chrome DevTools example:
1. Open DevTools (F12)
2. Navigate to Network tab
3. Enable "Preserve log"
4. Look for "Connection: keep-alive" in response headers
5. Check if multiple requests reuse the same connection ID

cURL provides detailed connection information:

curl -Iv http://example.com --http1.1 2>&1 | grep -i "keep-alive\|connection"

// Alternative verbose version:
curl -v http://example.com --http1.1 -o /dev/null
// Look for "Re-using existing connection" in output

For deep inspection of TCP connections:

1. Capture network traffic with Wireshark
2. Filter with: tcp.port == 80 || tcp.port == 443
3. Check TCP handshake (SYN/SYN-ACK/ACK)
4. Subsequent requests should reuse same connection
5. Look for FIN packets indicating connection closure

Programmatic verification with connection pooling:

import requests
from requests.adapters import HTTPAdapter

session = requests.Session()
adapter = HTTPAdapter(pool_connections=1, pool_maxsize=1)
session.mount('http://', adapter)

# First request establishes connection
response1 = session.get('http://example.com')
print("Connection:", response1.headers.get('Connection'))

# Second request should reuse connection
response2 = session.get('http://example.com/page2')
print("Reused connection:", response2.raw._connection)

# Verify with netstat:
# netstat -an | grep ESTABLISHED | grep 80

Professional utilities for connection analysis:

# Using httptrace
httptrace -H "Connection: keep-alive" http://example.com

# Using Apache Benchmark (ab)
ab -k -c 10 -n 100 http://example.com/
# The -k flag enables keep-alive

When troubleshooting keep-alive issues, check:

  • Server configuration (Apache KeepAliveTimeout, Nginx keepalive_timeout)
  • Intermediate proxies that might close connections
  • Client-side connection pool settings
  • HTTP/1.1 vs HTTP/2 behavior differences

HTTP/2 always uses persistent connections:

curl --http2 -v https://example.com
# Look for "Using HTTP2, server supports multi-use"

The most definitive way to verify keep-alive is packet-level inspection. Capture traffic while making multiple requests:


1. Start Wireshark capture
2. Filter with: tcp.port == 80 || tcp.port == 443
3. Make consecutive requests to target server
4. Check TCP handshake occurrences:
   - Single handshake for multiple requests = keep-alive working
   - Multiple handshakes = keep-alive failing

Use CURL's verbose mode to inspect connection reuse:


curl -Iv --http1.1 https://example.com
curl -Iv --http1.1 https://example.com/second-page

Key indicators in output:


* Connection #0 to host example.com left intact
* Re-using existing connection! (#0) with host example.com

Modern browsers provide network connection inspection:

  1. Open DevTools (F12) → Network tab
  2. Enable "Preserve log"
  3. Make multiple requests
  4. Check "Connection ID" column (Chrome/Edge)
  5. Same ID = connection reused

Programmatic verification with connection pooling:


import requests
from requests.adapters import HTTPAdapter

session = requests.Session()
adapter = HTTPAdapter(pool_connections=1, pool_maxsize=1)
session.mount('http://', adapter)

# First request
response1 = session.get('http://example.com')
print(f"Initial connection: {response1.raw._connection}")

# Second request
response2 = session.get('http://example.com/about')
print(f"Reused connection: {response2.raw._connection}")

Verify keep-alive headers in server responses:


HTTP/1.1 200 OK
Connection: keep-alive
Keep-Alive: timeout=5, max=100

Test using telnet:


telnet example.com 80
GET / HTTP/1.1
Host: example.com
Connection: keep-alive

Benchmark difference with/without keep-alive:


ab -n 1000 -c 10 -k http://example.com/  # With keep-alive
ab -n 1000 -c 10 http://example.com/     # Without keep-alive

Compare "Requests per second" metrics - keep-alive should show better performance.

Test connection reuse programmatically:


const http = require('http');
const agent = new http.Agent({ keepAlive: true });

function makeRequest(path) {
  return new Promise((resolve) => {
    const req = http.request({
      host: 'example.com',
      port: 80,
      path: path,
      agent: agent
    }, (res) => {
      resolve(res.socket._handle.fd);
    });
    req.end();
  });
}

(async () => {
  const fd1 = await makeRequest('/');
  const fd2 = await makeRequest('/contact');
  console.log(Same socket? ${fd1 === fd2});
})();