In my GAE app (Python) I have implemented multitenancy and multi-site support based on the host
part of the request object.
For example, www.foo.com/index.html
and www.bar.com/index.html
are both handled by the same app (e.g. myapp.appspot.com
). The app reads the host-value and then decides which namespace and site-configuration to use. This works great as long as the app receives the request directly from the user-agent.
However, I would like to use the Channel API, but there is an issue because requests to /_ah/channel/connected/
and /_ah/channel/disconnected/
are not originating from the original user-agent. Instead, the request has Host: myapp.appspot.com
and the parameter to=myapp.appspot.com
. (The from
parameter is the token I expect. Also www.foo.com/_ah/channel/jsapi
is redirected to a talkgadget server which is not documented but seems to be as expected.)
I assume, the problem is caused by the code in channel.js
which doesn't call my app using the original host, e.g. www.foo.com/_ah/channel/connected
. Instead it uses a talkgadget.google.com
host which (as far as I can tell) will then call my app, but using myapp.appspot.com
, ignoring the original host and so I cannot use the request's host
value for my purpose.
As a workaround, I can figure out a way of including the host information into the channel token, so when my connected
and disconnected
handlers receive the token, they can use the token instead.
However, I would like to know if there is a better approach, where I could still get the original host name (e.g. www.foo.com
) requests to /_ah/channel/connected/
and /_ah/channel/disconnected/
. Any ideas?
This is what I have tried so far (with-out any success):
Adding the custom domain host name to the JS src attribute:
<script type="text/javascript" src="//www.foo.com/_ah/channel/jsapi"></script>
I also tried to manually override the base-url of the channel socket, suggested here: https://stackoverflow.com/questions/16558776/google-app-engine-channel-api-same-origin-policy
<script type="text/javascript">
onOpened = function() {
// TODO
};
onMessage = function() {
// TODO
};
onError = function() {
// TODO
};
onClose = function() {
// TODO
};
goog.appengine.Socket.BASE_URL = "https://www.foo.com/_ah/channel/";
channel = new goog.appengine.Channel('{{channelToken}}');
socket = channel.open();
socket.onopen = onOpened;
socket.onmessage = onMessage;
socket.onerror = onError;
socket.onclose = onClose;
</script>
I couldn't find any official documentation for channel.js and I don't want to implement something that is going to break easily with the next update by Google.
Short of a proxy, I don't see a better way than including the information in-band. The problem is that the library/infrastructure (can't be certain without looking deeper) is stripping the HTTP-layer information (the Host header), and indeed you don't have any control of the HTTP layer to pass custom headers, etc. So, you either need to have the info at a lower layer (TCP doesn't even provide a means to do this, and since the entrypoint of your code is through the browser running channel.js, rather than a system-level process running on the bare network interface, this is out of the picture decisively), or at a higher layer, ie. within the channel.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With