import base64 from urllib.parse import parse_qs, urlencode from pydantic import BaseModel, Field, field_validator class RequestHeaders(BaseModel): request_signature: str = Field(validation_alias="x-twilio-signature") host: str scheme: str = Field(validation_alias="x-forwarded-proto") class Event(BaseModel): headers: RequestHeaders params: dict[str, str] | None = Field( default=None, validation_alias="queryStringParameters" ) path: str body: dict[str, str] @field_validator("body", mode="before") def decode_body(cls, body: str) -> dict[str, str]: decoded_body = base64.b64decode(body).decode() body_dict = parse_qs(decoded_body, keep_blank_values=True) body_dict_prepared = {k: v[0] for k, v in body_dict.items()} return body_dict_prepared @property def request_full_uri(self) -> str: return ( f"{self.headers.scheme}://{self.headers.host}{self.path}{self.request_qs}" ) @property def request_qs(self) -> str: if not self.params: return "" return f"?{urlencode(sorted(self.params.items()))}"