Skip to content
This repository was archived by the owner on May 30, 2025. It is now read-only.

Commit 06a63e6

Browse files
author
yashksaini-coder
committed
Setup post template for running the AI post reqs
1 parent 6942958 commit 06a63e6

File tree

2 files changed

+358
-1
lines changed

2 files changed

+358
-1
lines changed

app.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
1-
from fastapi import FastAPI, Request, Depends
1+
from fastapi import FastAPI, Request, Depends, HTTPException
22
from fastapi.middleware.cors import CORSMiddleware
3+
from fastapi.responses import HTMLResponse
4+
from fastapi.templating import Jinja2Templates
5+
from starlette.exceptions import HTTPException as StarletteHTTPException
6+
import datetime
37
from routes.stockRoutes import router as stock_router
48
from routes.agentRoutes import router as agent_router
59

610
app = FastAPI()
11+
templates = Jinja2Templates(directory="templates")
12+
713
app.add_middleware(
814
CORSMiddleware,
915
allow_origins=["*"],
@@ -12,6 +18,28 @@
1218
allow_headers=["*"],
1319
)
1420

21+
@app.exception_handler(StarletteHTTPException)
22+
async def http_exception_handler(request: Request, exc: StarletteHTTPException):
23+
if exc.status_code == 405: # Method Not Allowed
24+
# Extract the path from the request
25+
path = request.url.path
26+
# Get the current year for the template
27+
current_year = datetime.datetime.now().year
28+
29+
return templates.TemplateResponse(
30+
"post.html",
31+
{
32+
"request": request,
33+
"route_path": path,
34+
"full_path": str(request.url),
35+
"description": "This endpoint requires a different HTTP method than the one used.",
36+
"current_year": current_year,
37+
"example_query": "{}" # Default empty JSON object
38+
},
39+
status_code=405
40+
)
41+
raise exc # Re-raise other HTTP exceptions
42+
1543
app.include_router(stock_router)
1644
app.include_router(agent_router)
1745

templates/post.html

Lines changed: 329 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,329 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Investo API - {{ route_path }}</title>
7+
<style>
8+
:root {
9+
--bg-color: #000000;
10+
--text-color: #8b1eea;
11+
--highlight-color: #26b8e5;
12+
--secondary-color: #ffffff;
13+
--border-color: #8b1eea;
14+
--success-color: #49cc90;
15+
--font-family: 'Courier New', Courier, monospace;
16+
}
17+
18+
body {
19+
background-color: var(--bg-color);
20+
color: var(--text-color);
21+
font-family: var(--font-family);
22+
margin: 0;
23+
padding: 20px;
24+
line-height: 1.6;
25+
}
26+
27+
.terminal {
28+
max-width: 900px;
29+
margin: 0 auto;
30+
border: 1px solid var(--border-color);
31+
border-radius: 5px;
32+
padding: 15px;
33+
box-shadow: 0 0 10px rgba(139, 30, 234, 0.2);
34+
}
35+
36+
.endpoint {
37+
margin-bottom: 20px;
38+
border-bottom: 1px dotted var(--border-color);
39+
padding-bottom: 15px;
40+
}
41+
42+
.endpoint h2 {
43+
color: var(--highlight-color);
44+
margin-top: 0;
45+
}
46+
47+
.method {
48+
background-color: #1e1e1e;
49+
padding: 3px 8px;
50+
border-radius: 3px;
51+
font-weight: bold;
52+
color: var(--success-color);
53+
}
54+
55+
.request-body {
56+
background-color: #1a1a1a;
57+
padding: 15px;
58+
border-radius: 5px;
59+
margin: 10px 0;
60+
}
61+
62+
.request-body pre {
63+
margin: 0;
64+
white-space: pre-wrap;
65+
}
66+
67+
.param {
68+
margin-bottom: 10px;
69+
padding: 10px;
70+
background-color: #1a1a1a;
71+
border-radius: 5px;
72+
}
73+
74+
.param-header {
75+
color: var(--highlight-color);
76+
font-weight: bold;
77+
margin-bottom: 5px;
78+
}
79+
80+
.param-details {
81+
display: grid;
82+
grid-template-columns: 150px 1fr;
83+
gap: 10px;
84+
margin-left: 15px;
85+
}
86+
87+
.param-label {
88+
color: var(--secondary-color);
89+
font-weight: bold;
90+
}
91+
92+
.param-value {
93+
color: var(--text-color);
94+
}
95+
96+
.try-it {
97+
margin-top: 20px;
98+
padding: 20px;
99+
background-color: #1a1a1a;
100+
border-radius: 5px;
101+
}
102+
103+
.try-it h3 {
104+
color: var(--highlight-color);
105+
margin-top: 0;
106+
}
107+
108+
.input-group {
109+
margin-bottom: 15px;
110+
}
111+
112+
.input-group label {
113+
display: block;
114+
margin-bottom: 5px;
115+
color: var(--secondary-color);
116+
}
117+
118+
.input-group input, .input-group textarea {
119+
width: 100%;
120+
padding: 8px;
121+
background-color: #2a2a2a;
122+
border: 1px solid var(--border-color);
123+
color: var(--text-color);
124+
border-radius: 3px;
125+
font-family: var(--font-family);
126+
}
127+
128+
.submit-btn {
129+
background-color: var(--success-color);
130+
color: var(--bg-color);
131+
border: none;
132+
padding: 10px 20px;
133+
border-radius: 3px;
134+
cursor: pointer;
135+
font-weight: bold;
136+
}
137+
138+
.submit-btn:hover {
139+
opacity: 0.9;
140+
}
141+
142+
.response-preview {
143+
margin-top: 15px;
144+
display: none;
145+
background-color: #1a1a1a;
146+
padding: 15px;
147+
border-radius: 5px;
148+
}
149+
150+
.response-preview h4 {
151+
color: var(--highlight-color);
152+
margin-top: 0;
153+
margin-bottom: 10px;
154+
}
155+
156+
.response-preview pre {
157+
margin: 0;
158+
white-space: pre-wrap;
159+
background-color: #2a2a2a;
160+
padding: 15px;
161+
border-radius: 5px;
162+
overflow-x: auto;
163+
color: var(--secondary-color);
164+
}
165+
166+
.response-preview code {
167+
font-family: var(--font-family);
168+
font-size: 14px;
169+
line-height: 1.5;
170+
}
171+
172+
/* Add a loading indicator */
173+
.loading {
174+
display: none;
175+
text-align: center;
176+
margin: 10px 0;
177+
color: var(--highlight-color);
178+
}
179+
180+
.loading::after {
181+
content: "⏳";
182+
animation: loading-spin 1s linear infinite;
183+
display: inline-block;
184+
}
185+
186+
@keyframes loading-spin {
187+
from { transform: rotate(0deg); }
188+
to { transform: rotate(360deg); }
189+
}
190+
191+
footer {
192+
margin-top: 30px;
193+
text-align: center;
194+
font-size: 0.8em;
195+
color: var(--secondary-color);
196+
border-top: 1px solid var(--border-color);
197+
padding-top: 20px;
198+
}
199+
200+
a {
201+
color: var(--highlight-color);
202+
text-decoration: none;
203+
}
204+
205+
a:hover {
206+
text-decoration: underline;
207+
}
208+
209+
.terminal-input {
210+
display: flex;
211+
align-items: center;
212+
margin-bottom: 20px;
213+
}
214+
215+
.prompt {
216+
color: var(--highlight-color);
217+
margin-right: 10px;
218+
font-weight: bold;
219+
}
220+
221+
.blink {
222+
animation: blink-animation 1s steps(2, start) infinite;
223+
}
224+
225+
@keyframes blink-animation {
226+
to {
227+
visibility: hidden;
228+
}
229+
}
230+
</style>
231+
</head>
232+
<body>
233+
<div class="terminal">
234+
<div class="terminal-input">
235+
<span class="prompt">investo@api:~$</span>
236+
<span id="command-text">{{ route_path }} <span class="blink">_</span></span>
237+
</div>
238+
<div class="endpoint">
239+
<h2>{{ route_path }}</h2>
240+
<p><span class="method">POST</span> {{ full_path }}</p>
241+
<p>{{ description }}</p>
242+
243+
{% if request_body %}
244+
<h3>Request Body</h3>
245+
<div class="request-body">
246+
<pre><code>{{ request_body }}</code></pre>
247+
</div>
248+
{% endif %}
249+
250+
{% if parameters %}
251+
<h3>Parameters</h3>
252+
<div class="params-container">
253+
{% for param in parameters %}
254+
<div class="param">
255+
<div class="param-header">{{ param.name }}</div>
256+
<div class="param-details">
257+
<span class="param-label">Type:</span>
258+
<span class="param-value">{{ param.type }}</span>
259+
<span class="param-label">Description:</span>
260+
<span class="param-value">{{ param.description }}</span>
261+
</div>
262+
</div>
263+
{% endfor %}
264+
</div>
265+
{% endif %}
266+
267+
<div class="try-it">
268+
<h3>Try it out</h3>
269+
<form id="api-form" onsubmit="return sendRequest(event)">
270+
<div class="input-group">
271+
<label for="request-body">Request Body (JSON):</label>
272+
<textarea id="request-body" rows="5">{{ example_query }}</textarea>
273+
</div>
274+
<button type="submit" class="submit-btn">Send Request</button>
275+
</form>
276+
<div id="loading" class="loading">Processing request...</div>
277+
<div id="response-preview" class="response-preview">
278+
<h4>Response</h4>
279+
<pre><code id="response-content"></code></pre>
280+
</div>
281+
</div>
282+
</div>
283+
</div>
284+
285+
<footer>
286+
<p>Investo API &copy; {{ current_year }} | <a href="/">Home</a> | <a href="/docs">Documentation</a></p>
287+
</footer>
288+
289+
<script>
290+
async function sendRequest(event) {
291+
event.preventDefault();
292+
293+
const form = document.getElementById('api-form');
294+
const responsePreview = document.getElementById('response-preview');
295+
const responseContent = document.getElementById('response-content');
296+
const loading = document.getElementById('loading');
297+
const submitBtn = document.querySelector('.submit-btn');
298+
299+
// Hide previous response and show loading
300+
responsePreview.style.display = 'none';
301+
loading.style.display = 'block';
302+
submitBtn.disabled = true;
303+
304+
try {
305+
const requestBody = document.getElementById('request-body').value;
306+
const response = await fetch('{{ full_path }}', {
307+
method: 'POST',
308+
headers: {
309+
'Content-Type': 'application/json',
310+
},
311+
body: requestBody
312+
});
313+
314+
const data = await response.json();
315+
responseContent.textContent = JSON.stringify(data, null, 4);
316+
responsePreview.style.display = 'block';
317+
} catch (error) {
318+
responseContent.textContent = `Error: ${error.message}`;
319+
responsePreview.style.display = 'block';
320+
} finally {
321+
loading.style.display = 'none';
322+
submitBtn.disabled = false;
323+
}
324+
325+
return false;
326+
}
327+
</script>
328+
</body>
329+
</html>

0 commit comments

Comments
 (0)