2013-10-03 11 views
10

PythonプロジェクトでApp Engineモジュールを使用しています。 https://developers.google.com/appengine/docs/python/channel/App Engine Pythonモジュールとチャネルサービス

私は/( '/ _ah /チャンネル/接続/'、「/ _ah /チャネル接続/切断/切断後のメッセージを指示したい:私もMプロジェクト内のチャネルを使用しています(https://developers.google.com/appengine/docs/python/modules/#Python_Background_threads

')を私のapiモジュールに渡します。今、私は彼らが任意のモジュール(デフォルトまたはAPI)に表示することができません

app.yamlを

api_version: 1 
    application: integrate 
    version: 1-0-0 
    runtime: python27 
    threadsafe: true 

    builtins: 
     - deferred: on 

    libraries: 
     - name: pycrypto 
     version: "2.6" 

    handlers: 
     - url: /favicon\.ico 
     static_files: static/favicon.ico 
     upload: static/favicon\.ico 

     - url: /admin/.+ 
     script: src.default.main.app 
     login: admin 

     - url: /.* 
     script: src.default.main.app 

api.yaml

api_version: 1 
    application: integrate 
    module: api 
    version: 1-0-0 
    runtime: python27 
    threadsafe: true 

    inbound_services: 
     - channel_presence 

    builtins: 
     - deferred: on 

    libraries: 
     - name: pycrypto 
     version: "2.6" 

    handlers: 
     - url: /admin/.+ 
     script: src.api.main.app 
     login: admin 

     - url: /.* 
     script: src.api.main.app 

dispatch.yaml

application: integrate 

    dispatch: 
     - url: "*/_ah/channel/*" 
     module: api 

注:これはすべて、devモードのローカルでのみ有効です。

api.main.app

app = webapp2.WSGIApplication(debug=True) 
    _routes = [ 
     : 
     ChannelDisconnectedHandler.mapping(), 
     ChannelConnectHandler.mapping() 
    ] 

    for r in self._routes: 
     app.router.add(r) 

ChannelDisconnectHandler

CHANNEL_DISCONNECTED_URL_PATTERN = '/_ah/channel/disconnected/' 


    class ChannelDisconnectedHandler(RequestHandler): 

     @classmethod 
     def mapping(cls): 
      return CHANNEL_DISCONNECTED_URL_PATTERN, cls 

     def post(self): 
      """ 
      Channel Presence handler. Will be called when a client disconnects. 
      """ 
      channel_id = self.request.get('from') 
      logging.info("Channel Disconnect. Id: %s" % channel_id) 

ChannelConnectHandler

CHANNEL_CONNECT_URL_PATTERN = '/_ah/channel/connected/' 

    class ChannelConnectHandler(RequestHandler): 

     @classmethod 
     def mapping(cls): 
      return CHANNEL_CONNECT_URL_PATTERN, cls 

     def post(self): 
      """ 
      Channel Presence handler. Will be called when a client connects. 
      """ 
      channel_id = self.request.get('from') 
      logging.info("Channel Connect. Id: %s" % channel_id) 

だから私のクライアントは私のAPIモジュールへの投稿(JavaScriptで書かれた)とチャネルを開きます。

var open_channel = function(tokenResponse) { 
     console.log("Open Channel. token Response: " + tokenResponse) 
     token = tokenResponse.token; 
     var channel = new goog.appengine.Channel(token); 
     if (socket != null) { 
      socket.close(); 
     } 
     socket = channel.open(); 
     socket.onopen = onOpened; 
     socket.onmessage = onMessage; 
     socket.onerror = onError; 
     socket.onclose = onClose; 
    }; 

    onOpened = function() { 
     console.info("Channel API Connection is open."); 
    }; 

    onError = function(e) { 
     console.info("CHANNEL Error. Code: " + e.code + ", Description: " + e.description); 
    }; 

    onClose = function() { 
     console.info("Close Channel"); 
    }; 

    onMessage = function(msg) { 
     console.info("Message Received: " + msg + ", Data: " + msg.data); 
    }; 

このコールバック関数には有効なトークンが設定されています。私は正常にソケットを作成し、期待どおりこの機能を完了します。ローカルシステム上でonOpened関数が呼び出され、サーバーからメッセージが受信されます。プロダクションでは、onOpenedは決して呼び出されず、メッセージを受け取ることはありません。/_ah/channel/connected /も決して呼び出されません。

チャネルサービスはモジュールでサポートされていませんか?私が見逃していることについての考えは?

答えて

0

URLの接続と切断には、hadlerルーティングを宣言する必要があります。 Googleエンタープライズサポート(彼らの生の答えとは少し変更された)によると

application = webapp2.WSGIApplication([ 
    ... 
    # Define a URL routing for /_ah/channel/connected/ 
    webapp2.Route(r'/_ah/channel/connected/', 
        handler=ChannelConnectedHandler, 
        name='channel_connected') 

], debug=True, config=webapp2_config) 


# Implement class handler of /_ah/channel/connected/ 
class ChannelConnectedHandler(webapp2.RequestHandler): 
    def post(self): 
     client_id = self.request.get('from') 
     logging.info('client %s has connected!' % client_id) 
     ... 
+1

おかげで私はそれがここでの問題ではないかと思います。私はここにコードを掲載しませんでしたが、ルートを追加しました。もし私がいなければ、devモードでは動作しません。 –

+0

私はそのコードを追加して、私が何を意味するのかを示します。 –

6

main.pyでハンドラのルーティングに

  1. channel_presenceインバウンドサービスはapp.yamlで有効にする必要があります。

    inbound_services: 
    - channel_presence 
    

    モジュールのYAMLファイルで、このインバウンド・サービスを有効にする(例えば、この問題のapi.yaml)は、このサービスを有効にしません。

  2. */_ahで始まるURLパスはディスパッチ可能なパスではなく、dispatch.yamlでルーティングすることはできません。したがって、channel_presence URLパスハンドラはapp.yamlに記述する必要があります。

    handlers: 
    - url: /_ah/channel/connected/ 
        script: mymodule.application 
    
+0

golangの正しい行は、 '' script:mymodule.application''ですか? – mattes

+0

mattes-私はその行は言語にとらわれないと思いますが、Emil-その動作についてのさらなる説明をお待ちしております。 – davidkomer

+0

'app.yaml'の詳細については、言語固有のドキュメントを参照してください。 Goの場合、該当するバージョンはhttps://cloud.google.com/appengine/docs/go/config/appconfigにあります –

0

私も、モジュール内のチャネルAPIを使用しての問題にぶつかってきたと私はエミールは、モジュールに要求をリダイレクトすることで言及と同様のトリックを使用してそれらを回避しようとしました。

私は実際に3つのモジュールを持っていたので、もう少し複雑な設定でしたが、2つはChannel APIを使用し、1つは 'フロントエンド'でした。このような何か:

  • モジュールフロントエンド(デフォルト)
  • モジュールサービスA
  • モジュールserviceB(チャネルAPI 1を使用して)私は聞くことができるように望んでいた

(チャネルAPI 2を使用して)フロントエンドの2つの別々のサービスからの「通知」

そして、私はそれを回避することができました(devで)フロントエンドにリダイレクトを追加して、各サービスに接頭辞を付けて各サービスにリダイレクトするトークンを読み込むことでした。

「素晴らしいです!」私は思ったが、アプリエンジンにデプロイしようとしたとき、Channel APIによって内部的に使用されていたtalkgadgetエンドポイントが特定のソースアプリを期待しているように見えて、クロスドメイン通信を許可していないことが分かった。

私はモジュールの代わりに複数のプロジェクトを使用し、クロスドメインの問題を回避するためにHTML iframe "postMessage bridge"を置くことになりました。そして喜んでそれは本当にうまくいって、副作用として私は使用する2倍の "フリー"チャンネルを得ます。

私はあなたが追跡するために興味深いかもしれここではこれに関連した問題が見つかりました:答えるためhttps://code.google.com/p/googleappengine/issues/detail?id=10293

関連する問題