From 72158846902726caf24c5b326913dc0ad756f0f1 Mon Sep 17 00:00:00 2001 From: thevickypedia Date: Mon, 15 Jan 2024 08:45:28 +0530 Subject: [PATCH] Allow multiple website entries for CORS Update README.md --- README.md | 6 +++--- docs/README.html | 6 +++--- docs/README.md | 6 +++--- docs/_sources/README.md.txt | 6 +++--- docs/genindex.html | 6 ++++-- docs/index.html | 10 ++++++++-- docs/objects.inv | Bin 897 -> 902 bytes docs/searchindex.js | 2 +- pystream/main.py | 14 ++++---------- pystream/models/config.py | 18 ++++++++++++++---- 10 files changed, 43 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 8a87603..efb02a7 100644 --- a/README.md +++ b/README.md @@ -32,8 +32,8 @@ if __name__ == '__main__': ``` ### Env Variables -> :bulb:   Environment variables can be loaded from any file. _Defaults to `.env`_
-> Set the env var `env_file` to the filename to use custom `.env` files +> :bulb:   Environment variables can be loaded from any file. _Filename defaults to `.env`_
+> To use custom filenames, set the env var `env_file` as `key` and the _filename_ as its `value` **Mandatory** - **USERNAME**: Any username of choice. @@ -46,7 +46,7 @@ if __name__ == '__main__': - **VIDEO_PORT**: Port number to host the application. Defaults to `8000` - **FILE_FORMATS**: Sequence of supported video file formats. Defaults to `(.mp4, .mov)` - **WORKERS**: Number of workers to spin up the `uvicorn` server. Defaults to `1` -- **WEBSITE**: Website to add to CORS configuration. _Required only if tunneled via CDN_ +- **WEBSITE**: List of websites (_supports regex_) to add to CORS configuration. _Required only if tunneled via CDN_ - **AUTO_THUMBNAIL**: Boolean flag to auto generate thumbnail images for preview. Defaults to `True` ## Coding Standards diff --git a/docs/README.html b/docs/README.html index dfe99cc..6c94745 100644 --- a/docs/README.html +++ b/docs/README.html @@ -76,8 +76,8 @@

Sample Usage

Env Variables

-

:bulb:   Environment variables can be loaded from any file. Defaults to .env
-Set the env var env_file to the filename to use custom .env files

+

:bulb:   Environment variables can be loaded from any file. Filename defaults to .env
+To use custom filenames, set the env var env_file as key and the filename as its value

Mandatory

diff --git a/docs/README.md b/docs/README.md index 8a87603..efb02a7 100644 --- a/docs/README.md +++ b/docs/README.md @@ -32,8 +32,8 @@ if __name__ == '__main__': ``` ### Env Variables -> :bulb:   Environment variables can be loaded from any file. _Defaults to `.env`_
-> Set the env var `env_file` to the filename to use custom `.env` files +> :bulb:   Environment variables can be loaded from any file. _Filename defaults to `.env`_
+> To use custom filenames, set the env var `env_file` as `key` and the _filename_ as its `value` **Mandatory** - **USERNAME**: Any username of choice. @@ -46,7 +46,7 @@ if __name__ == '__main__': - **VIDEO_PORT**: Port number to host the application. Defaults to `8000` - **FILE_FORMATS**: Sequence of supported video file formats. Defaults to `(.mp4, .mov)` - **WORKERS**: Number of workers to spin up the `uvicorn` server. Defaults to `1` -- **WEBSITE**: Website to add to CORS configuration. _Required only if tunneled via CDN_ +- **WEBSITE**: List of websites (_supports regex_) to add to CORS configuration. _Required only if tunneled via CDN_ - **AUTO_THUMBNAIL**: Boolean flag to auto generate thumbnail images for preview. Defaults to `True` ## Coding Standards diff --git a/docs/_sources/README.md.txt b/docs/_sources/README.md.txt index 8a87603..efb02a7 100644 --- a/docs/_sources/README.md.txt +++ b/docs/_sources/README.md.txt @@ -32,8 +32,8 @@ if __name__ == '__main__': ``` ### Env Variables -> :bulb:   Environment variables can be loaded from any file. _Defaults to `.env`_
-> Set the env var `env_file` to the filename to use custom `.env` files +> :bulb:   Environment variables can be loaded from any file. _Filename defaults to `.env`_
+> To use custom filenames, set the env var `env_file` as `key` and the _filename_ as its `value` **Mandatory** - **USERNAME**: Any username of choice. @@ -46,7 +46,7 @@ if __name__ == '__main__': - **VIDEO_PORT**: Port number to host the application. Defaults to `8000` - **FILE_FORMATS**: Sequence of supported video file formats. Defaults to `(.mp4, .mov)` - **WORKERS**: Number of workers to spin up the `uvicorn` server. Defaults to `1` -- **WEBSITE**: Website to add to CORS configuration. _Required only if tunneled via CDN_ +- **WEBSITE**: List of websites (_supports regex_) to add to CORS configuration. _Required only if tunneled via CDN_ - **AUTO_THUMBNAIL**: Boolean flag to auto generate thumbnail images for preview. Defaults to `True` ## Coding Standards diff --git a/docs/genindex.html b/docs/genindex.html index 9dbadfc..a1d5655 100644 --- a/docs/genindex.html +++ b/docs/genindex.html @@ -225,6 +225,8 @@

P

+ -
+
  • pystream.models.images @@ -267,8 +271,6 @@

    P

  • module
-
  • pystream.models.squire diff --git a/docs/index.html b/docs/index.html index 81f739a..7795974 100644 --- a/docs/index.html +++ b/docs/index.html @@ -108,7 +108,7 @@

    Models

    Config

    -class pystream.models.config.EnvConfig(_case_sensitive: bool | None = None, _env_prefix: str | None = None, _env_file: DotenvType | None = PosixPath('.'), _env_file_encoding: str | None = None, _env_nested_delimiter: str | None = None, _secrets_dir: str | Path | None = None, *, username: str, password: SecretStr, video_source: Path, video_host: IPv4Address = '127.0.0.1', video_port: int = 8000, file_formats: Sequence[str] = ('.mov', '.mp4'), workers: int = 1, website: Optional[Url] = None, auto_thumbnail: bool = True)
    +class pystream.models.config.EnvConfig(_case_sensitive: bool | None = None, _env_prefix: str | None = None, _env_file: DotenvType | None = PosixPath('.'), _env_file_encoding: str | None = None, _env_nested_delimiter: str | None = None, _secrets_dir: str | Path | None = None, *, username: str, password: SecretStr, video_source: Path, video_host: IPv4Address = '127.0.0.1', video_port: int = 8000, file_formats: Sequence[str] = ('.mov', '.mp4'), workers: int = 1, website: Optional[List[str]] = [], auto_thumbnail: bool = True)

    Configure all env vars and validate using pydantic to share across modules.

    >>> EnvConfig
     
    @@ -155,7 +155,7 @@

    Models
    -website: Optional[Url]
    +website: Optional[List[str]]

    @@ -195,6 +195,12 @@

    Models

    Returns the string notion of IPv4Address object.

    +
    +
    +classmethod parse_website(value: str) List[str]
    +

    Evaluates the string as a list and returns the list of strings.

    +
    +
    diff --git a/docs/objects.inv b/docs/objects.inv index b3f83daf7ec9b15d4f6c290ba55119846f64bd09..be50d21939297875b37ba18f436a81d2e0d1cd2d 100644 GIT binary patch delta 797 zcmV+&1LFLF2Zjfbc7MTc+b|4plHs z$w{4|Z7eI7Ahz^>6iJzsx&g@mZ*!^Z8cfy=*R3wCgzQ@;R0*$nL#_N0-fh2T+f8?> z$RD+)pF&a)7m_1pS99&>qP#k4TcAdlpNLy7RLly;`8g6dG=Hips|pfYoiPvuwqwL` zk4uHR1c^Df)PN#UaMDq+d{3YEU_>>qxL73mF{`(PeE}0)l^GgwOP(5?| z14a}lGGb>5(r}%DO1xeQ_)3Ofh}DP^m{6T1_shT-Z7>z>_LFAR*mkG5kg2pW6Rgsv z<&?a#jvEBlJAa=wYc$fb@BdTS3+zx3B$5zcv?){Fvj|4X>%bGYHNyQ z|7JN$!f3OHwV#XYLvZ&yzFGxc?kA^M&ZR)|Wp1SdPk=Z!hiDHbp>v_qD@_x3-D-tp zugiHp@PCrTc(z~$<_a8dlQ>~asQNOl z_1wyp1lNQkg`(wk_%4`3{L4n}}Y?jZZ4dw&Vu_a>)jHdo6LDkg6 zknq_G11lmLgx)rnl7&I$GE1N+?xZ?HmBL&KC8oPXwAg+4qj3d6wg#a%S;JjaT$5#c z7*;_Hw12vX(?eSX#6PV`YFIDR*tp&lw)r?;@*T)gad;avcjMp9+q4Ngn-O^1 zU!!aO*0RlRGK9h!DBV04?TWiw1L@f*jT{8$Ba?7+hOa brxt1iZi?nq7~V~ugz*R0Yd8M@oG$NFv$BDj delta 792 zcmV+z1LypP2Z0BWc7IK8oG=iE@B1r|+Uug`np@PSQlv(W5~)|q3jsFUmLiQ~as)X0Pp;mqg@3vpF?WUV6 z@<*-dr;rrHh2)6Y)v5M#QC=OjEl{J&PsA-3D#pWcevZTqjen}js)B@8XAA^^?HF;~ z<5Hn6L1NA=HK0fooODz!-_z$k7*P#z9u!(tqF!M-2=iOje?KD5E#?Q({8EG*RL|W0 zfDy%sjM!O%G+bw(60es6zLMb=Vl|=!CRAt1{W35{8%#yJ{iGQ+w%sW%WGZc3307&- za!U5B;|78CE`Mgt8jZB<`~MJz_@Ygj>Xbz=inqzzZ5~!Ssng~{B-GXv$??6w4h5xS zwAsVjP42n}-2INPF+rF6$tjj|DUf_|S{c9-AdV$HI)X{)La6jg)5KkmSz+1h@}jY7 z&rtk@6!T#T7^t$-LQxXRohr1en-^iZ2GI+6Nn$)(FnO-eVNdDZskgX zYn_oo(egTc8<8iGAk6QM`h}Zxrps$kU^oFgS52{-Zqz#g+b<4mOxS5`SJu+3Ueuxm~H^kV)x;X#uWtF8ie9x4R={_O_uFpSOqcA z>K^7tt$zrJe_FG!;b}~v;i?AK0579c8J+^bfU8|d=>A}*6~ZbOx^l&K0|Bx*b|KBU zYVJ-3{yr3wmQ&qZi;pxob(2Wtj-x1Wjk7`N7qQ~KC>HPI{{Y6_sUwxX60Pys3lFW5 zNgc84=7_0)936=UgkpNy9v2`i9g6tExV^wHk$=>MD;A=QvE+rF-APfLRX*O{{J6i( zkjm>)7uohI3vc|4?2pgW)8SaKalI*Q^Kri9JCLK|@HS}f#=o1lX%qHjM&NCKjiLEl z%Qm~o5DIIcbn{%cEADO$q_e3~`K05 None: """Tasks that need to run during the API startup.""" + logger.info('Setting CORS policy.') origins = ["http://localhost.com", "https://localhost.com"] - if config.env.website: - logger.info('Setting CORS policy.') - origins.extend([ - f"http://{config.env.website.host}", - f"https://{config.env.website.host}", - f"http://{config.env.website.host}/*", - f"https://{config.env.website.host}/*" - ]) - kwargs = dict(allow_origins=origins) - app.add_middleware(CORSMiddleware, **kwargs) + origins.extend(config.env.website) + origins.extend(map((lambda x: x + '/*'), config.env.website)) + app.add_middleware(CORSMiddleware, allow_origins=origins) def start(**kwargs) -> None: diff --git a/pystream/models/config.py b/pystream/models/config.py index 54bcae1..1e80c61 100644 --- a/pystream/models/config.py +++ b/pystream/models/config.py @@ -1,10 +1,10 @@ import os import socket from ipaddress import IPv4Address -from typing import Sequence, Union +from typing import List, Sequence, Union -from pydantic import (BaseModel, DirectoryPath, Field, HttpUrl, PositiveInt, - SecretStr, field_validator) +from pydantic import (BaseModel, DirectoryPath, Field, PositiveInt, SecretStr, + field_validator) from pydantic_settings import BaseSettings @@ -24,7 +24,7 @@ class EnvConfig(BaseSettings): file_formats: Sequence[str] = (".mov", ".mp4") workers: int = Field(1, le=os.cpu_count(), ge=1, env="WORKERS") - website: Union[HttpUrl, None] = None + website: Union[List[str], None] = [] auto_thumbnail: bool = True class Config: @@ -41,6 +41,16 @@ def parse_video_host(cls, value: IPv4Address) -> str: """Returns the string notion of IPv4Address object.""" return str(value) + # noinspection PyMethodParameters + @field_validator("website", mode='before', check_fields=True) + def parse_website(cls, value: str) -> List[str]: + """Evaluates the string as a list and returns the list of strings.""" + if not value: + return [] + val = eval(value) + assert isinstance(val, list) + return val + class FileIO(BaseModel): """Loads all the files' path required/created.