0

Wondering if there is a way to set a authorization header when making a client side socket connection with pythons socket module.

I have looked into this: Python requests library how to pass Authorization header with single token

And not sure if this is what I need to do as well.

I am trying to establish a websocket connection from a third party service and their docs provide an example with JS, but the python socket library I am using is a bit different. Zendesk Stream API

As the docs point out, after a connection is established, the Authorization header must be set with the OAuth Token.

var WebSocket = require('ws');

var ws_client = new WebSocket(
  'wss://rtm.zopim.com/stream', {
    headers: {
      'Authorization': 'Bearer ' + {OAuth2 access token}
    }
  }
);

How can I set the Authorization header with python socket library.

What I have so far:

import socket 



class SockHandler():
    def __init__(self):
        #create a new socket
        try: 
            self._s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
            print "Socket successfully created"
        except socket.error as err: 
            print "socket creation failed with error %s" %(err)

    def connect(self):
        #connect to a remote socket address
        HOST = self._s.gethostbyname("wss://rtm.zopim.com/stream")
        self._s.connect((HOST, 443))

    def sendMsg(self):
        self._s.send("agents_online")

    def receiveData(self):
        data = self._s.recv(1024)
        print("Data received: %s", data)

After self._s.connect((HOST, 443)) How can I set the Authorization header with my OAuth Token?

EDIT: I need to also "subscribe" to event according to the Zendesk docs I provided above.

In the JS example, they send an object to subscribe to a socket such as

{
  topic: "agents.{metric_key}",
  action: "subscribe"
}

I am unsure how I can do this with python socket. The socket.send only accepts a string and not an object, so I don't know how to send an object to subscribe.

Henry Lee
  • 147
  • 1
  • 1
  • 8
  • `s.connect(("wss://rtm.zopim.com/stream", 80))` - I'm pretty sure that this will not work, i.e. it expects a hostname or IP and not a URL. And then you also need to upgrade the socket to SSL. And then you need to make the WebSockets handshake which consists of HTTP request and reading the HTTP response. And then you must implement the WebSockets framing protocol. Once you know how to send a HTTP request you likely also know how to send the `Authorization` header, which is a normal HTTP header like the other ones in the request. Why not just simply use a library for all this? – Steffen Ullrich Dec 14 '18 at 20:16
  • @SteffenUllrich Thanks for the input. My application is hosted on Google App Engine and we use the Python 2.7 environment, and this is currently limited to outbound sockets, so I dont think I can establish a connection from the front end to this server I am creating. So what I am considering doing is creating this client side socket that will last as long as the user is connected, and whenever a message is sent and the data received is different than whats in the cache, I will execute a task handler that will update the cache with this new value. Then from the front end I will just ping my API – Henry Lee Dec 14 '18 at 20:24
  • @SteffenUllrich The reason I thought this would work `s.connect(("wss://rtm.zopim.com/stream", 80))` was because I thought stream URL `wss://rtm.zopim.com/stream` would already be connected to an IP. If not I can use `s. gethostbyname("wss://rtm.zopim.com/stream")` and then use the IPv4 IP returned from that to create the connection. – Henry Lee Dec 14 '18 at 20:27
  • While your code is incomplete I assume that the `s` in `s.connect` is actually the `self._s` socket you've setup earlier. `connect` has no idea about URLs, it only knows IP, hostname and ports. It also cannot handle SSL, HTTP, WebSockets etc by itself. I recommend to study the Python documentation for this. – Steffen Ullrich Dec 14 '18 at 20:32
  • Yes, @SteffenUllrich, I commented above on how to use IP. But as mentioned, I can only use outbound sockets, so I dont think I can create a handshake with the front end. That is why, I need to set the Authorization Header with my OAuth token when the socket connection is established, as described in my OP with their JS example. I am wondering if there is a way to create a Authorization header like in their JS example but with the Python Socket library. – Henry Lee Dec 14 '18 at 20:35
  • The socket you currently have is TCP/IP. I've tried to explain already that you are with this plain socket some network layers away from where you need to be in order set the authorization header - i.e. you need to implement first SSL and then HTTP and then within HTTP you can set the header. All of this would need to be implement in your program first which is a huge tasks given that you don't seem to understand anything of this yet. You therefore better use a websockets library like [this](https://websockets.readthedocs.io/en/stable/intro.html). – Steffen Ullrich Dec 14 '18 at 20:50
  • *"I can only use outbound sockets, so I dont think I can create a handshake with the front end."* - outbound socket just means that the connection has to be initiated from inside. It does not mean that you cannot receive any data from outside but only that data from outside can only be received within a connection which is initiated from inside. In other words the TCP handshake, SSL handshake and WebSockets handshake all can be done as long as the connection is initiated from inside - which you do with `connect`. – Steffen Ullrich Dec 14 '18 at 20:55
  • @SteffenUllrich Okay, I really appreciate your feedback. So since I am already attempting to create a connection from the inside, would I then need to create connection to my client side socket with for example the NodeJS `ws` websocket module? Now that I think about it, maybe it would be simpler to just use the NodeJS `ws` websocket module in my front end React application then just create the connection like in the example in my OP. I can even set the authrization from the React front end as well. @SteffenUllrich Would this be a better approach than setting up a python socket? – Henry Lee Dec 14 '18 at 21:11
  • @SteffenUllrich Ive handled request that come in from the front end, i.e a browser via AJAX etc. We have routes and task handlers for these. Does this mean that I can create my socket connection in my route task handler? For example, whenever someone on front end makes a request to www.mywebsite.com/getAgents, this will process a get request which would set the header then create the socket connection to like how I am doing in OP? The Zendesk API I am using states every request made must have an OAuth Token, which makes me think taht I can create this socket connection in one of my API routes. – Henry Lee Dec 15 '18 at 02:09
  • Your question does not provide enough information about what you actually do in order to understand your last comments. What would be needed is a more detailed explanation of your general architecture and use case and what you are trying to achieve at the end. But, it would not be longer in the context of your question where you specifically ask about adding Authorization to the outgoing socket. Maybe you should just start from scratch with a new question where you ask how to best implement your use case instead of asking for help on your specific implementation idea. – Steffen Ullrich Dec 15 '18 at 03:57

0 Answers0