Cleanup JSON outputs

This commit is contained in:
Thomas Sileo 2019-08-24 10:58:35 +02:00
parent dad3dae988
commit 681cfe5e54
5 changed files with 58 additions and 75 deletions

8
app.py
View file

@ -14,7 +14,6 @@ from flask import Flask
from flask import Response from flask import Response
from flask import abort from flask import abort
from flask import g from flask import g
from flask import jsonify as flask_jsonify
from flask import redirect from flask import redirect
from flask import render_template from flask import render_template
from flask import request from flask import request
@ -67,6 +66,7 @@ from core.shared import activitypubify
from core.shared import csrf from core.shared import csrf
from core.shared import htmlify from core.shared import htmlify
from core.shared import is_api_request from core.shared import is_api_request
from core.shared import jsonify
from core.shared import login_required from core.shared import login_required
from core.shared import noindex from core.shared import noindex
from core.shared import paginated_query from core.shared import paginated_query
@ -173,7 +173,7 @@ def handle_value_error(error):
logger.error( logger.error(
f"caught value error for {g.request_id}: {error!r}, {traceback.format_tb(error.__traceback__)}" f"caught value error for {g.request_id}: {error!r}, {traceback.format_tb(error.__traceback__)}"
) )
response = flask_jsonify(message=error.args[0], request_id=g.request_id) response = jsonify({"message": error.args[0], "request_id": g.request_id})
response.status_code = 400 response.status_code = 400
return response return response
@ -183,7 +183,7 @@ def handle_activitypub_error(error):
logger.error( logger.error(
f"caught activitypub error for {g.request_id}: {error!r}, {traceback.format_tb(error.__traceback__)}" f"caught activitypub error for {g.request_id}: {error!r}, {traceback.format_tb(error.__traceback__)}"
) )
response = flask_jsonify({**error.to_dict(), "request_id": g.request_id}) response = jsonify({**error.to_dict(), "request_id": g.request_id})
response.status_code = error.status_code response.status_code = error.status_code
return response return response
@ -193,7 +193,7 @@ def handle_task_error(error):
logger.error( logger.error(
f"caught activitypub error for {g.request_id}: {error!r}, {traceback.format_tb(error.__traceback__)}" f"caught activitypub error for {g.request_id}: {error!r}, {traceback.format_tb(error.__traceback__)}"
) )
response = flask_jsonify({"traceback": error.message, "request_id": g.request_id}) response = jsonify({"traceback": error.message, "request_id": g.request_id})
response.status_code = 500 response.status_code = 500
return response return response

View file

@ -1,4 +1,3 @@
import json
import mimetypes import mimetypes
from datetime import datetime from datetime import datetime
from datetime import timedelta from datetime import timedelta
@ -10,7 +9,6 @@ from typing import List
import flask import flask
from bson.objectid import ObjectId from bson.objectid import ObjectId
from flask import Response
from flask import abort from flask import abort
from flask import current_app as app from flask import current_app as app
from flask import redirect from flask import redirect
@ -41,6 +39,7 @@ from core.meta import _meta
from core.shared import MY_PERSON from core.shared import MY_PERSON
from core.shared import _Response from core.shared import _Response
from core.shared import csrf from core.shared import csrf
from core.shared import jsonify
from core.shared import login_required from core.shared import login_required
from core.tasks import Tasks from core.tasks import Tasks
from utils import emojis from utils import emojis
@ -124,7 +123,7 @@ def _user_api_response(**kwargs) -> _Response:
if _redirect: if _redirect:
return redirect(_redirect) return redirect(_redirect)
resp = flask.jsonify(**kwargs) resp = jsonify(kwargs)
resp.status_code = 201 resp.status_code = 201
return resp return resp
@ -132,7 +131,7 @@ def _user_api_response(**kwargs) -> _Response:
@blueprint.route("/api/key") @blueprint.route("/api/key")
@login_required @login_required
def api_user_key() -> _Response: def api_user_key() -> _Response:
return flask.jsonify(api_key=ADMIN_API_KEY) return jsonify({"api_key": ADMIN_API_KEY})
@blueprint.route("/note/delete", methods=["POST"]) @blueprint.route("/note/delete", methods=["POST"])
@ -575,25 +574,24 @@ def api_follow() -> _Response:
def api_debug() -> _Response: def api_debug() -> _Response:
"""Endpoint used/needed for testing, only works in DEBUG_MODE.""" """Endpoint used/needed for testing, only works in DEBUG_MODE."""
if not DEBUG_MODE: if not DEBUG_MODE:
return flask.jsonify(message="DEBUG_MODE is off") return jsonify({"message": "DEBUG_MODE is off"})
if request.method == "DELETE": if request.method == "DELETE":
_drop_db() _drop_db()
return flask.jsonify(message="DB dropped") return jsonify(dict(message="DB dropped"))
return flask.jsonify( return jsonify(
dict(
inbox=DB.activities.count({"box": Box.INBOX.value}), inbox=DB.activities.count({"box": Box.INBOX.value}),
outbox=DB.activities.count({"box": Box.OUTBOX.value}), outbox=DB.activities.count({"box": Box.OUTBOX.value}),
outbox_data=without_id(DB.activities.find({"box": Box.OUTBOX.value})), outbox_data=without_id(DB.activities.find({"box": Box.OUTBOX.value})),
) )
)
@blueprint.route("/stream") @blueprint.route("/stream")
@api_required @api_required
def api_stream() -> _Response: def api_stream() -> _Response:
return Response( return jsonify(
response=json.dumps(
feed.build_inbox_json_feed("/api/stream", request.args.get("cursor")) feed.build_inbox_json_feed("/api/stream", request.args.get("cursor"))
),
headers={"Content-Type": "application/json"},
) )

View file

@ -1,5 +1,4 @@
import binascii import binascii
import json
import os import os
from datetime import datetime from datetime import datetime
from datetime import timedelta from datetime import timedelta
@ -20,6 +19,7 @@ from config import DB
from config import JWT from config import JWT
from core.shared import _get_ip from core.shared import _get_ip
from core.shared import htmlify from core.shared import htmlify
from core.shared import jsonify
from core.shared import login_required from core.shared import login_required
blueprint = flask.Blueprint("indieauth", __name__) blueprint = flask.Blueprint("indieauth", __name__)
@ -27,11 +27,7 @@ blueprint = flask.Blueprint("indieauth", __name__)
def build_auth_resp(payload): def build_auth_resp(payload):
if request.headers.get("Accept") == "application/json": if request.headers.get("Accept") == "application/json":
return Response( return jsonify(payload)
status=200,
headers={"Content-Type": "application/json"},
response=json.dumps(payload),
)
return Response( return Response(
status=200, status=200,
headers={"Content-Type": "application/x-www-form-urlencoded"}, headers={"Content-Type": "application/x-www-form-urlencoded"},

View file

@ -1,9 +1,7 @@
import json
import mimetypes import mimetypes
from typing import Any from typing import Any
import flask import flask
from flask import Response
from flask import abort from flask import abort
from flask import request from flask import request
from little_boxes import activitypub as ap from little_boxes import activitypub as ap
@ -11,6 +9,7 @@ from little_boxes import activitypub as ap
import config import config
from config import DB from config import DB
from core.meta import Box from core.meta import Box
from core.shared import jsonify
blueprint = flask.Blueprint("well_known", __name__) blueprint = flask.Blueprint("well_known", __name__)
@ -45,22 +44,21 @@ def wellknown_webfinger() -> Any:
], ],
} }
return Response( return jsonify(out, "application/jrd+json; charset=utf-8")
response=json.dumps(out),
headers={"Content-Type": "application/jrd+json; charset=utf-8"},
)
@blueprint.route("/.well-known/nodeinfo") @blueprint.route("/.well-known/nodeinfo")
def wellknown_nodeinfo() -> Any: def wellknown_nodeinfo() -> Any:
"""Exposes the NodeInfo endpoint (http://nodeinfo.diaspora.software/).""" """Exposes the NodeInfo endpoint (http://nodeinfo.diaspora.software/)."""
return flask.jsonify( return jsonify(
links=[ {
"links": [
{ {
"rel": "http://nodeinfo.diaspora.software/ns/schema/2.1", "rel": "http://nodeinfo.diaspora.software/ns/schema/2.1",
"href": f"{config.ID}/nodeinfo", "href": f"{config.ID}/nodeinfo",
} }
] ]
}
) )
@ -73,8 +71,7 @@ def nodeinfo() -> Any:
"type": {"$in": [ap.ActivityType.CREATE.value, ap.ActivityType.ANNOUNCE.value]}, "type": {"$in": [ap.ActivityType.CREATE.value, ap.ActivityType.ANNOUNCE.value]},
} }
response = json.dumps( out = {
{
"version": "2.1", "version": "2.1",
"software": { "software": {
"name": "microblogpub", "name": "microblogpub",
@ -91,11 +88,8 @@ def nodeinfo() -> Any:
"versionDate": config.VERSION_DATE, "versionDate": config.VERSION_DATE,
}, },
} }
)
return Response( return jsonify(
headers={ out,
"Content-Type": "application/json; profile=http://nodeinfo.diaspora.software/ns/schema/2.1#" "application/json; profile=http://nodeinfo.diaspora.software/ns/schema/2.1#",
},
response=response,
) )

View file

@ -48,7 +48,7 @@ MY_PERSON = ap.Person(**ME)
@lru_cache(512) @lru_cache(512)
def build_resp(resp): def build_resp(resp):
"""Encode the response to gzip if supported by the client.""" """Encode the response to gzip if supported by the client."""
headers = {} headers = {"Cache-Control": "max-age=0, private, must-revalidate"}
accept_encoding = request.headers.get("Accept-Encoding", "") accept_encoding = request.headers.get("Accept-Encoding", "")
if "gzip" in accept_encoding.lower(): if "gzip" in accept_encoding.lower():
return ( return (
@ -59,15 +59,15 @@ def build_resp(resp):
return resp, headers return resp, headers
def jsonify(data, content_type="application/json"):
resp, headers = build_resp(json.dumps(data))
return Response(headers={**headers, "Content-Type": content_type}, response=resp)
def htmlify(data): def htmlify(data):
resp, headers = build_resp(data) resp, headers = build_resp(data)
return Response( return Response(
response=resp, response=resp, headers={**headers, "Content-Type": "text/html; charset=utf-8"}
headers={
**headers,
"Content-Type": "text/html; charset=utf-8",
"Cache-Control": "max-age=0, private, must-revalidate",
},
) )
@ -76,12 +76,7 @@ def activitypubify(**data):
data["@context"] = config.DEFAULT_CTX data["@context"] = config.DEFAULT_CTX
resp, headers = build_resp(json.dumps(data)) resp, headers = build_resp(json.dumps(data))
return Response( return Response(
response=resp, response=resp, headers={**headers, "Content-Type": "application/activity+json"}
headers={
**headers,
"Cache-Control": "max-age=0, private, must-revalidate",
"Content-Type": "application/activity+json",
},
) )