如何从NodeJS中的缓冲区流范围HTTP请求

时间:2019-07-12 18:19:34

标签: node.js http buffer nodejs-stream http-range

在流式传输时,在节点中测试http范围请求

const url2 = "https://www.sportsbookreview.com/betting-odds/nba-basketball/money-line/?date=20190311"
async function main(){
    const client = webdriverio.remote({
        desiredCapabilities: {
            browserName: "chrome",
            deprecationWarnings: "false"
        }
    })
    await client.init();
    await client.url(url2);
    await client.waitForVisible("#bettingOddsGridContainer", 10000);
    await client.click("#bettingOddsGridContainer > div:nth-child(3) > div:nth-child(4) > div:nth-child(3) > div > div > div:nth-child(1) > i");
}

对于http服务器的http let rightArrowExist = await client.isExisting("#bettingOddsGridContainer > div:nth-child(3) > div:nth-child(4) > div:nth-child(3) > div > div > div:nth-child(1) > i"); ,来自节点的http客户端会接受它。

但是,当我通过管道传输缓冲区流时,

fs.createReadStream('index.html').pipe(res)

Curl和浏览器接受它,但NodeJS res客户端除外,它抛出:

const content = fs.readFileSync("src/index.html");
const stream = new Readable();

stream.push(
  opts.start && opts.end
    ? content.slice(opts.start, opts.end + 1)
    : content
);
stream.push(null);

stream.pipe(res);

要对其进行测试,只需将第56行从http更改为events.js:180 throw er; // Unhandled 'error' event ^ Error: Parse Error at Socket.socketOnData (_http_client.js:452:22) at Socket.emit (events.js:203:13) at addChunk (_stream_readable.js:294:12) at readableAddChunk (_stream_readable.js:275:11) at Socket.Readable.push (_stream_readable.js:210:10) at TCP.onStreamRead (internal/stream_base_commons.js:166:17) Emitted 'error' event at: at Socket.socketOnData (_http_client.js:458:9) at Socket.emit (events.js:203:13) [... lines matching original stack trace ...] at TCP.onStreamRead (internal/stream_base_commons.js:166:17) { bytesParsed: 234, code: 'HPE_INVALID_CONSTANT', reason: 'Expected HTTP/' }

'read'

'buffer'

index.js

const http = require("http");
const fs = require("fs");
const Readable = require("stream").Readable;

const stats = fs.statSync("index.html");

const handler = function(read_or_buffer) {
  return function(req, res) {
    let code = 200;
    const opts = {};
    const headers = {
      "Content-Length": stats.size,
      "Content-Type": "text/html",
      "Last-Modified": stats.mtime.toUTCString()
    };

    if (req.headers.range) {
      code = 206;

      let [x, y] = req.headers.range.replace("bytes=", "").split("-");
      let end = (opts.end = parseInt(y, 10) || stats.size - 1);
      let start = (opts.start = parseInt(x, 10) || 0);

      if (start >= stats.size || end >= stats.size) {
        res.setHeader("Content-Range", `bytes */${stats.size}`);
        res.statusCode = 416;
        return res.end();
      }

      headers["Content-Range"] = `bytes ${start}-${end}/${stats.size}`;
      headers["Content-Length"] = end - start + 1;
      headers["Accept-Ranges"] = "bytes";
    }

    res.writeHead(code, headers);

    if (read_or_buffer == "read")
      fs.createReadStream("index.html", opts).pipe(res);

    if (read_or_buffer == "buffer") {
      const content = fs.readFileSync("index.html");
      const stream = new Readable();

      stream.push(
        opts.start && opts.end
          ? content.slice(opts.start, opts.end + 1)
          : content
      );
      stream.push(null);

      stream.pipe(res);
    }
  };
};

http.createServer(handler("read")).listen(8080);

// TESTS

const options = { headers: { Range: "bytes=0-4" } };

http.get("http://127.0.0.1:8080/", options, response => {
  let data = "";
  response.on("data", chunk => (data += chunk));
  response.on("end", () => {
    console.log(data);
    process.exit();
  });
});

1 个答案:

答案 0 :(得分:0)

服务器收到从0开始的http范围请求时:

opts.start && opts.end

计算为false,因为opts.start0,因此代码发送的是整个缓冲区,而不是预期的分片。

由于NodeJS严格符合HTTP规范,因此它不接受请求。


解决方案是验证opts.start是否存在,zero

opts.start || opts.start === 0 && opts.end