Skip to content

Path-based routes fail when the Host header includes a port #8471

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

Closed
elyscape opened this issue Apr 12, 2016 · 3 comments
Closed

Path-based routes fail when the Host header includes a port #8471

elyscape opened this issue Apr 12, 2016 · 3 comments

Comments

@elyscape
Copy link
Contributor

Path-based routes are not correctly dispatched if the client includes the port in the Host header. While including the port number in requests to HTTP(S) endpoints on standard port numbers is unusual, it is not against the spec, and some clients force it.

Version
openshift v1.1.4
kubernetes v1.2.0-origin-41-g91d3e75
etcd 2.2.5
Steps To Reproduce
  1. Save root.yml and subpath.yml from this gist to your system.
  2. Create the service for the root route: oc create -f root.yml. This creates a service using a simple nginx container that serves this content.
  3. Create a route for the service: oc expose svc nginx-root --hostname=pathtest.$ROUTERDOMAIN
  4. Create the service for the path-based route: oc create -f subpath.yml. This creates a service using the same nginx container that serves this content.
  5. Create a path-based route for the service: oc expose svc nginx-subpath --hostname=pathtest.$ROUTERDOMAIN --path=/subdir/
  6. curl the root: curl http://pathtest.$ROUTERDOMAIN/
  7. curl the subdir: curl http://pathtest.$ROUTERDOMAIN/subdir/
  8. curl the subdir with the port in the Host header: curl -H 'Host: pathtest.$ROUTERDOMAIN:80' http://pathtest.$ROUTERDOMAIN/subdir/
Current Result
# oc create -f root.yml 
imagestream "origin-path-nginx" created
deploymentconfig "nginx-root" created
service "nginx-root" created
# oc expose svc nginx-root --hostname=pathtest.apps.redacted.com
route "nginx-root" exposed
# oc create -f subpath.yml 
deploymentconfig "nginx-subpath" created
service "nginx-subpath" created
Error from server: imagestreams "origin-path-nginx" already exists
# oc expose svc nginx-subpath --hostname=pathtest.apps.redacted.com --path=/subdir/
route "nginx-subpath" exposed
# curl http://pathtest.apps.redacted.com/
This is the master server.
# curl http://pathtest.apps.redacted.com/subdir/
This is the child server.
# curl -H 'Host: pathtest.apps.redacted.com:80' http://pathtest.apps.redacted.com/subdir/
This is still the master server.

The last step outputs This is still the master server.

Expected Result

The last step should instead output This is the child server.

This is a result of using map_beg in HAProxy against base, which is defined as "the concatenation of the first Host header and the path part of the request". In other words, in the last request, base is equal to pathtest.apps.redacted.com:80/subdir/, which does not match pathtest.apps.redacted.com/subdir/.

@elyscape
Copy link
Contributor Author

It occurs to me that a simpler reproduction case would be to not bother with the root service at all:

Steps To Reproduce
  1. Create the service for the path-based route: oc create -f subpath.yml
  2. Create a path-based route for the service: oc expose svc nginx-subpath --hostname=pathtest.$ROUTERDOMAIN --path=/subdir/
  3. curl the subdir: curl http://pathtest.$ROUTERDOMAIN/subdir/
  4. curl the subdir with the port in the Host header: curl -H 'Host: pathtest.$ROUTERDOMAIN:80' http://pathtest.$ROUTERDOMAIN/subdir/
Current Result
# oc create -f subpath.yml 
deploymentconfig "nginx-subpath" created
service "nginx-subpath" created
Error from server: imagestreams "origin-path-nginx" already exists
# oc expose svc nginx-subpath --hostname=pathtest.apps.redacted.com --path=/subdir/
route "nginx-subpath" exposed
# curl http://pathtest.apps.redacted.com/subdir/
This is the child server.
# curl -H 'Host: pathtest.apps.redacted.com:80' http://pathtest.apps.redacted.com/subdir/
<html>
  <body>
    <h1>503 Service Unavailable</h1>
    No server available to handle the request.
  </body>
</html>

The last step results in an HTTP 503 error.

Expected Result

The last step should instead output This is the child server.

@elyscape
Copy link
Contributor Author

Okay, I did some experimentation and modifying the template to add another line with the correct port does indeed work. I'll submit a pull request shortly.

@elyscape
Copy link
Contributor Author

I have submitted #8490, which provides a solution to this issue.

elyscape added a commit to elyscape/origin that referenced this issue Apr 21, 2016
elyscape added a commit to elyscape/origin that referenced this issue Apr 25, 2016
This is done to support path-based routing for clients that include the
port number in the Host header. While unusual, doing so isn't against
the HTTP spec, and some clients force it.

Fixes openshift#8471.
elyscape added a commit to elyscape/origin that referenced this issue Apr 25, 2016
This is done to support path-based routing for clients that include the
port number in the Host header. While unusual, doing so isn't against
the HTTP spec, and some clients force it.

Fixes openshift#8471.
elyscape added a commit to elyscape/origin that referenced this issue Apr 26, 2016
This is done to support path-based routing for clients that include the
port number in the Host header. While unusual, doing so isn't against
the HTTP spec, and some clients force it.

Fixes openshift#8471.
elyscape added a commit to elyscape/origin that referenced this issue Apr 27, 2016
This is done to support path-based routing for clients that include the
port number in the Host header. While unusual, doing so isn't against
the HTTP spec, and some clients force it.

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

No branches or pull requests

3 participants