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

Supporting alternate Host header for XMLHttpRequest requests #203

Closed
subnetmarco opened this issue May 6, 2015 · 27 comments · Fixed by #246
Closed

Supporting alternate Host header for XMLHttpRequest requests #203

subnetmarco opened this issue May 6, 2015 · 27 comments · Fixed by #246
Labels
task/feature Requests for new features in Kong

Comments

@subnetmarco
Copy link
Member

XMLHttpRequest doesn't allow to explicitly set a Host header, so we would need to support an alternate header like X-Host.

http://www.w3.org/TR/XMLHttpRequest/#the-setrequestheader()-method

@rsdevigo
Copy link

rsdevigo commented May 6, 2015

It has a problem, from the moment you create a custom header, for example X-Host, the browser makes this request in a request with the OPTIONS method so that it seeks to know whether the server supports this header, therefore the value this header is not visible in "resolver.access" and so kong not know which address to send this api options requisition.

It has two solutions:

  • The kong treat this request the OPTIONS type, only way for all apis he owns.
  • Besides you can put the public_dns the Host header, be possible to access the api via: http: // kong: 8000 / api_id

rsdevigo added a commit to rsdevigo/kong that referenced this issue May 8, 2015
@GuilhermeBenites
Copy link

+1

@subnetmarco
Copy link
Member Author

@rsdevigo Kong should handle the OPTIONS request and automatically add X-Host to the Access-Control-Allow-Headers header.

@thibaultcha
Copy link
Member

side note: this is not a request because it is something we need to do, we are not just considering it. Otherwise any issue is a request. This is closer to a bug.

@rsdevigo
Copy link

So @thefosk, I think if the kong handle the OPTIONS request, it´s dangerous, cause sometimes the request may come with custom header besides X-Host, and sometimes I want that my API handle this request. Or I mistaken somewhere ?

@subnetmarco
Copy link
Member Author

If we decide to implement the X-Host solution, Kong will append the header to the list of headers that the API might return, so any scenario will be handled. So that everything can happen in one request.

@rsdevigo
Copy link

So, the idea is:

  • Client -> do a GET|POST|PUT|DELETE request with X-Host, the browser do a preflight request with Method: OPTIONS and just a custom header list without their values is sent.
  • Kong -> Receive this OPTIONS request and answer Access-Control-Allow-Headers : "X-Host".
    Client Browser -> Do the GET request with the X-Host value.
  • Kong -> Receive the GET|POST|PUT|DELETE and get the X-Host value and proxy to the API target_url the request ?

Is it ?

@subnetmarco
Copy link
Member Author

  • The client makes an HTTP request to the API setting an additional X-Host header. The browser will execute an OPTIONS requests before executing the real request.
  • Kong will proxy the OPTIONS request to the final API, and before returning the response to the browser it will append X-Host to whatever Access-Control-Allow-Headers the API returned.
  • The browser now knows that the request conditions are valid (including the X-Host header), and executes the HTTP request.

@rsdevigo
Copy link

I got it, but how the kong know the api public_dns if the x-host value it does not go with the OPTIONS request ? Or go ?

@saaslink
Copy link

Not able to use Postman to test Kong calls. Though it allows "Host" header it actually doesn't get parsed since Chrome strips restricted headers including "Host".

@subnetmarco
Copy link
Member Author

@rsdevigo I will post more info on this issue once I think about the implementation

@montanaflynn
Copy link

Could Kong just look for both Host and X-Host-Override headers and replace the Host header going upstream with the value from X-Host-Override if it exists?

@thibaultcha thibaultcha added this to the 0.3.0 milestone May 14, 2015
@thibaultcha thibaultcha self-assigned this May 14, 2015
thibaultcha added a commit that referenced this issue May 18, 2015
Proxying can now be triggered via a `Host` or a `X-Host-Override`
header. Multiple values can be given to each of those headers.

Fix #203
@thibaultcha
Copy link
Member

#246 supports Host or X-Host-Override. Sounds good?

@rsdevigo
Copy link

Yes, sounds good, but u test with XMLHttpRequest and angularJS preflight requests ?
When the angularJS application send a OPTIONS request the value of X-Host-Override does not exist, just the name of custom header.
How the Kong get this value to proxy the OPTIONS request ?

@thibaultcha
Copy link
Member

I'm not really sure if this issue is about allowing a custom header for restricted headers on browsers or about the OPTIONS request. What is really needed, here?

@rsdevigo
Copy link

I agree that now there is a way to make a XMLHttpRequest without using the browser for it, with this branch the kong can redirect the request to the API. But when the matter came up in the chat was to use the kong with a client written in angularjs.
I do not know if the issue was made thinking about it. But without a solution to this kind of request the kong can not work with libraries as angularjs and browsers.
I see that there should be another issue to deal with CORS and then XMLHttpRequests requests.

@thibaultcha
Copy link
Member

From what I've read we want several things here:

  1. @thefosk Be able to set a non-restricted header from the browser that can allow Kong to know what API we are proxying (X-Host or X-Host-Override).
  2. @thefosk + @rsdevigo Proxy preflight requests to upstream. This means finding a way for Kong to know what API is being used in an OPTIONS request.
  3. @montanaflynn When a preflight request is happening, allow to replace the upstream request's Host with a custom value.

As of today:

  1. This is implemented in [feature] support for alternate Host header #246.
  2. I don't see a way to do that, except with the path resolver coming in 0.3, see [request] support for routing based on path? #192.
  3. It requires 2, and I'm not sure why we would want to do that? Currently the requests going to upstream have Host set to the upstream's domain name, as expected. The issue is more in 2.

On a side note, keep in mind that if you want to use Kong from your browser you can use the CORS plugin. It will not proxy preflight requests to the end API by default (see kong/plugins/cors/access.lua#L63), but this issue raises concerns about it since like @rsdevigo said, if one uses the CORS plugin with preflight_continue=true from the browser, I don't see how Kong gets the public_dns of the API, I need to test this.

To conclude: we support a custom header, I do not see a way to proxy preflight requests with this resolver, but one can use the CORS plugin to perform browser calls (needs to be tested but probably still no preflight requests).

Please feel free to give me more infos on this if I'm missing anything.

thibaultcha added a commit that referenced this issue May 19, 2015
Proxying can now be triggered via a `Host` or a `X-Host-Override`
header. Multiple values can be given to each of those headers.

Fix #203
@montanaflynn
Copy link

@thibaultcha I think you misunderstood me.

Could Kong just look for both Host and X-Host-Override headers and replace the Host header going upstream with the value from X-Host-Override if it exists?

Meaning if I curl 127.0.0.1:8000 -H "x-host-override: publicapis.com" and I have an API with the public_dns of publicapis.com it would still work. This is what I believe #246 did.

@thibaultcha
Copy link
Member

Oh ok, then yes it is what @thefosk originally described in the first comment of this issue, and it is #246.

@subnetmarco
Copy link
Member Author

I now fully understand what @rsdevigo was trying to say, I completely misunderstood his point. As he was trying to explain, the problem here is that the preflight OPTIONS request that the browser sends to Kong doesn't support any additional header, not even X-Host-Override.

Because of this, Kong will never know what is the API consumed, unless the API has a path resolver configured. The options we have here are:

  • The Kong resolver itself handles CORS, and it will just accept any API regardless of the CORS plugin configuration (but what if I don't want CORS on that API? Why do we need a CORS plugin at this point if it is handled by the Kong resolver?)
  • CORS is only supported when:
    • A path resolver is being used (no need to send additional headers, Kong will detect the API by the requested endpoint)
    • A fully configured public DNS is being used (which will make it work in production, but not when developing). Not really an acceptable solution, unless both the path and the public DNS are being set, and the path is used in development, and the public DNS in production.
  • [DIRTY TRICK] Or the only other possibility is to send the public_dns as one of the Access-Control-Request-Headers values, that will then be handled by Kong. This will work because the only thing a browser can change is the value of Access-Control-Request-Headers, the OPTIONS request will look like:
OPTIONS / HTTP/1.1
Host: localhost:8000
Access-Control-Request-Headers: accept, test.com
Access-Control-Request-Method: GET
Origin: website.com

Kong will then parse the header, and try to resolve an API based on those values.

I may be wrong but basically whatever we decide to do, the X-Host-Override is just useless and can be removed.

@subnetmarco subnetmarco reopened this Jul 15, 2015
@subnetmarco
Copy link
Member Author

I have reopened the issue because clearly the previous solution is not satisfactory anymore.

@thibaultcha
Copy link
Member

The problem was understood and discussed here. See:

I don't see a way to do that, except with the path resolver coming in 0.3,

The path resolver (now available) is still the only way. I don't like the dirty hack though.

However supporting X-Host-Override does cover one use case:

  1. Browser makes a request to Kong
  2. Kong has no idea which API is requested at this point, correct, this has been discussed here
  3. But this Kong instance was configured to allow CORS for all its APIs (not currently possible)
  4. Kong replies 204 to the preflight request and specifies X-Host-Override as an allowed header
  5. Browser makes the request with X-Host-Override
  6. Kong knows which API the browser is requesting and proxies the request

If we only keep Host, then one can only query Kong with the DNS resolver (the public_dns value) when the domain name has an A record pointing to the Kong instance. Which is not an ideal development setup.

That being said, I am fine with removing X-Host-Override.

@thibaultcha thibaultcha removed their assignment Aug 21, 2015
ctranxuan pushed a commit to streamdataio/kong that referenced this issue Aug 25, 2015
Proxying can now be triggered via a `Host` or a `X-Host-Override`
header. Multiple values can be given to each of those headers.

Fix Kong#203
@subnetmarco subnetmarco removed this from the 0.3.0 milestone Oct 15, 2015
@thibaultcha thibaultcha added [about] resolver task/feature Requests for new features in Kong labels Oct 15, 2015
@EwanValentine
Copy link

Should this not be and issue any longer? I'm attempting to send form data from a React application via Kong and I'm getting OPTIONS 405 when I do a POST request. The Host value isn't what I'm sending in the original request either.

@EwanValentine
Copy link

Anyone?

@subnetmarco
Copy link
Member Author

@EwanValentine if you are using the path resolver this issue doesn't apply to your use-case.

@EwanValentine
Copy link

@thefosk I'm not using the path resolver. My API endpoints follow the following scheme:

/api/v1/login (api.auth.v1) 
/api/v1/signup (api.auth.v1)
/api/v1/artists (api.artists.v1)
/api/v1/orders (api.store.v1)
/api/v1/products (api.store.v1) 

etc... 

So I'm not sure how the path resolver would fit into that?

@EwanValentine
Copy link

No worries, I've sorted it! I had no idea you could just call auth.myapi.dev/api/v1/login. My bad!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
task/feature Requests for new features in Kong
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants