menorki commited on
Commit
a3d4368
·
1 Parent(s): 8098f33
Files changed (3) hide show
  1. Dockerfile +13 -0
  2. app.py +75 -0
  3. requirements.txt +4 -0
Dockerfile ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.9
2
+
3
+ RUN useradd -m -u 1000 user
4
+ USER user
5
+ ENV PATH="/home/user/.local/bin:$PATH"
6
+
7
+ WORKDIR /app
8
+
9
+ COPY --chown=user ./requirements.txt requirements.txt
10
+ RUN pip install --no-cache-dir --upgrade -r requirements.txt
11
+
12
+ COPY --chown=user . /app
13
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
app.py ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from fastapi import FastAPI, Request, HTTPException, Depends, Query
3
+ from fastapi.responses import HTMLResponse, PlainTextResponse
4
+ import httpx
5
+ import uvicorn
6
+
7
+ # --- Security Dependency ---
8
+
9
+ # 1. Retrieve the server-side access key from the environment variable 'AK'
10
+ ACCESS_KEY = os.environ.get("AK")
11
+
12
+ async def verify_access_key(ak: str = Query(..., alias="AK")):
13
+ """
14
+ Dependency to secure endpoints by verifying the 'AK' query parameter
15
+ against the secret key stored in the environment.
16
+ """
17
+ if not ACCESS_KEY:
18
+ # Server-side configuration error if the secret is not set
19
+ raise HTTPException(
20
+ status_code=500,
21
+ detail="Access key is not configured on the server."
22
+ )
23
+ if ak != ACCESS_KEY:
24
+ # Client-side error for an invalid access key
25
+ raise HTTPException(
26
+ status_code=401,
27
+ detail="Unauthorized: Invalid access key provided."
28
+ )
29
+
30
+ # --- FastAPI Application ---
31
+
32
+ app = FastAPI(
33
+ title="URL Fetcher API",
34
+ description="A simple API to fetch URL content, with a protected endpoint."
35
+ )
36
+
37
+
38
+ @app.get("/ping", response_class=PlainTextResponse)
39
+ async def ping():
40
+ """
41
+ An unprotected endpoint to check if the service is running.
42
+ Returns a simple 'pong' response.
43
+ """
44
+ return "pong"
45
+
46
+
47
+ @app.get("/fetch_url", response_class=HTMLResponse, dependencies=[Depends(verify_access_key)])
48
+ async def fetch_url_content(request: Request):
49
+ """
50
+ Fetches the HTML content of a URL from the 'url' query parameter.
51
+ This endpoint is protected and requires a valid 'AK' (access key).
52
+ """
53
+ target_url = request.query_params.get('url')
54
+
55
+ if not target_url:
56
+ raise HTTPException(
57
+ status_code=400,
58
+ detail="The 'url' query parameter is required."
59
+ )
60
+
61
+ async with httpx.AsyncClient(follow_redirects=True) as client:
62
+ try:
63
+ headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'}
64
+ response = await client.get(target_url, headers=headers)
65
+ response.raise_for_status() # Raise an exception for bad status codes (4xx or 5xx)
66
+ return HTMLResponse(content=response.text, status_code=response.status_code)
67
+
68
+ except httpx.RequestError as exc:
69
+ raise HTTPException(status_code=400, detail=f"An error occurred while requesting {exc.request.url!r}: {exc}")
70
+ except httpx.HTTPStatusError as exc:
71
+ raise HTTPException(status_code=exc.response.status_code, detail=f"Error response {exc.response.status_code} while requesting {exc.request.url!r}.")
72
+
73
+
74
+ #if __name__ == "__main__":
75
+ # uvicorn.run(app, host="0.0.0.0", port=7860)
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ uvicorn
2
+ fastapi
3
+ fake-useragent
4
+ httpx