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

An explicit host header is ignored if the request url has no implicit host #245

Closed
ggoodman opened this issue Apr 3, 2019 · 0 comments
Closed
Assignees
Labels
bug
Milestone

Comments

@ggoodman
Copy link
Contributor

@ggoodman ggoodman commented Apr 3, 2019

In the code below, the options.headers.host header value will be disregarded and replaced with either: 1) the host implied by the url; or 2) an empty ('') value. The resulting Host header will then be invalid. Further, it is possible that there is ambiguity which Host header is used if the options.header.Host was set, given that we don't consider header casing.

wreck/lib/index.js

Lines 131 to 132 in e4be576

uri.headers = options.headers || {};
uri.headers.host = uri.host;

This breaks any use-case where wreck is being used as a reverse proxy and the full downstream url is not being reconstructed and passed in as the target url. As a result, h2o2 is likely affected as well.

Affected versions:

  • wreck@14.2.0 (latest version in 14.x has this regression)
  • wreck@15.0.0
  • @hapi/wreck@15.0.0

Reproduction:

//@ts-check
"use strict";

const Fs = require("fs");
const Http = require("http");
const Wreck = require("wreck");
const Util = require("util");

const unlink = Util.promisify(Fs.unlink);

async function main() {
  const server = Http.createServer((req, res) => {
    res.writeHead(200, { "Content-Type": "application/json" });
    res.end(JSON.stringify(req.headers.host));
  });
  const socketPath = "/tmp/wreck-bug-repro.sock";
  const host = "myhost";

  try {
    await unlink(socketPath);
  } catch (err) {
    if (err.code !== "ENOENT") throw err;
  }

  await new Promise(resolve => server.listen(socketPath, resolve));

  let res;

  // This works
  res = await Wreck.get(`http://${host}/path`, {
    json: true,
    socketPath
  });

  console.log(res.payload === host ? "✅ %s === %s" : "❌ %s !== %s", res.payload, host, 'With the host in the request url')

  // This fails
  res = await Wreck.get(`/path`, {
    headers: {
      host,
    },
    json: true,
    socketPath
  });

  console.log(res.payload === host ? "✅ %s === %s" : "❌ %s !== %s", res.payload, host, 'With no host in the request url but a host header via options')

  await new Promise((resolve, reject) => server.close(err => err? reject(err) : resolve()));
}

main().then(
  () => {
    process.exit(0);
  },
  err => {
    console.trace(err);
    process.exit(1);
  }
);
@geek geek closed this in #246 Apr 3, 2019
@geek geek added this to the 15.0.1 milestone Apr 3, 2019
@geek geek added the bug label Apr 3, 2019
@geek geek self-assigned this Apr 3, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.