Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proxyman removes all original response headers on Server-Sent event connections #471

Open
AlexanderShirokih opened this issue Jan 29, 2025 · 2 comments
Assignees
Labels
bug Something isn't working

Comments

@AlexanderShirokih
Copy link

Description

When establishing a Server-Sent Events (SSE) connection through Proxyman, all headers originally sent by the server are missing from the response. Instead, Proxyman appears to replace them with its own headers (for example, adding Transfer-Encoding: chunked and omitting the original Content-Type: text/event-stream). Because OkHttp-SSE depends on the Content-Type: text/event-stream header to process SSE, the connection cannot be established while the proxy is enabled.

Steps to Reproduce

I wrote a simple Node.js program to demonstrate the erroneous behavior, replicating the headers used by a real client-server application. To confirm that the problem wasn’t due to a specific server or client, I used low-level mechanisms—like raw sockets—to verify that everything worked as expected.

const http = require('http');
const url = require('url');
const net = require('net');

const server = net.createServer((socket) => {
  const headers = [
    'HTTP/1.1 200 OK',
    'server: nginx/1.26.1',
    'date: Wed, 29 Jan 2025 15:37:11 GMT',
    'content-type: text/event-stream',
    'connection: Keep-Alive',
    'cache-control: no-cache',
    'some-custom-header: test',
    '',
    ''
  ].join('\r\n');

  socket.write(headers);

  let counter = 0;
  const intervalId = setInterval(() => {
    socket.write(`data: Event ${counter++}\r\n\r\n`);
  }, 1000);

  socket.on('close', () => clearInterval(intervalId));
});

server.listen(8081, () => {
  console.log('SSE server running on port 8081');
});


function startClient(targetUrl) {
    const proxy = { hostname:'192.168.0.9', port: 9091 };

    const options = {
        protocol: 'http:',
        hostname: proxy.hostname,
        port: proxy.port,
        path: targetUrl, 
        headers: {
            'Host': 'localhost:8081',
            'Connection': 'Keep-Alive',
            'Accept': 'text/event-stream',
            'Accept-Encoding': 'gzip',
            'User-Agent': 'okhttp/4.12.0'
        }
    };

    const req = http.request(options, (res) => {
        Object.entries(res.headers).forEach(([key, value]) => {
            console.log(`${key}: ${value}`);
        });
    });

    req.end();
}

startClient('http://localhost:8081/events');

Current Behavior

When running through proxy, the program output is as follows:

date: Wed, 29 Jan 2025 21:07:46 GMT
connection: keep-alive
keep-alive: timeout=5
transfer-encoding: chunked

No Content-type, and all the other headers, but in the Proxyman window, I see that the server is sending the correct headers.

Image

Expected Behavior

When Proxyman is on, the orignal headers are kept in the proxy output.

server: nginx/1.26.1
date: Wed, 29 Jan 2025 21:07:11 GMT
content-type: text/event-stream
connection: Keep-Alive
cache-control: no-cache
some-custom-header: test

Environment

Proxyman Version 2.19.0 (21900) | Linux (Build 6.11.0-14-generic)

@AlexanderShirokih AlexanderShirokih added the bug Something isn't working label Jan 29, 2025
@AlexanderShirokih
Copy link
Author

Additionaly, i tried using the cURL client.

curl -v \
  --noproxy '' \
  --proxy http://192.168.0.9:9091 \
  -H "Accept: text/event-stream" \
  "127.0.0.1:8081"

Output on Linux through Proxyman Version 2.19.0:

* Connected to 192.168.0.9 (192.168.0.9) port 9091
> GET http://127.0.0.1:8081/ HTTP/1.1
> Host: 127.0.0.1:8081
> User-Agent: curl/8.9.1
> Proxy-Connection: Keep-Alive
> Accept: text/event-stream
> 
* Request completely sent off
< HTTP/1.1 200 OK
< Date: Wed, 29 Jan 2025 21:35:52 GMT
< Connection: keep-alive
< Keep-Alive: timeout=5
< Transfer-Encoding: chunked

However, it works as expected with Proxyman 5.14.0 on macOS:

curl -v \
  --proxy http://192.168.0.3:9090 \
  -H "Accept: text/event-stream" \
  "http://192.168.0.9:8081"
*   Trying 192.168.0.3:9090...
* Connected to 192.168.0.3 (192.168.0.3) port 9090
> GET http://192.168.0.9:8081/ HTTP/1.1
> Host: 192.168.0.9:8081
> User-Agent: curl/8.6.0
> Proxy-Connection: Keep-Alive
> Accept: text/event-stream
> 
< HTTP/1.1 200 OK
< server: nginx/1.26.1
< date: Wed, 29 Jan 2025 15:37:11 GMT
< content-type: text/event-stream
< connection: Keep-Alive
< cache-control: no-cache
< some-custom-header: test
< transfer-encoding: chunked

Furthermore, SSE doesn't work in Postman or in the browser when the proxy is enabled.

@AlexanderShirokih AlexanderShirokih changed the title Proxyman removes all original response headers on Server-Sents event connections Proxyman removes all original response headers on Server-Sent event connections Jan 30, 2025
@kics223w1 kics223w1 self-assigned this Jan 31, 2025
@kics223w1
Copy link

@AlexanderShirokih Thank you for reporting this issue. We can reproduce this and we are fixing it 👍🏻

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
Development

No branches or pull requests

2 participants