Skip to content

Response(Bun.file) streams look like HTTP/0.9 over LAN  #26406

@iitzkube

Description

@iitzkube

What version of Bun is running?

1.3.6+d530ed993

What platform is your computer?

Darwin 23.6.0 arm64 arm

What steps can reproduce the bug?

When serving a static file with Response(Bun.file(...)), requests from other devices over LAN fail to open it. For example, iOS shows NSURLErrorDomain:-1017 (cannot parse response) and curl prints Received HTTP/0.9 when not allowed.

Important detail: this only happens when I access the server from another device over the LAN using a 192.168.x.x address. Accessing via localhost on the host machine works.

import { networkInterfaces } from 'node:os';

const filePath = 'sample.txt'; // make sure file exists

const server = Bun.serve({
  port: 8000,
  async fetch() {
    return new Response(Bun.file(filePath));
  },
});

const localIps = Object.values(networkInterfaces())
  .flatMap((entries) => entries ?? [])
  .filter((entry) => entry.family === 'IPv4' && !entry.internal)
  .map((entry) => entry.address);

console.log(`  Local: http://localhost:${server.port}`);
if (localIps.length === 0) {
  console.log('Network: No external address found');
} else {
  for (const ip of localIps) {
    console.log(`Network: http://${ip}:${server.port}`);
  }
}

What is the expected behavior?

The file should load normally (same as other methods mentioned under Additional information below).

What do you see instead?

Opening http://<host-lan-ip>:8000/ from devices on the same LAN over Wi-Fi does not serve the file correctly:

  • iOS Safari: NSURLErrorDomain:-1017 (cannot parse response)
  • curl: Received HTTP/0.9 when not allowed

This does not reproduce on the host machine via http://localhost:8000/.

Additional information

  • Specifying headers such as content-type, content-length, content-encoding, transfer-encoding does NOT fix the issue.

  • Works when replacing new Response(Bun.file(filePath)) with the following (even without specifying headers):

    const buffer = await Bun.file(filePath).arrayBuffer()
    return new Response(buffer)
  • Works when serving the file as a route routes: { '/': Bun.file(filePath) }.

  • Works in Node when replicating the repro above:

    Node implementation
    import { createReadStream } from 'node:fs';
    import { createServer } from 'node:http';
    import { networkInterfaces } from 'node:os';
    
    const filePath = 'sample.txt';
    
    const server = createServer((req, res) => {
      const stream = createReadStream(filePath);
      stream.on('error', () => {
        res.statusCode = 500;
        res.end('Failed to read file');
      });
      stream.pipe(res);
    });
    
    server.listen(8000, () => {
      const localIps = Object.values(networkInterfaces())
        .flatMap((entries) => entries ?? [])
        .filter((entry) => entry.family === 'IPv4' && !entry.internal)
        .map((entry) => entry.address);
      if (localIps.length === 0) {
        console.log('Network: No external IPv4 address found');
      } else {
        for (const ip of localIps) {
          console.log(`Network: http://${ip}:8000`);
        }
      }
    });

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions