change all request.headers from dicts to CaseInsensitiveDicts

This commit is contained in:
Googolplexed0
2025-09-18 21:36:54 -05:00
parent a96b11c0a5
commit e0070925e2
8 changed files with 36 additions and 30 deletions

View File

@@ -5,6 +5,7 @@ import subprocess
import time import time
import requests import requests
from requests.structures import CaseInsensitiveDict
from librespot.audio.decoders import AudioQuality, VorbisOnlyAudioQuality from librespot.audio.decoders import AudioQuality, VorbisOnlyAudioQuality
from librespot.core import Session from librespot.core import Session
@@ -66,7 +67,7 @@ def client():
"q": cmd[2:], "q": cmd[2:],
"type": "track" "type": "track"
}, },
headers={"Authorization": "Bearer %s" % token}, headers=CaseInsensitiveDict({"Authorization": "Bearer %s" % token}),
) )
i = 1 i = 1
tracks = resp.json()["tracks"]["items"] tracks = resp.json()["tracks"]["items"]

View File

@@ -2,6 +2,7 @@ import os
import re import re
import socket import socket
import threading import threading
from requests.structures import CaseInsensitiveDict
from librespot.audio.decoders import AudioQuality, VorbisOnlyAudioQuality from librespot.audio.decoders import AudioQuality, VorbisOnlyAudioQuality
from librespot.core import Session from librespot.core import Session
@@ -23,7 +24,7 @@ def handler(client: socket.socket, address: str):
req_method = req_http_arr[0] req_method = req_http_arr[0]
req_uri = req_http_arr[1] req_uri = req_http_arr[1]
req_http_version = req_http_arr[2] req_http_version = req_http_arr[2]
req_header = {} req_header = CaseInsensitiveDict()
for header in req_header_str.split(b"\r\n"): for header in req_header_str.split(b"\r\n"):
try: try:
key, value = header.split(b": ") key, value = header.split(b": ")
@@ -73,7 +74,7 @@ def main():
threading.Thread(target=handler, args=sock.accept()).start() threading.Thread(target=handler, args=sock.accept()).start()
def response(client: socket.socket, uri: str, header: dict, def response(client: socket.socket, uri: str, header: CaseInsensitiveDict,
body: bytes) -> tuple[str, list, bytes, bool]: body: bytes) -> tuple[str, list, bytes, bool]:
if re.search(r"^/audio/track/([0-9a-zA-Z]{22})$", uri) is not None: if re.search(r"^/audio/track/([0-9a-zA-Z]{22})$", uri) is not None:
track_id_search = re.search( track_id_search = re.search(

View File

@@ -8,6 +8,7 @@ from librespot.crypto import Packet
from librespot.metadata import EpisodeId, PlayableId, TrackId from librespot.metadata import EpisodeId, PlayableId, TrackId
from librespot.proto import Metadata_pb2 as Metadata, StorageResolve_pb2 as StorageResolve from librespot.proto import Metadata_pb2 as Metadata, StorageResolve_pb2 as StorageResolve
from librespot.structure import AudioDecrypt, AudioQualityPicker, Closeable, FeederException, GeneralAudioStream, GeneralWritableStream, HaltListener, NoopAudioDecrypt, PacketsReceiver from librespot.structure import AudioDecrypt, AudioQualityPicker, Closeable, FeederException, GeneralAudioStream, GeneralWritableStream, HaltListener, NoopAudioDecrypt, PacketsReceiver
from requests.structures import CaseInsensitiveDict
import concurrent.futures import concurrent.futures
import io import io
import logging import logging
@@ -471,9 +472,9 @@ class CdnManager:
class InternalResponse: class InternalResponse:
buffer: bytes buffer: bytes
headers: typing.Dict[str, str] headers: CaseInsensitiveDict[str, str]
def __init__(self, buffer: bytes, headers: typing.Dict[str, str]): def __init__(self, buffer: bytes, headers: CaseInsensitiveDict[str, str]):
self.buffer = buffer self.buffer = buffer
self.headers = headers self.headers = headers
@@ -578,8 +579,6 @@ class CdnManager:
response = self.request(range_start=0, response = self.request(range_start=0,
range_end=ChannelManager.chunk_size - 1) range_end=ChannelManager.chunk_size - 1)
content_range = response.headers.get("Content-Range") content_range = response.headers.get("Content-Range")
if content_range is None:
content_range = response.headers.get("content-range")
if content_range is None: if content_range is None:
raise IOError("Missing Content-Range header!") raise IOError("Missing Content-Range header!")
split = content_range.split("/") split = content_range.split("/")
@@ -633,16 +632,16 @@ class CdnManager:
range_end = (chunk + 1) * ChannelManager.chunk_size - 1 range_end = (chunk + 1) * ChannelManager.chunk_size - 1
response = self.__session.client().get( response = self.__session.client().get(
self.__cdn_url.url, self.__cdn_url.url,
headers={ headers=CaseInsensitiveDict({
"Range": "bytes={}-{}".format(range_start, range_end) "Range": "bytes={}-{}".format(range_start, range_end)
}, }),
) )
if response.status_code != 206: if response.status_code != 206:
raise IOError(response.status_code) raise IOError(response.status_code)
body = response.content body = response.content
if body is None: if body is None:
raise IOError("Response body is empty!") raise IOError("Response body is empty!")
return CdnManager.InternalResponse(body, dict(response.headers)) return CdnManager.InternalResponse(body, response.headers)
class InternalStream(AbsChunkedInputStream): class InternalStream(AbsChunkedInputStream):
streamer: CdnManager.Streamer streamer: CdnManager.Streamer

View File

@@ -28,6 +28,7 @@ from Cryptodome.Hash import SHA1
from Cryptodome.Protocol.KDF import PBKDF2 from Cryptodome.Protocol.KDF import PBKDF2
from Cryptodome.PublicKey import RSA from Cryptodome.PublicKey import RSA
from Cryptodome.Signature import PKCS1_v1_5 from Cryptodome.Signature import PKCS1_v1_5
from requests.structures import CaseInsensitiveDict
from librespot import util from librespot import util
from librespot import Version from librespot import Version
@@ -80,7 +81,7 @@ class ApiClient(Closeable):
self, self,
method: str, method: str,
suffix: str, suffix: str,
headers: typing.Union[None, typing.Dict[str, str]], headers: typing.Union[None, CaseInsensitiveDict[str, str]],
body: typing.Union[None, bytes], body: typing.Union[None, bytes],
url: typing.Union[None, str], url: typing.Union[None, str],
) -> requests.PreparedRequest: ) -> requests.PreparedRequest:
@@ -89,7 +90,7 @@ class ApiClient(Closeable):
:param method: str: :param method: str:
:param suffix: str: :param suffix: str:
:param headers: typing.Union[None: :param headers: typing.Union[None:
:param typing.Dict[str: :param CaseInsensitiveDict[str:
:param str]]: :param str]]:
:param body: typing.Union[None: :param body: typing.Union[None:
:param bytes]: :param bytes]:
@@ -106,7 +107,7 @@ class ApiClient(Closeable):
request = requests.PreparedRequest() request = requests.PreparedRequest()
request.method = method request.method = method
request.data = body request.data = body
request.headers = {} request.headers = CaseInsensitiveDict()
if headers is not None: if headers is not None:
request.headers = headers request.headers = headers
request.headers["Authorization"] = "Bearer {}".format( request.headers["Authorization"] = "Bearer {}".format(
@@ -122,7 +123,7 @@ class ApiClient(Closeable):
self, self,
method: str, method: str,
suffix: str, suffix: str,
headers: typing.Union[None, typing.Dict[str, str]], headers: typing.Union[None, CaseInsensitiveDict[str, str]],
body: typing.Union[None, bytes], body: typing.Union[None, bytes],
) -> requests.Response: ) -> requests.Response:
""" """
@@ -130,7 +131,7 @@ class ApiClient(Closeable):
:param method: str: :param method: str:
:param suffix: str: :param suffix: str:
:param headers: typing.Union[None: :param headers: typing.Union[None:
:param typing.Dict[str: :param CaseInsensitiveDict[str:
:param str]]: :param str]]:
:param body: typing.Union[None: :param body: typing.Union[None:
:param bytes]: :param bytes]:
@@ -145,7 +146,7 @@ class ApiClient(Closeable):
method: str, method: str,
url: str, url: str,
suffix: str, suffix: str,
headers: typing.Union[None, typing.Dict[str, str]], headers: typing.Union[None, CaseInsensitiveDict[str, str]],
body: typing.Union[None, bytes], body: typing.Union[None, bytes],
) -> requests.Response: ) -> requests.Response:
""" """
@@ -154,7 +155,7 @@ class ApiClient(Closeable):
:param url: str: :param url: str:
:param suffix: str: :param suffix: str:
:param headers: typing.Union[None: :param headers: typing.Union[None:
:param typing.Dict[str: :param CaseInsensitiveDict[str:
:param str]]: :param str]]:
:param body: typing.Union[None: :param body: typing.Union[None:
:param bytes]: :param bytes]:
@@ -327,10 +328,10 @@ class ApiClient(Closeable):
resp = requests.post( resp = requests.post(
"https://clienttoken.spotify.com/v1/clienttoken", "https://clienttoken.spotify.com/v1/clienttoken",
proto_req.SerializeToString(), proto_req.SerializeToString(),
headers={ headers=CaseInsensitiveDict({
"Accept": "application/x-protobuf", "Accept": "application/x-protobuf",
"Content-Encoding": "", "Content-Encoding": "",
}, }),
) )
ApiClient.StatusCodeException.check_status(resp) ApiClient.StatusCodeException.check_status(resp)
@@ -604,10 +605,10 @@ class DealerClient(Closeable):
return return
self.__message_listeners_lock.wait() self.__message_listeners_lock.wait()
def __get_headers(self, obj: typing.Any) -> dict[str, str]: def __get_headers(self, obj: typing.Any) -> CaseInsensitiveDict[str, str]:
headers = obj.get("headers") headers = obj.get("headers")
if headers is None: if headers is None:
return {} return CaseInsensitiveDict()
return headers return headers
class ConnectionHolder(Closeable): class ConnectionHolder(Closeable):
@@ -1212,12 +1213,12 @@ class Session(Closeable, MessageListener, SubListener):
raise RuntimeError("Session isn't authenticated!") raise RuntimeError("Session isn't authenticated!")
return self.__mercury_client return self.__mercury_client
def on_message(self, uri: str, headers: typing.Dict[str, str], def on_message(self, uri: str, headers: CaseInsensitiveDict[str, str],
payload: bytes): payload: bytes):
""" """
:param uri: str: :param uri: str:
:param headers: typing.Dict[str: :param headers: CaseInsensitiveDict[str:
:param str]: :param str]:
:param payload: bytes: :param payload: bytes:
@@ -2331,10 +2332,10 @@ class TokenProvider:
response = requests.post( response = requests.post(
"https://login5.spotify.com/v3/login", "https://login5.spotify.com/v3/login",
data=login5_request.SerializeToString(), data=login5_request.SerializeToString(),
headers={ headers=CaseInsensitiveDict({
"Content-Type": "application/x-protobuf", "Content-Type": "application/x-protobuf",
"Accept": "application/x-protobuf" "Accept": "application/x-protobuf"
}) }))
if response.status_code == 200: if response.status_code == 200:
login5_response = Login5.LoginResponse() login5_response = Login5.LoginResponse()

View File

@@ -3,6 +3,7 @@ from librespot import util
from librespot.crypto import Packet from librespot.crypto import Packet
from librespot.proto import Mercury_pb2 as Mercury, Pubsub_pb2 as Pubsub from librespot.proto import Mercury_pb2 as Mercury, Pubsub_pb2 as Pubsub
from librespot.structure import Closeable, PacketsReceiver, SubListener from librespot.structure import Closeable, PacketsReceiver, SubListener
from requests.structures import CaseInsensitiveDict
import io import io
import json import json
import logging import logging
@@ -346,11 +347,11 @@ class RawMercuryRequest:
return RawMercuryRequest.Builder() return RawMercuryRequest.Builder()
class Builder: class Builder:
header_dict: dict header_dict: CaseInsensitiveDict
payload: typing.List[bytes] payload: typing.List[bytes]
def __init__(self): def __init__(self):
self.header_dict = {} self.header_dict = CaseInsensitiveDict()
self.payload = [] self.payload = []
def set_uri(self, uri: str): def set_uri(self, uri: str):

View File

@@ -8,6 +8,7 @@ if typing.TYPE_CHECKING:
from librespot.crypto import Packet from librespot.crypto import Packet
from librespot.mercury import MercuryClient from librespot.mercury import MercuryClient
from librespot.proto import Metadata_pb2 as Metadata from librespot.proto import Metadata_pb2 as Metadata
from requests.structures import CaseInsensitiveDict
class AudioDecrypt: class AudioDecrypt:
@@ -61,7 +62,7 @@ class HaltListener:
class MessageListener: class MessageListener:
def on_message(self, uri: str, headers: typing.Dict[str, str], def on_message(self, uri: str, headers: CaseInsensitiveDict[str, str],
payload: bytes): payload: bytes):
raise NotImplementedError raise NotImplementedError

View File

@@ -7,6 +7,7 @@ from librespot.core import Session
from librespot.crypto import DiffieHellman from librespot.crypto import DiffieHellman
from librespot.proto import Connect_pb2 as Connect from librespot.proto import Connect_pb2 as Connect
from librespot.structure import Closeable, Runnable, SessionListener from librespot.structure import Closeable, Runnable, SessionListener
from requests.structures import CaseInsensitiveDict
import base64 import base64
import concurrent.futures import concurrent.futures
import copy import copy
@@ -275,7 +276,7 @@ class ZeroconfServer(Closeable):
method = request_line[0].decode() method = request_line[0].decode()
path = request_line[1].decode() path = request_line[1].decode()
http_version = request_line[2].decode() http_version = request_line[2].decode()
headers = {} headers = CaseInsensitiveDict()
while True: while True:
header = request.readline().strip() header = request.readline().strip()
if not header: if not header:

View File

@@ -5,6 +5,7 @@ from librespot.core import Session
from librespot.mercury import MercuryRequests from librespot.mercury import MercuryRequests
from librespot.proto import Connect_pb2 as Connect from librespot.proto import Connect_pb2 as Connect
from librespot.structure import Closeable, MessageListener, RequestListener from librespot.structure import Closeable, MessageListener, RequestListener
from requests.structures import CaseInsensitiveDict
import concurrent.futures import concurrent.futures
import logging import logging
import typing import typing
@@ -200,6 +201,6 @@ class StateWrapper(MessageListener):
"hm://collection/collection/" + session.username() + "/json" "hm://collection/collection/" + session.username() + "/json"
]) ])
def on_message(self, uri: str, headers: typing.Dict[str, str], def on_message(self, uri: str, headers: CaseInsensitiveDict[str, str],
payload: bytes): payload: bytes):
pass pass