This commit is contained in:
Waylon Walker 2025-11-22 22:00:19 -06:00
parent 2e03f31a09
commit 9c83f862e0
16 changed files with 894 additions and 10 deletions

2
docker-entrypoint.sh Normal file
View file

@ -0,0 +1,2 @@
#!/bin/bash
fdr_app app run

View file

@ -10,6 +10,8 @@ metadata:
name: fastapi-dynamic-response
namespace: fastapi-dynamic-response
spec:
selector:
app: fastapi-dynamic-response
ports:
- name: "8000"
port: 8000
@ -20,6 +22,12 @@ kind: Deployment
metadata:
name: fastapi-dynamic-response
namespace: fastapi-dynamic-response
labels:
app: fastapi-dynamic-response
version: "0.0.3"
owner: "waylonwalker"
annotations:
email: "fastapi-dynamic-response@fastapi-dynamic-response.com"
spec:
replicas: 3
selector:
@ -35,17 +43,16 @@ spec:
labels:
app: fastapi-dynamic-response
spec:
# affinity:
# podAntiAffinity:
# requiredDuringSchedulingIgnoredDuringExecution:
# - labelSelector:
# matchLabels:
# app: fastapi-dynamic-response
# topologyKey: "kubernetes.io/hostname"
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: fastapi-dynamic-response
topologyKey: "kubernetes.io/hostname"
containers:
- image: docker.io/waylonwalker/fastapi-dynamic-response:0.0.2
name: fastapi-dynamic-response
args: ["./.venv/bin/uvicorn", "src.fastapi_dynamic_response.main:app", "--host", "0.0.0.0", "--port", "8000"]
ports:
- containerPort: 8000
protocol: TCP
@ -90,8 +97,9 @@ metadata:
name: fastapi-dynamic-response
namespace: fastapi-dynamic-response
spec:
ingressClassName: nginx
rules:
- host: app.fokais.com
- host: fastapi-dynamic-response.waylonwalker.com
http:
paths:
- backend:

12
kind-config.yaml Normal file
View file

@ -0,0 +1,12 @@
# kind-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
extraPortMappings:
- containerPort: 30080
hostPort: 30080
protocol: TCP
extraMounts:
- hostPath: ./sqlite-data
containerPath: /sqlite-data

BIN
kube-linter Normal file

Binary file not shown.

BIN
kube-score Normal file

Binary file not shown.

View file

@ -0,0 +1,18 @@
receivers:
otlp:
protocols:
grpc:
http:
exporters:
otlp:
endpoint: "0.0.0.0:14250"
tls:
insecure: true
processors:
batch:
service:
pipelines:
traces:
receivers: [otlp]
processors: [batch]
exporters: [otlp]

View file

@ -37,6 +37,7 @@ dependencies = [
"rich>=13.9.2",
"selenium>=4.25.0",
"structlog>=24.4.0",
"typer>=0.12.5",
"uvicorn>=0.31.1",
"weasyprint>=61.2",
]
@ -46,6 +47,9 @@ Documentation = "https://github.com/U.N. Owen/fastapi-dynamic-response#readme"
Issues = "https://github.com/U.N. Owen/fastapi-dynamic-response/issues"
Source = "https://github.com/U.N. Owen/fastapi-dynamic-response"
[project.scripts]
fdr_app = "fastapi_dynamic_response.cli.cli:app"
[tool.hatch.version]
path = "src/fastapi_dynamic_response/__about__.py"

131
requirements.txt Normal file
View file

@ -0,0 +1,131 @@
# This file was autogenerated by uv via the following command:
# uv pip compile pyproject.toml -o requirements.txt
annotated-types==0.7.0
# via pydantic
anyio==4.6.2.post1
# via starlette
attrs==24.2.0
# via
# outcome
# trio
brotli==1.1.0
# via fonttools
certifi==2024.8.30
# via selenium
cffi==1.17.1
# via weasyprint
click==8.1.7
# via uvicorn
cssselect2==0.7.0
# via weasyprint
fastapi==0.115.3
# via fastapi-dynamic-response (pyproject.toml)
fonttools==4.54.1
# via weasyprint
h11==0.14.0
# via
# uvicorn
# wsproto
html2text==2024.2.26
# via fastapi-dynamic-response (pyproject.toml)
html5lib==1.1
# via weasyprint
idna==3.10
# via
# anyio
# trio
itsdangerous==2.2.0
# via fastapi-dynamic-response (pyproject.toml)
jinja2==3.1.4
# via fastapi-dynamic-response (pyproject.toml)
levenshtein==0.26.0
# via python-levenshtein
markdown==3.7
# via fastapi-dynamic-response (pyproject.toml)
markdown-it-py==3.0.0
# via rich
markupsafe==3.0.2
# via jinja2
mdurl==0.1.2
# via markdown-it-py
outcome==1.3.0.post0
# via trio
pillow==11.0.0
# via
# fastapi-dynamic-response (pyproject.toml)
# weasyprint
pycparser==2.22
# via cffi
pydantic==2.9.2
# via
# fastapi
# pydantic-settings
pydantic-core==2.23.4
# via pydantic
pydantic-settings==2.6.0
# via fastapi-dynamic-response (pyproject.toml)
pydyf==0.8.0
# via
# fastapi-dynamic-response (pyproject.toml)
# weasyprint
pygments==2.18.0
# via rich
pyphen==0.16.0
# via weasyprint
pysocks==1.7.1
# via urllib3
python-dotenv==1.0.1
# via pydantic-settings
python-levenshtein==0.26.0
# via fastapi-dynamic-response (pyproject.toml)
rapidfuzz==3.10.0
# via levenshtein
rich==13.9.3
# via fastapi-dynamic-response (pyproject.toml)
selenium==4.25.0
# via fastapi-dynamic-response (pyproject.toml)
six==1.16.0
# via html5lib
sniffio==1.3.1
# via
# anyio
# trio
sortedcontainers==2.4.0
# via trio
starlette==0.41.0
# via fastapi
structlog==24.4.0
# via fastapi-dynamic-response (pyproject.toml)
tinycss2==1.3.0
# via
# cssselect2
# weasyprint
trio==0.27.0
# via
# selenium
# trio-websocket
trio-websocket==0.11.1
# via selenium
typing-extensions==4.12.2
# via
# fastapi
# pydantic
# pydantic-core
# selenium
urllib3==2.2.3
# via selenium
uvicorn==0.32.0
# via fastapi-dynamic-response (pyproject.toml)
weasyprint==61.2
# via fastapi-dynamic-response (pyproject.toml)
webencodings==0.5.1
# via
# cssselect2
# html5lib
# tinycss2
websocket-client==1.8.0
# via selenium
wsproto==1.2.0
# via trio-websocket
zopfli==0.2.3.post1
# via fonttools

612
sitemap.html Normal file
View file

@ -0,0 +1,612 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sitemap</title>
<style>
*, ::before, ::after {
}
::backdrop {
}
/*
! tailwindcss v3.4.13 | MIT License | https://tailwindcss.com
*/
/*
1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
*/
*,
::before,
::after {
box-sizing: border-box;
/* 1 */
border-width: 0;
/* 2 */
border-style: solid;
/* 2 */
border-color: #e5e7eb;
/* 2 */
}
::before,
::after {
}
/*
1. Use a consistent sensible line-height in all browsers.
2. Prevent adjustments of font size after orientation changes in iOS.
3. Use a more readable tab size.
4. Use the user's configured `sans` font-family by default.
5. Use the user's configured `sans` font-feature-settings by default.
6. Use the user's configured `sans` font-variation-settings by default.
7. Disable tap highlights on iOS
*/
html,
:host {
line-height: 1.5;
/* 1 */
-webkit-text-size-adjust: 100%;
/* 2 */
-moz-tab-size: 4;
/* 3 */
-o-tab-size: 4;
tab-size: 4;
/* 3 */
font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
/* 4 */
font-feature-settings: normal;
/* 5 */
font-variation-settings: normal;
/* 6 */
-webkit-tap-highlight-color: transparent;
/* 7 */
}
/*
1. Remove the margin in all browsers.
2. Inherit line-height from `html` so users can set them as a class directly on the `html` element.
*/
body {
margin: 0;
/* 1 */
line-height: inherit;
/* 2 */
}
/*
1. Add the correct height in Firefox.
2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)
3. Ensure horizontal rules are visible by default.
*/
hr {
height: 0;
/* 1 */
color: inherit;
/* 2 */
border-top-width: 1px;
/* 3 */
}
/*
Add the correct text decoration in Chrome, Edge, and Safari.
*/
abbr:where([title]) {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
}
/*
Remove the default font size and weight for headings.
*/
h1,
h2,
h3,
h4,
h5,
h6 {
font-size: inherit;
font-weight: inherit;
}
/*
Reset links to optimize for opt-in styling instead of opt-out.
*/
a {
color: inherit;
text-decoration: inherit;
}
/*
Add the correct font weight in Edge and Safari.
*/
b,
strong {
font-weight: bolder;
}
/*
1. Use the user's configured `mono` font-family by default.
2. Use the user's configured `mono` font-feature-settings by default.
3. Use the user's configured `mono` font-variation-settings by default.
4. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
samp,
pre {
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
/* 1 */
font-feature-settings: normal;
/* 2 */
font-variation-settings: normal;
/* 3 */
font-size: 1em;
/* 4 */
}
/*
Add the correct font size in all browsers.
*/
small {
font-size: 80%;
}
/*
Prevent `sub` and `sup` elements from affecting the line height in all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/*
1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)
2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)
3. Remove gaps between table borders by default.
*/
table {
text-indent: 0;
/* 1 */
border-color: inherit;
/* 2 */
border-collapse: collapse;
/* 3 */
}
/*
1. Change the font styles in all browsers.
2. Remove the margin in Firefox and Safari.
3. Remove default padding in all browsers.
*/
button,
input,
optgroup,
select,
textarea {
font-family: inherit;
/* 1 */
font-feature-settings: inherit;
/* 1 */
font-variation-settings: inherit;
/* 1 */
font-size: 100%;
/* 1 */
font-weight: inherit;
/* 1 */
line-height: inherit;
/* 1 */
letter-spacing: inherit;
/* 1 */
color: inherit;
/* 1 */
margin: 0;
/* 2 */
padding: 0;
/* 3 */
}
/*
Remove the inheritance of text transform in Edge and Firefox.
*/
button,
select {
text-transform: none;
}
/*
1. Correct the inability to style clickable types in iOS and Safari.
2. Remove default button styles.
*/
button,
input:where([type='button']),
input:where([type='reset']),
input:where([type='submit']) {
-webkit-appearance: button;
/* 1 */
background-color: transparent;
/* 2 */
background-image: none;
/* 2 */
}
/*
Use the modern Firefox focus style for all focusable elements.
*/
:-moz-focusring {
outline: auto;
}
/*
Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)
*/
:-moz-ui-invalid {
box-shadow: none;
}
/*
Add the correct vertical alignment in Chrome and Firefox.
*/
progress {
vertical-align: baseline;
}
/*
Correct the cursor style of increment and decrement buttons in Safari.
*/
::-webkit-inner-spin-button,
::-webkit-outer-spin-button {
height: auto;
}
/*
1. Correct the odd appearance in Chrome and Safari.
2. Correct the outline style in Safari.
*/
[type='search'] {
-webkit-appearance: textfield;
/* 1 */
outline-offset: -2px;
/* 2 */
}
/*
Remove the inner padding in Chrome and Safari on macOS.
*/
::-webkit-search-decoration {
-webkit-appearance: none;
}
/*
1. Correct the inability to style clickable types in iOS and Safari.
2. Change font properties to `inherit` in Safari.
*/
::-webkit-file-upload-button {
-webkit-appearance: button;
/* 1 */
font: inherit;
/* 2 */
}
/*
Add the correct display in Chrome and Safari.
*/
summary {
display: list-item;
}
/*
Removes the default spacing and border for appropriate elements.
*/
blockquote,
dl,
dd,
h1,
h2,
h3,
h4,
h5,
h6,
hr,
figure,
p,
pre {
margin: 0;
}
fieldset {
margin: 0;
padding: 0;
}
legend {
padding: 0;
}
ol,
ul,
menu {
list-style: none;
margin: 0;
padding: 0;
}
/*
Reset default styling for dialogs.
*/
dialog {
padding: 0;
}
/*
Prevent resizing textareas horizontally by default.
*/
textarea {
resize: vertical;
}
/*
1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)
2. Set the default placeholder color to the user's configured gray 400 color.
*/
input::-moz-placeholder, textarea::-moz-placeholder {
opacity: 1;
/* 1 */
color: #9ca3af;
/* 2 */
}
input::placeholder,
textarea::placeholder {
opacity: 1;
/* 1 */
color: #9ca3af;
/* 2 */
}
/*
Set the default cursor for buttons.
*/
button,
[role="button"] {
cursor: pointer;
}
/*
Make sure disabled buttons don't get the pointer cursor.
*/
:disabled {
cursor: default;
}
/*
1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)
2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)
This can trigger a poorly considered lint error in some tools but is included by design.
*/
img,
svg,
video,
canvas,
audio,
iframe,
embed,
object {
display: block;
/* 1 */
vertical-align: middle;
/* 2 */
}
/*
Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)
*/
img,
video {
max-width: 100%;
height: auto;
}
/* Make elements with the HTML hidden attribute stay hidden by default */
[hidden] {
display: none;
}
.container {
width: 100%;
}
@media (min-width: 640px) {
.container {
max-width: 640px;
}
}
@media (min-width: 768px) {
.container {
max-width: 768px;
}
}
@media (min-width: 1024px) {
.container {
max-width: 1024px;
}
}
@media (min-width: 1280px) {
.container {
max-width: 1280px;
}
}
@media (min-width: 1536px) {
.container {
max-width: 1536px;
}
}
.mx-auto {
margin-left: auto;
margin-right: auto;
}
.mt-auto {
margin-top: auto;
}
.block {
display: block;
}
.flex {
display: flex;
}
.min-h-screen {
min-height: 100vh;
}
.flex-col {
flex-direction: column;
}
.items-center {
align-items: center;
}
.justify-end {
justify-content: flex-end;
}
.justify-between {
justify-content: space-between;
}
.space-x-4 > :not([hidden]) ~ :not([hidden]) {
}
.bg-gray-800 {
}
.bg-gray-900 {
}
.p-4 {
padding: 1rem;
}
.text-center {
text-align: center;
}
.text-xl {
font-size: 1.25rem;
line-height: 1.75rem;
}
.font-bold {
font-weight: 700;
}
.text-gray-200 {
}
.text-teal-400 {
}
.hover\:text-teal-300:hover {
}
</style>
</head>
<body class="bg-gray-900 text-gray-200 min-h-screen flex flex-col">
<header class="bg-gray-800 p-4">
<div class="container mx-auto flex justify-between items-center">
<a href="/" class="text-xl font-bold text-teal-400">FastAPI Dynamic Response</a>
<nav class="space-x-4">
<a href="/example" class="hover:text-teal-300">Example</a>
<a href="/another-example" class="hover:text-teal-300">Another Example</a>
<a href="/message" class="hover:text-teal-300">Message</a>
<a href="/sitemap" class="hover:text-teal-300">Sitemap</a>
</nav>
</div>
</header>
<main class="container mx-auto p-4">
<h1>Sitemap</h1>
<li><a href="/livez">/livez</a> </li>
<li><a href="/readyz">/readyz</a> </li>
<li><a href="/healthz">/healthz</a> </li>
<li><a href="/example">/example</a> </li>
<li><a href="/another-example">/another-example</a> </li>
<li><a href="/message">/message</a> </li>
<li><a href="/static">/static</a> </li>
<li><a href="/sitemap">/sitemap</a> </li>
</main>
<footer class="bg-gray-800 text-center p-4 mt-auto justify-end">
<p>&copy; 2024 FastApi Dynamic Response</p>
</footer>
</body>
</html>

0
sitemap.pdf Normal file
View file

BIN
sitemap.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View file

@ -0,0 +1,26 @@
import typer
import uvicorn
from fastapi_dynamic_response import settings
app_app = typer.Typer()
@app_app.callback()
def app():
"model cli"
@app_app.command()
def run(
env: str = typer.Option(
"local",
help="the environment to use",
),
):
uvicorn.run(**settings.api_server.dict())
if __name__ == "__main__":
app_app()

View file

@ -0,0 +1,26 @@
import typer
import uvicorn
from fastapi_dynamic_response.settings import settings
app_app = typer.Typer()
@app_app.callback()
def app():
"model cli"
@app_app.command()
def run(
env: str = typer.Option(
"local",
help="the environment to use",
),
):
uvicorn.run(**settings.api_server.dict())
if __name__ == "__main__":
app_app()

View file

@ -0,0 +1,7 @@
import typer
from fastapi_dynamic_response.cli.app import app_app
app = typer.Typer()
app.add_typer(app_app, name="app")

View file

@ -1,10 +1,22 @@
from pydantic import model_validator
from pydantic import BaseModel, model_validator
from pydantic_settings import BaseSettings
class ApiServer(BaseModel):
app: str = "fastapi_dynamic_response.main:app"
port: int = 8000
reload: bool = True
log_level: str = "info"
host: str = "0.0.0.0"
workers: int = 1
forwarded_allow_ips: str = "*"
proxy_headers: bool = True
class Settings(BaseSettings):
ENV: str = "local"
DEBUG: bool = False
api_server: ApiServer = ApiServer()
class Config:
env_file = "config.env"

26
uv.lock generated
View file

@ -335,6 +335,7 @@ dependencies = [
{ name = "rich" },
{ name = "selenium" },
{ name = "structlog" },
{ name = "typer" },
{ name = "uvicorn" },
{ name = "weasyprint" },
]
@ -353,6 +354,7 @@ requires-dist = [
{ name = "rich", specifier = ">=13.9.2" },
{ name = "selenium", specifier = ">=4.25.0" },
{ name = "structlog", specifier = ">=24.4.0" },
{ name = "typer", specifier = ">=0.12.5" },
{ name = "uvicorn", specifier = ">=0.31.1" },
{ name = "weasyprint", specifier = ">=61.2" },
]
@ -1117,6 +1119,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/aa/85/fa44f23dd5d5066a72f7c4304cce4b5ff9a6e7fd92431a48b2c63fbf63ec/selenium-4.25.0-py3-none-any.whl", hash = "sha256:3798d2d12b4a570bc5790163ba57fef10b2afee958bf1d80f2a3cf07c4141f33", size = 9693127 },
]
[[package]]
name = "shellingham"
version = "1.5.4"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755 },
]
[[package]]
name = "six"
version = "1.16.0"
@ -1210,6 +1221,21 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/48/be/a9ae5f50cad5b6f85bd2574c2c923730098530096e170c1ce7452394d7aa/trio_websocket-0.11.1-py3-none-any.whl", hash = "sha256:520d046b0d030cf970b8b2b2e00c4c2245b3807853ecd44214acd33d74581638", size = 17408 },
]
[[package]]
name = "typer"
version = "0.12.5"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "click" },
{ name = "rich" },
{ name = "shellingham" },
{ name = "typing-extensions" },
]
sdist = { url = "https://files.pythonhosted.org/packages/c5/58/a79003b91ac2c6890fc5d90145c662fd5771c6f11447f116b63300436bc9/typer-0.12.5.tar.gz", hash = "sha256:f592f089bedcc8ec1b974125d64851029c3b1af145f04aca64d69410f0c9b722", size = 98953 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/a8/2b/886d13e742e514f704c33c4caa7df0f3b89e5a25ef8db02aa9ca3d9535d5/typer-0.12.5-py3-none-any.whl", hash = "sha256:62fe4e471711b147e3365034133904df3e235698399bc4de2b36c8579298d52b", size = 47288 },
]
[[package]]
name = "typing-extensions"
version = "4.12.2"