Skip to content

Commit 19dabaa

Browse files
committed
Use flask.Blueprint for endpoint grouping
This is a cleaner way to split them up, but more importantly also allows the same local function name to be used across routes submodules (e.g. "routes.legacy.get_room", "routes.rooms.get_room" clash without Blueprints).
1 parent 5e91ee2 commit 19dabaa

File tree

5 files changed

+49
-33
lines changed

5 files changed

+49
-33
lines changed

sogs/routes/__init__.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33
from .. import config, crypto, http, utils
44
from ..model.room import get_readable_rooms
55

6-
from . import auth, converters, general, legacy, onion_request # noqa: F401
6+
from . import auth, converters # noqa: F401
7+
8+
from .legacy import legacy as legacy_endpoints
9+
from .general import general as general_endpoints
10+
from .onion_request import onion_request as onion_request_endpoints
711

812
from io import BytesIO
913

@@ -12,6 +16,11 @@
1216
from PIL.Image import NEAREST
1317

1418

19+
app.register_blueprint(legacy_endpoints)
20+
app.register_blueprint(general_endpoints)
21+
app.register_blueprint(onion_request_endpoints)
22+
23+
1524
@app.get("/")
1625
def serve_index():
1726
rooms = get_readable_rooms()

sogs/routes/general.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@
44
from .. import utils
55
from .subrequest import make_subrequest
66

7-
from flask import request, abort, jsonify
7+
from flask import request, abort, jsonify, Blueprint
88

99
# General purpose routes for things like capability retrieval and batching
1010

11+
general = Blueprint('general', __name__)
1112

12-
@app.get("/capabilities")
13+
14+
@general.get("/capabilities")
1315
def get_caps():
1416
"""
1517
Return the list of server features/capabilities. Optionally takes a required= parameter
@@ -114,7 +116,7 @@ def parse_batch_req(r):
114116
return method, path, headers, json, body
115117

116118

117-
@app.post("/batch")
119+
@general.post("/batch")
118120
def batch(_sequential=False):
119121
"""
120122
Submits multiple requests wrapped up in a single request, runs them all, then returns the result
@@ -162,7 +164,7 @@ def batch(_sequential=False):
162164
return utils.jsonify_with_base64(response)
163165

164166

165-
@app.post("/sequence")
167+
@general.post("/sequence")
166168
def sequence():
167169
"""
168170
This is like batch, except that it guarantees to submit requests sequentially in the order

sogs/routes/legacy.py

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from flask import abort, request, jsonify, g
1+
from flask import abort, request, jsonify, g, Blueprint
22
from werkzeug.exceptions import HTTPException
33
from ..web import app
44
from .. import crypto, config, db, http, utils
@@ -12,6 +12,8 @@
1212
# an endpoint (via onion request) that doesn't start with a `/` -- we prepend `/legacy/` and submit
1313
# it as an internal request to land here.
1414

15+
legacy = Blueprint('legacy', __name__, url_prefix='/legacy')
16+
1517

1618
def get_pubkey_from_token(token):
1719
if not token:
@@ -90,7 +92,7 @@ def legacy_check_user_room(
9092
return (user, room)
9193

9294

93-
@app.get("/legacy/rooms")
95+
@legacy.get("/rooms")
9496
def get_rooms():
9597
"""serve public room list for user"""
9698

@@ -103,7 +105,7 @@ def get_rooms():
103105
)
104106

105107

106-
@app.get("/legacy/rooms/<Room:room>")
108+
@legacy.get("/rooms/<Room:room>")
107109
def get_room_info(room):
108110
"""serve room metadata"""
109111
# This really should be authenticated but legacy Session just doesn't pass along auth info.
@@ -112,7 +114,7 @@ def get_room_info(room):
112114
return jsonify({'room': room_info, 'status_code': http.OK})
113115

114116

115-
@app.get("/legacy/rooms/<Room:room>/image")
117+
@legacy.get("/rooms/<Room:room>/image")
116118
def legacy_serve_room_image(room):
117119
"""serve room icon"""
118120
# This really should be authenticated but legacy Session just doesn't pass along auth info.
@@ -124,20 +126,20 @@ def legacy_serve_room_image(room):
124126
return jsonify({"status_code": http.OK, "result": room.image.read_base64()})
125127

126128

127-
@app.get("/legacy/member_count")
129+
@legacy.get("/member_count")
128130
def legacy_member_count():
129131
user, room = legacy_check_user_room(read=True)
130132

131133
return jsonify({"status_code": http.OK, "member_count": room.active_users()})
132134

133135

134-
@app.post("/legacy/claim_auth_token")
136+
@legacy.post("/claim_auth_token")
135137
def legacy_claim_auth():
136138
"""this does nothing but needs to exist for backwards compat"""
137139
return jsonify({'status_code': http.OK})
138140

139141

140-
@app.get("/legacy/auth_token_challenge")
142+
@legacy.get("/auth_token_challenge")
141143
def legacy_auth_token_challenge():
142144
"""
143145
legacy endpoint to give back an encrypted auth token bundle for the client to use to
@@ -170,7 +172,7 @@ def legacy_transform_message(m):
170172
}
171173

172174

173-
@app.post("/legacy/messages")
175+
@legacy.post("/messages")
174176
def handle_post_legacy_message():
175177

176178
user, room = legacy_check_user_room(write=True)
@@ -187,7 +189,7 @@ def handle_post_legacy_message():
187189
)
188190

189191

190-
@app.get("/legacy/messages")
192+
@legacy.get("/messages")
191193
def handle_legacy_get_messages():
192194
from_id = request.args.get('from_server_id')
193195
limit = utils.get_int_param('limit', 256, min=1, max=256, truncate=True)
@@ -205,7 +207,7 @@ def handle_legacy_get_messages():
205207
)
206208

207209

208-
@app.post("/legacy/compact_poll")
210+
@legacy.post("/compact_poll")
209211
def handle_comapct_poll():
210212
req_list = request.json
211213
result = list()
@@ -272,22 +274,22 @@ def process_legacy_file_upload_for_room(
272274
return room.upload_file(file_content, user, filename=filename, lifetime=lifetime)
273275

274276

275-
@app.post("/legacy/files")
277+
@legacy.post("/files")
276278
def handle_legacy_store_file():
277279
user, room = legacy_check_user_room(write=True, upload=True)
278280
file_id = process_legacy_file_upload_for_room(user, room)
279281
return jsonify({'status_code': http.OK, 'result': file_id})
280282

281283

282-
@app.post("/legacy/rooms/<Room:room>/image")
284+
@legacy.post("/rooms/<Room:room>/image")
283285
def handle_legacy_upload_room_image(room):
284286
user, room = legacy_check_user_room(write=True, upload=True, moderator=True)
285287
file_id = process_legacy_file_upload_for_room(user, room, lifetime=None)
286288
room.image = file_id
287289
return jsonify({'status_code': http.OK, 'result': file_id})
288290

289291

290-
@app.get("/legacy/files/<int:file_id>")
292+
@legacy.get("/files/<int:file_id>")
291293
def handle_legacy_get_file(file_id):
292294
user, room = legacy_check_user_room(read=True)
293295

@@ -300,7 +302,7 @@ def handle_legacy_get_file(file_id):
300302
return jsonify_with_base64({'status_code': http.OK, 'result': file_content})
301303

302304

303-
@app.post("/legacy/delete_messages")
305+
@legacy.post("/delete_messages")
304306
def handle_legacy_delete_messages(ids=None):
305307
user, room = legacy_check_user_room(read=True)
306308

@@ -315,12 +317,12 @@ def handle_legacy_delete_messages(ids=None):
315317
return jsonify({'status_code': http.OK})
316318

317319

318-
@app.delete("/legacy/messages/<int:msgid>")
320+
@legacy.delete("/messages/<int:msgid>")
319321
def handle_legacy_single_delete(msgid):
320322
return handle_legacy_delete_messages(ids=[msgid])
321323

322324

323-
@app.post("/legacy/block_list")
325+
@legacy.post("/block_list")
324326
def handle_legacy_ban():
325327
user, room = legacy_check_user_room(moderator=True)
326328
ban = User(session_id=request.json['public_key'], autovivify=True)
@@ -330,7 +332,7 @@ def handle_legacy_ban():
330332
return jsonify({"status_code": http.OK})
331333

332334

333-
@app.post("/legacy/ban_and_delete_all")
335+
@legacy.post("/ban_and_delete_all")
334336
def handle_legacy_banhammer():
335337
mod, room = legacy_check_user_room(moderator=True)
336338
ban = User(session_id=request.json['public_key'], autovivify=True)
@@ -342,7 +344,7 @@ def handle_legacy_banhammer():
342344
return jsonify({"status_code": http.OK})
343345

344346

345-
@app.delete("/legacy/block_list/<SessionID:session_id>")
347+
@legacy.delete("/block_list/<SessionID:session_id>")
346348
def handle_legacy_unban(session_id):
347349
user, room = legacy_check_user_room(moderator=True)
348350
to_unban = User(session_id=session_id, autovivify=False)
@@ -352,7 +354,7 @@ def handle_legacy_unban(session_id):
352354
abort(http.NOT_FOUND)
353355

354356

355-
@app.get("/legacy/block_list")
357+
@legacy.get("/block_list")
356358
def handle_legacy_banlist():
357359
# Bypass permission checks here because we want to continue even if we are banned:
358360
user, room = legacy_check_user_room(no_perms=True)
@@ -369,7 +371,7 @@ def handle_legacy_banlist():
369371
return jsonify({"status_code": http.OK, "banned_members": bans})
370372

371373

372-
@app.get("/legacy/moderators")
374+
@legacy.get("/moderators")
373375
def handle_legacy_get_mods():
374376
user, room = legacy_check_user_room(read=True)
375377

@@ -379,7 +381,7 @@ def handle_legacy_get_mods():
379381

380382
# Posting here adds an admin and requires admin access. Legacy Session doesn't understand the
381383
# moderator/admin distinction so we don't support moderator adjustment at all here.
382-
@app.post("/legacy/moderators")
384+
@legacy.post("/moderators")
383385
def handle_legacy_add_admin():
384386
user, room = legacy_check_user_room(admin=True)
385387

@@ -396,7 +398,7 @@ def handle_legacy_add_admin():
396398
# DELETE here removes an admin or moderator and requires admin access. (Legacy Session doesn't
397399
# understand the moderator/admin distinction so we don't distinguish between them and just remove
398400
# both powers, if present).
399-
@app.delete("/legacy/moderators/<SessionID:session_id>")
401+
@legacy.delete("/moderators/<SessionID:session_id>")
400402
def handle_legacy_remove_admin(session_id):
401403
user, room = legacy_check_user_room(admin=True)
402404

sogs/routes/onion_request.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1-
from flask import request, abort
1+
from flask import request, abort, Blueprint
22
import json
33

44
from ..web import app
55
from .. import crypto, http, utils
66

77
from .subrequest import make_subrequest
88

9+
onion_request = Blueprint('onion_request', __name__)
10+
911

1012
def handle_onionreq_plaintext(body):
1113
"""
@@ -82,8 +84,8 @@ def handle_onionreq_plaintext(body):
8284
return json.dumps({'status_code': http.BAD_REQUEST}).encode()
8385

8486

85-
@app.post("/oxen/v3/lsrpc")
86-
@app.post("/loki/v3/lsrpc")
87+
@onion_request.post("/oxen/v3/lsrpc")
88+
@onion_request.post("/loki/v3/lsrpc")
8789
def handle_onion_request():
8890
"""
8991
Parse an onion request, handle it as a subrequest, then encrypt the subrequest result and send

sogs/web.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,15 @@
1010
# below, because they depend on this existing.
1111
if not hasattr(flask.Flask, 'post'):
1212

13-
def _add_flask_method(name):
13+
def _add_route_shortcut(on, name):
1414
def meth(self, rule: str, **options):
1515
return self.route(rule, methods=[name.upper()], **options)
1616

17-
setattr(flask.Flask, name, meth)
17+
setattr(on, name, meth)
1818

1919
for method in ('get', 'post', 'put', 'delete', 'patch'):
20-
_add_flask_method(method)
20+
_add_route_shortcut(flask.Flask, method)
21+
_add_route_shortcut(flask.Blueprint, method)
2122

2223

2324
def get_db_conn():

0 commit comments

Comments
 (0)