Skip to content

Commit 71fe9fe

Browse files
committed
chg: [API] OpenAPI added + fix for multiple slashes in the url
1 parent 433eae2 commit 71fe9fe

File tree

4 files changed

+65
-4
lines changed

4 files changed

+65
-4
lines changed

app.py

+58-3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
from starlette.staticfiles import StaticFiles
88
from starlette.routing import Route, Mount
99
from starlette.templating import Jinja2Templates
10+
from starlette.responses import JSONResponse, RedirectResponse
11+
from starlette.datastructures import URL
12+
from starlette.types import ASGIApp, Receive, Scope, Send
13+
repeated_quotes = re.compile(r'//+') # handling multiple // in url
1014
import sys
1115
import uvicorn
1216
import valkey
@@ -22,10 +26,33 @@
2226
valkey_host = config['DEFAULT']['valkey_host']
2327
valkey_port = config['DEFAULT']['valkey_port']
2428
cache = valkey.Valkey(host=valkey_host, port=valkey_port, db=0)
29+
# API definition
30+
from apiman.starlette import Apiman
31+
apiman = Apiman(template="openapi.yml")
2532

2633
if not cache.ping():
2734
sys.exit("Valkey server not reachable")
2835

36+
37+
class HttpUrlRedirectMiddleware:
38+
"""
39+
This http middleware redirects urls with repeated slashes to the cleaned up
40+
versions of the urls - from GitHub issue from Starlette project
41+
"""
42+
43+
def __init__(self, app: ASGIApp) -> None:
44+
self.app = app
45+
46+
async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
47+
48+
if scope["type"] == "http" and repeated_quotes.search(URL(scope=scope).path):
49+
url = URL(scope=scope)
50+
url = url.replace(path=repeated_quotes.sub('/', url.path))
51+
response = RedirectResponse(url, status_code=307)
52+
await response(scope, receive, send)
53+
else:
54+
await self.app(scope, receive, send)
55+
2956
def check_onion(onion=None):
3057
# We only support onion_v3 and automatically append dot onion if missing
3158
if onion is None or onion == '':
@@ -46,9 +73,8 @@ def query_onion(onion=None):
4673
r = requests.get(f'{ail_url}/api/v1/lookup/onion/{onion}', headers=headers, verify=False)
4774
if r.status_code != 200:
4875
return False
49-
print(r.status_code)
50-
print(r.json())
5176
cache.set(keycache, r.text, ex=3600)
77+
return json.loads(cache.get(keycache))
5278

5379
async def homepage(request):
5480
template = "index.html"
@@ -65,6 +91,32 @@ async def homepage(request):
6591

6692
return templates.TemplateResponse(template, context)
6793

94+
@apiman.from_yaml(
95+
"""
96+
summary: lookup api
97+
tags:
98+
- lookup
99+
parameters:
100+
- name: onion
101+
in: path
102+
required: True
103+
responses:
104+
"200":
105+
description: OK
106+
""")
107+
async def lookup(request):
108+
onion = check_onion(onion=request.path_params['onion'].lower())
109+
keycache = f'onion-lookup:{onion}'
110+
if onion:
111+
onion_response = check_onion(onion=onion)
112+
if onion_response is not False:
113+
onion_meta = query_onion(onion=onion)
114+
if onion_meta is not False:
115+
return JSONResponse(onion_meta)
116+
else:
117+
return JSONResponse({"error": "Incorrect onion format"})
118+
119+
return JSONResponse({})
68120

69121
async def error(request):
70122
"""
@@ -92,8 +144,10 @@ async def server_error(request: Request, exc: HTTPException):
92144

93145
routes = [
94146
Route('/', homepage),
147+
Route('/api/lookup/{onion}', lookup, methods=['GET']),
95148
Route('/error', error),
96149
Mount('/static', app=StaticFiles(directory='statics'), name='static')
150+
97151
]
98152

99153
exception_handlers = {
@@ -102,7 +156,8 @@ async def server_error(request: Request, exc: HTTPException):
102156
}
103157

104158
app = Starlette(debug=True, routes=routes, exception_handlers=exception_handlers)
105-
159+
app.add_middleware(HttpUrlRedirectMiddleware)
160+
apiman.init_app(app)
106161

107162
if __name__ == "__main__":
108163
uvicorn.run(app, host='0.0.0.0', port=8000)

openapi.yml

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
openapi: "3.0.0"
2+
info:
3+
title: 'onion-lookup'
4+
version: '0.1'
5+
description: 'API manual for onion-lookup'

requirements.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
aiofiles
2+
apiman
23
jinja2
34
requests
45
starlette

templates/index.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ <h6 class="card-subtitle mb-2 text-light">
5252
<div class="col-md-4">
5353
<h2>API</h2>
5454
<p>An OpenAPI is also available to query onion-lookup.</p>
55-
<p><a class="btn btn-secondary" href="#" role="button">View details &raquo;</a></p>
55+
<p><a class="btn btn-secondary" href="/apiman/redoc/" role="button">View details &raquo;</a><a class="btn btn-secondary" href="/apiman/swagger/" role="button">Swagger&raquo;</a></p>
5656
</div>
5757
</div>
5858

0 commit comments

Comments
 (0)