Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google App Engine Channel API with custom domains

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.

like image 674
Ani Avatar asked Jan 13 '14 11:01

Ani


1 Answers

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.

like image 69
Nick Avatar answered Sep 29 '22 08:09

Nick