Closed Bluenix2 closed 2 years ago
@Bluenix2 would you mind pasting your code of how you are creating the socket and related parts?
wsproto is a sans-io library, meaning that it does not handle your TLS connection or socket -- you have to take care of that yourself. wsproto only received and emits bytes, but putting them into a network connection (either plain or with TLS) is up to you. In the general protocol stack, the operating system takes care of the TCP socket, then you probably want to use Python's ssl
module or similar to give you a secure trusted TLS socket. And then you shuffle bytes in and out with wsproto.
You should only pass a valid hostname (without any scheme prefix) to the Request
event.
Hello, the code below should be able to reproduce the issue @Kriechi
import socket
from wsproto.events import Request
from wsproto import WSConnection, ConnectionType
RECV_BUFFER = 4096
conn = WSConnection(ConnectionType.CLIENT)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('gateway.discord.gg', 443))
sock.send(conn.send(Request('gateway.discord.gg', target='/?v=9&encoding=json')))
while True:
data = conn.receive_data(sock.recv(RECV_BUFFER))
for event in conn.events():
print(event)
The output of this code can be seen below:
RejectConnection(status_code=400, headers=<Headers([(b'server', b'cloudflare'), (b'date', b'Fri, 22 Oct 2021 07:56:35 GMT'), (b'content-type', b'text/html'), (b'content-length', b'253'), (b'connection', b'close'), (b'cf-ray', b'-')])>, has_body=True)
RejectData(data=bytearray(b'<html>\r\n<head><title>400 The plain HTTP request was sent to HTTPS port</title></head>\r\n<body>\r\n<center><h1>400 Bad Request</h1></center>\r\n<center>The plain HTTP request was sent to HTTPS port</center>\r\n<hr><center>cloudflare</center>\r\n</body>\r\n</html>\r\n'), body_finished=False)
RejectData(data=b'', body_finished=True)
@Bluenix2 you are missing the TLS layer in your connection. The error message clearly tells you: you are not sending TLS encrypted data to port 443.
This snippet should get you a working socket with TLS (untested):
import socket
import ssl
import certifi
SERVER_NAME = 'gateway.discord.gg'
SERVER_PORT = 443
# generic socket and ssl configuration
socket.setdefaulttimeout(15)
ctx = ssl.create_default_context(cafile=certifi.where())
# open a socket to the server and initiate TLS
sock = socket.create_connection((SERVER_NAME, SERVER_PORT))
sock = ctx.wrap_socket(sock, server_hostname=SERVER_NAME)
# wsproto
conn = WSConnection(ConnectionType.CLIENT)
sock.send(conn.send(Request(SERVER_NAME, target='/?v=9&encoding=json')))
When trying to use WSProto I ran into issues with connecting to Discord using a Secure WebSocket as Cloudflare kept returning a
400 Bad Request
rejection.What appeared to be happening was that WSProto included the wss part of the URL as in the HTTP request as shown here:
I could fix this by changing
Request('wss://gateway.discord.gg', target='/?v=9$encoding=json')
toRequest('gateway.discord.gg', target='/?v=9$encoding=json')
.Now I am having issues with WSProto trying to send a HTTP request instead of a HTTPS one as sen from this Cloudflare response: