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

fix: use :authority header of http2 requests as host #1262

Merged
merged 1 commit into from
Oct 23, 2018

Conversation

mgjm
Copy link
Contributor

@mgjm mgjm commented Oct 19, 2018

The now stable http2 api does not use the host header. The host can be found in the http2 :authority header. Therefore koa should use this header instead.

This fixes the host property and all properties that depend on it for http2 requests. These dependent properties include the hostname, the origin and the URL. This will also fix #1174.

@codecov
Copy link

codecov bot commented Oct 19, 2018

Codecov Report

Merging #1262 into master will not change coverage.
The diff coverage is 100%.

Impacted file tree graph

@@          Coverage Diff           @@
##           master   #1262   +/-   ##
======================================
  Coverage     100%    100%           
======================================
  Files           5       5           
  Lines         391     392    +1     
======================================
+ Hits          391     392    +1
Impacted Files Coverage Δ
lib/request.js 100% <100%> (ø) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 9146024...350f5e1. Read the comment docs.

@fengmk2
Copy link
Member

fengmk2 commented Oct 19, 2018

I think this should be feature not bug fix?

@fengmk2
Copy link
Member

fengmk2 commented Oct 19, 2018

cc @dead-horse

@@ -252,6 +252,7 @@ module.exports = {
get host() {
const proxy = this.app.proxy;
let host = proxy && this.get('X-Forwarded-Host');
if (this.req.httpVersionMajor >= 2) host = this.get(':authority');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be an undocumented property. Is it save to use it and should koa use undocumented props?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's unsafe either way, at least this.req.authority is a specific getter with a sane naming that conforms with the RFC headerfield.

Copy link
Contributor Author

@mgjm mgjm Oct 22, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this.req.headers is the documented way to access http headers and this.get is using this way. And :authority is the official header name from RFC 7540. So this way should not be unsafe.

Whereas this.req.authority is not documented and therefore could change in a minor update and is considered an internal API (as described in the node COLLABORATOR_GUIDE).

But I agree that this.req.authority should be part of the public API and I just created an issue in the node repo (nodejs/node#23825).

@fengmk2 fengmk2 merged commit 9c5c58b into koajs:master Oct 23, 2018
@fengmk2
Copy link
Member

fengmk2 commented Oct 23, 2018

2.6.0

@panva
Copy link
Contributor

panva commented Oct 23, 2018

The requested change to keep x-forwarded values as host is not in?

@mgjm
Copy link
Contributor Author

mgjm commented Oct 23, 2018

@panva The current order is...

  1. If app.proxy the X-Forwarded-Host header
  2. If HTTP/2 the :authority header
  3. The Host header

(See lib/request.js)

@panva
Copy link
Contributor

panva commented Oct 23, 2018

Yeah, as requested in the review by @dead-horse

If app.proxy was set, I'd like to keep the X-Forwarded-Host set by reverse proxy(nginx).

And in my practice, when client request nginx with http 1/2 and nginx proxy to node server, it always use X-Forwarded-Host, it is a de-facto standard for reverse proxy to set host when visit upstream.

But the fact is :authority will overwrite what's in the x-forwarded-host if proxy is true (looking at master)

It should be like this imho

if (this.req.httpVersionMajor >= 2) host = host || this.get(':authority');

@dead-horse
Copy link
Member

  1. If app.proxy the X-Forwarded-Host header
  2. If HTTP/2 the :authority header
  3. The Host header

I think this works for me, X-Forwarded-Host is set by reverse proxy, we just trust the proxy when app.proxy is true. Otherwise we detect HTTP 1 / HTTP 2 to choose which header we should use to get host.

@panva
Copy link
Contributor

panva commented Oct 23, 2018

I agree, but the implementation takes :authority over x-forwarded-host.

@fengmk2
Copy link
Member

fengmk2 commented Oct 23, 2018

@panva I will release a bugfix version soon.

@panva
Copy link
Contributor

panva commented Oct 23, 2018

@fengmk2 perfect!

@fengmk2
Copy link
Member

fengmk2 commented Oct 23, 2018

#1263

@mgjm
Copy link
Contributor Author

mgjm commented Oct 23, 2018

@panva Good catch. @fengmk2 Thanks for the quick fix 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ctx.request.origin is wrong
6 participants