latch-asgi 1.0.4__tar.gz → 1.0.6.dev0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: latch-asgi
3
- Version: 1.0.4
3
+ Version: 1.0.6.dev0
4
4
  Summary: ASGI python server
5
5
  Author-Email: Max Smolin <max@latch.bio>
6
6
  License: CC0-1.0
@@ -147,15 +147,15 @@ def get_signer_sub(auth_header: str) -> Authorization:
147
147
  # ) from e
148
148
 
149
149
  with app_tracer.start_as_current_span("decode jwt"):
150
+ audience = config.audience if jwt_key != config.self_signed_jwk else None
150
151
  try:
151
152
  jwt_data: dict[str, str] = jwt.decode(
152
153
  oauth_token,
153
154
  key=jwt_key,
154
155
  algorithms=["RS256", "HS256"],
155
156
  # fixme(maximsmol): gut this abomination
156
- audience=(
157
- config.audience if jwt_key != config.self_signed_jwk else None
158
- ),
157
+ audience=audience,
158
+ options={"verify_aud": audience is not None},
159
159
  )
160
160
  except jwt.exceptions.InvalidTokenError as e:
161
161
  # todo(maximsmol): filter out scope failures and include the correct error code
@@ -27,9 +27,42 @@ class Context(
27
27
 
28
28
  @trace_app_function
29
29
  async def accept_connection(
30
- self: Self, *, subprotocol: str | None = None, headers: Headers | None = None
30
+ self: Self,
31
+ *,
32
+ subprotocol: str | None = None,
33
+ headers: Headers | None = None,
34
+ negotiate_permessage_deflate: bool = False,
31
35
  ) -> None:
32
- await accept_connection(self.send, subprotocol=subprotocol, headers=headers)
36
+ if not negotiate_permessage_deflate:
37
+ await accept_connection(self.send, subprotocol=subprotocol, headers=headers)
38
+ return
39
+
40
+ offer = self.header_str("sec-websocket-extensions")
41
+
42
+ headers_out: Headers = {}
43
+ if headers is not None:
44
+ headers_out = dict(headers)
45
+
46
+ def _has_extensions_header(h: Headers) -> bool:
47
+ for k in h.keys():
48
+ if isinstance(k, bytes):
49
+ if k.decode("latin-1").lower() == "sec-websocket-extensions":
50
+ return True
51
+ else:
52
+ if k.lower() == "sec-websocket-extensions":
53
+ return True
54
+ return False
55
+
56
+ if (
57
+ offer is not None
58
+ and "permessage-deflate" in offer.replace(" ", "").lower()
59
+ and not _has_extensions_header(headers_out)
60
+ ):
61
+ headers_out["Sec-WebSocket-Extensions"] = "permessage-deflate"
62
+
63
+ await accept_connection(
64
+ self.send, subprotocol=subprotocol, headers=headers_out or headers
65
+ )
33
66
 
34
67
  @trace_app_function
35
68
  async def receive_message(self: Self, cls: type[T]) -> T:
@@ -22,6 +22,7 @@ otel_header_whitelist = {
22
22
  "sec-gpc",
23
23
  "te",
24
24
  "upgrade-insecure-requests",
25
+ "sec-websocket-extensions",
25
26
  "device-memory",
26
27
  "downlink",
27
28
  "dpr",
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "latch-asgi"
3
- version = "1.0.4"
3
+ version = "1.0.6.dev0"
4
4
  description = "ASGI python server"
5
5
  authors = [
6
6
  { name = "Max Smolin", email = "max@latch.bio" },
File without changes
File without changes