dpv007 commited on
Commit
37391fe
·
verified ·
1 Parent(s): ddeac38

Create main.py

Browse files
Files changed (1) hide show
  1. main.py +120 -0
main.py ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import httpx
2
+ from urllib.parse import urlparse, quote_plus
3
+
4
+ from fastapi import FastAPI, Request, Query, Form
5
+ from fastapi.responses import HTMLResponse, Response, RedirectResponse
6
+ from fastapi.templating import Jinja2Templates
7
+
8
+ app = FastAPI()
9
+
10
+ templates = Jinja2Templates(directory="templates")
11
+
12
+
13
+ def sanitize_url(url: str) -> str:
14
+ url = url.strip()
15
+ if not url:
16
+ return ""
17
+ # If it's just a word, treat it as search later
18
+ if "://" not in url:
19
+ return url
20
+ p = urlparse(url)
21
+ if p.scheme not in ("http", "https"):
22
+ return ""
23
+ if not p.netloc:
24
+ return ""
25
+ return p.geturl()
26
+
27
+
28
+ @app.get("/", response_class=HTMLResponse)
29
+ async def home(request: Request):
30
+ return templates.TemplateResponse("index.html", {"request": request})
31
+
32
+
33
+ @app.post("/go", response_class=HTMLResponse)
34
+ async def go(request: Request, q: str = Form(...)):
35
+ """
36
+ Handle form submission: treat q as either URL or search query.
37
+ """
38
+ cleaned = sanitize_url(q)
39
+ if cleaned:
40
+ # Looks like a URL
41
+ return RedirectResponse(url=f"/proxy?url={quote_plus(cleaned)}", status_code=302)
42
+ else:
43
+ # Treat as search query
44
+ return RedirectResponse(url=f"/search?q={quote_plus(q)}", status_code=302)
45
+
46
+
47
+ @app.get("/search", response_class=HTMLResponse)
48
+ async def search(request: Request, q: str = Query(...)):
49
+ """
50
+ Very simple meta-search using DuckDuckGo HTML.
51
+ Note: This is a hacky example, not an official API.
52
+ """
53
+ if not q.strip():
54
+ return RedirectResponse(url="/", status_code=302)
55
+
56
+ # DuckDuckGo HTML interface
57
+ target = f"https://duckduckgo.com/html/?q={quote_plus(q)}"
58
+
59
+ async with httpx.AsyncClient(follow_redirects=True, timeout=30) as client:
60
+ r = await client.get(target, headers={"User-Agent": "Mozilla/5.0"})
61
+
62
+ # Rewrite links in the HTML so clicks go via /proxy
63
+ html = r.text
64
+ # Very naive replacement; proper rewrite would need HTML parsing
65
+ html = html.replace('href="/', 'href="https://duckduckgo.com/')
66
+ html = html.replace('href="http', 'href="/proxy?url=http')
67
+
68
+ wrapper_html = f"""
69
+ <html>
70
+ <head>
71
+ <title>Proxy Search - {q}</title>
72
+ <style>
73
+ body {{ font-family: sans-serif; margin: 1rem; }}
74
+ form {{ margin-bottom: 1rem; }}
75
+ input[type=text] {{ width: 70%; padding: 0.5rem; }}
76
+ button {{ padding: 0.5rem 1rem; }}
77
+ iframe {{ width: 100%; height: 80vh; border: 1px solid #ccc; }}
78
+ </style>
79
+ </head>
80
+ <body>
81
+ <form action="/go" method="post">
82
+ <input type="text" name="q" value="{q}" placeholder="Search or enter URL" />
83
+ <button type="submit">Go</button>
84
+ </form>
85
+ <hr/>
86
+ {html}
87
+ </body>
88
+ </html>
89
+ """
90
+ return HTMLResponse(content=wrapper_html)
91
+
92
+
93
+ @app.get("/proxy")
94
+ async def proxy(url: str = Query(...)):
95
+ """
96
+ Simple GET proxy to fetch pages.
97
+ """
98
+ target = sanitize_url(url)
99
+ if not target:
100
+ return RedirectResponse(url="/", status_code=302)
101
+
102
+ async with httpx.AsyncClient(follow_redirects=True, timeout=30) as client:
103
+ try:
104
+ r = await client.get(target, headers={"User-Agent": "Mozilla/5.0"})
105
+ except httpx.RequestError as e:
106
+ return HTMLResponse(
107
+ f"<h1>Upstream error</h1><pre>{e}</pre>", status_code=502
108
+ )
109
+
110
+ content_type = r.headers.get("content-type", "text/html")
111
+ # Very simple: just forward content. No rewriting of embedded links/CSS/JS.
112
+ return Response(content=r.content, status_code=r.status_code, media_type=content_type)
113
+
114
+
115
+ if __name__ == "__main__":
116
+ import os
117
+ import uvicorn
118
+
119
+ port = int(os.getenv("PORT", "7860"))
120
+ uvicorn.run("main:app", host="0.0.0.0", port=port)