0

Let's say I have a vue client trying to receive an event from a private channel using pusher services.

This client autenticates using pusher auth secuence: enter image description here

Here are the docs: https://pusher.com/docs/channels/server_api/authenticating-users/

Seems I need to provide an endpoint on my server in order to autenticate the user.

So, as the docs says, since my server is in a different domain to the front-end app, I need to use CORS or JSONP, I choose JSONP.

My server (backend) is made in Django using django-rest-framework and it provides an endpoint that is responsible to process the socket_id, the channel_name and the callback that the pusher-js (which is a pusher frontend library) generates.

Something alike to a javascript code is sent to the frontend, so the response needs to be content-type:application/javascript.

In order to test the event, I made a simple python script which I will later integrate to my bussiness logic. This script is the responsible to trigger the event.

The problem: The main problem is the event never arrives. I looked up into the web-console (frontend) to check the correct function of the requests. The ws protocol requests responds with status 101 and the endpoint /auth/pusher with status 200. So they seem to work correctly.

  • Here is my Django /auth/pusher endpoint:
def get(self, request):
  pusher_client = pusher.Pusher(
      app_id = settings.P_APP_ID,
      key = settings.P_APP_KEY,
      secret = settings.P_APP_KEY_SECRET,
      cluster = settings.P_REGION_CLUSTER,
      ssl = True
  )

  auth = pusher_client.authenticate(
      channel=request.query_params.get('channel_name'),
      socket_id=request.query_params.get('socket_id')
  )

  callback_query_params = request.query_params.get('callback')

  callback = re.sub(r'/\\"/g', '', callback_query_params) + "(" + str(auth) + ");";

  return Response(callback, content_type = 'application/javascript')
  • Here is the important part of the pusher connection in vue:
var pusher = new Pusher(env.pusher_app_key, {
      cluster: 'us2',
      authTransport: "jsonp",
      authEndpoint: "http://localhost:8000/pusher/auth",
    });

var channel = pusher.subscribe('private-cesar');

channel.bind('my-event', function(data) {
  console.log(data);
  this.messages.push(JSON.stringify(data));
});
  • Here is the python script I made to trigger the event manually:
import pusher

pusher_client = pusher.Pusher(
      app_id = settings.P_APP_ID,
      key = settings.P_APP_KEY,
      secret = settings.P_APP_KEY_SECRET,
      cluster = settings.P_REGION_CLUSTER,
      ssl = True
  )

  while True: 
      option = input("Send? (Y/N)") 
      if option.lower() == "y":
          pusher_client.trigger('private-cesar', 'my-event', {'message': 'test from python'}) 
          print("Sent")
      else:
          break

So, what seems to be the problem here, is there something I'm missing?

I already figured out how to use it without auth, And it works as expected, but in that case I don't need to have a auth/pusher endpoint.

Cesar Augusto
  • 268
  • 4
  • 16
  • I know I am coming a bit late, but are you sure the endpoint you need to implement is a GET endpoint? From the [documentation](https://pusher.com/docs/channels/server_api/authenticating-users/), all of the examples implement a POST endpoint. Have you solved this in the meantime? – vinkomlacic Mar 17 '22 at 09:19
  • Hello, don't worry, any help is welcome at any time. I did not solved this yet, I paused the implementation of that module meanwhile I think on a better solution or a figure out what's the problem with the auth. Yes, you are right, most of the examples implements a POST endpoint. But, since my server is in a different domain to the web app, I need to use JSONP. When I set-up the JSONP params on the pusher client instantiation, pusher-js automatically requests for a GET endpoint, not a POST endpoint. At the docs, where they explain the JSONP method, they example a GET endpoint – Cesar Augusto Mar 17 '22 at 20:00
  • Did you try to serialize `auth` into JSON first? the docs show that when returning the JSONP, the `auth` variable is [first serialized into JSON](https://pusher.com/docs/channels/server_api/authenticating-users/#using-jsonp-in-pusher-js), just like the auth endpoint was doing in python with `return json.dumps(auth)` in [this snippet](https://pusher.com/docs/channels/server_api/authenticating-users/#implementing-the-auth-endpoint-for-a-presence-channel). – EDG956 Mar 22 '22 at 11:11
  • No, I solved yet. The problem was the response type – Cesar Augusto Mar 23 '22 at 17:44

1 Answers1

0

SOLUTION:

Finally, I solved this. Turns out I needed to return an HttpResponse object, which is provided by django.http, not the Response that rest_framework.response provides.

My mistake: believing that rest_framework.response is implicit an http response.

imports:

from django.http import HttpResponse

So the endpoint ended like this:

def get(self, request):
        pusher_client = pusher.Pusher(
            app_id = settings.P_APP_ID,
            key = settings.P_APP_KEY,
            secret = settings.P_APP_KEY_SECRET,
            cluster = settings.P_REGION_CLUSTER,
            ssl = True
        )

        auth = pusher_client.authenticate(
            channel=request.query_params.get('channel_name'),
            socket_id=request.query_params.get('socket_id')
        )

        callback_query_params = request.query_params.get('callback')

        callback = re.sub(r'/\\"/g', '', callback_query_params) + "(" + str(auth) + ");";

        return HttpResponse(callback, content_type = 'application/javascript')
Cesar Augusto
  • 268
  • 4
  • 16