recon: add /api/wiki-rewrite endpoint (extraction #5 prep, additive) (#9)

Per-tag HTTP wrapper over wiki_rewrite.rewrite_wiki_link so the (future)
navi-places service can rewrite OSM wiki tags to local Kiwix URLs over HTTP
instead of importing recon's wiki_rewrite module (which talks to Kiwix on
localhost:8430 and the wiki_cache table in /opt/recon/data/place_cache.db).
Companion to PR #8 (/api/wiki-enrich) — Matt picked option B (HTTP-couple the
Kiwix offline-wiki rewriting too, since it matters in prod).

  GET /api/wiki-rewrite?tag=<wikipedia|wikidata|wikivoyage|appropedia>&value=<raw>
  -> 200 {url, status}  where status is "local" | "public" | "original"
  -> 400 on missing value or unknown tag
  -> no 404 (unclassifiable value echoes back with status "original",
     mirroring rewrite_wiki_link)
  Public (no auth), like /api/place/* and /api/wiki-enrich.

Changes (additive only):
  - lib/wiki_rewrite_api.py: new wiki_rewrite_bp blueprint. Thin route directly
    over the existing rewrite_wiki_link(tag, value) — no extraction needed
    (it's already a clean standalone function, unlike wiki-enrich's lookup).
  - lib/api.py: register the blueprint (one block).
  - lib/wiki_rewrite_api_test.py: 5 tests (local Kiwix hit, public fallback,
    unclassifiable -> original, missing value -> 400, unknown tag -> 400),
    stubbing check_kiwix_has_article (no Kiwix/DB), plain-assert + __main__
    runner. Verified green against recon's venv (flask 3.1.2).

Does NOT touch place_detail's in-process _enrich_wiki_links — that gets removed
in a later PR once navi-places is live (same as PR #8). wiki_cache stays in
recon's own place_cache.db post-cutover (harmless positive-cache duplication).

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
malice 2026-05-22 14:08:18 -06:00 committed by GitHub
commit 14ad2cd34a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 111 additions and 0 deletions

34
lib/wiki_rewrite_api.py Normal file
View file

@ -0,0 +1,34 @@
"""Wiki-rewrite API — read-only HTTP wrapper over wiki_rewrite.rewrite_wiki_link.
Extraction #5 prep: lets the (future) navi-places service rewrite OSM wiki tags
to local Kiwix URLs over HTTP instead of importing recon's wiki_rewrite module
(which talks to Kiwix and the wiki_cache table in /opt/recon/data/place_cache.db).
Additive only does not change place_detail's in-process `_enrich_wiki_links`.
GET /api/wiki-rewrite?tag=<wikipedia|wikidata|wikivoyage|appropedia>&value=<raw>
Public (no auth), matching /api/place/* and /api/wiki-enrich. 400 on missing
value or unknown tag. No 404 an unclassifiable value returns the original
value with status "original" (mirrors rewrite_wiki_link).
"""
from flask import Blueprint, request, jsonify
from .wiki_rewrite import rewrite_wiki_link
wiki_rewrite_bp = Blueprint('wiki_rewrite', __name__)
_KNOWN_TAGS = {'wikipedia', 'wikidata', 'wikivoyage', 'appropedia'}
@wiki_rewrite_bp.route('/api/wiki-rewrite')
def api_wiki_rewrite():
tag = (request.args.get('tag') or '').strip().lower()
value = (request.args.get('value') or '').strip()
if not value:
return jsonify({'error': 'value is required'}), 400
if tag not in _KNOWN_TAGS:
return jsonify({'error': f"tag must be one of {sorted(_KNOWN_TAGS)}"}), 400
url, status = rewrite_wiki_link(tag, value)
return jsonify({'url': url, 'status': status})