Implementing WebSockets with Sony's Audio Control API in Python

168 Views Asked by At

Sony's website provided a example to use WebSockets to works with their api in Node.js

https://developer.sony.com/develop/audio-control-api/get-started/websocket-example#tutorial-step-3

it worked fine for me. But when i was trying to implement it in Python, it does not seems to work

i use websocket_client

import websocket

ws = websocket.WebSocket()
ws.connect("ws://192.168.0.34:54480/sony/avContent",sslopt={"cert_reqs": ssl.CERT_NONE})

gives

websocket._exceptions.WebSocketBadStatusException: Handshake status 403 Forbidden

but in their example code, there is not any kinds of authrization or authentication

1

There are 1 best solutions below

0
On BEST ANSWER

I recently had the same problem. Here is what I found out:

Normal HTTP responses can contain Access-Control-Allow-Origin headers to explicitly allow other websites to request data. Otherwise, web browsers block such "cross-origin" requests, because the user could be logged in there for example.

This "same-origin-policy" apparently does not apply to WebSockets and the handshakes can't have these headers. Therefore any website could connect to your Sony device. You probably wouldn't want some website to set your speaker/receiver volume to 100% or maybe upload a defective firmware, right?

That's why the audio control API checks the Origin header of the handshake. It always contains the website the request is coming from.

The Python WebSocket client you use assumes http://192.168.0.34:54480/sony/avContent as the origin by default in your case. However, it seems that the API ignores the content of the Origin header and just checks whether it's there.

The WebSocket#connect method has a parameter named suppress_origin which can be used to exclude the Origin header.

TL;DR

The Sony audio control API doesn't accept WebSocket handshakes that contain an Origin header.

You can fix it like this:

ws.connect("ws://192.168.0.34:54480/sony/avContent",
           sslopt={"cert_reqs": ssl.CERT_NONE},
           suppress_origin=True)