|
1 | 1 | __package__ = 'archivebox.api'
|
2 | 2 |
|
3 |
| -# import orjson |
4 |
| - |
5 |
| -from io import StringIO |
6 |
| -from traceback import format_exception |
7 |
| -from contextlib import redirect_stdout, redirect_stderr |
8 |
| - |
9 | 3 | from django.urls import path
|
10 |
| -from django.http import HttpRequest, HttpResponse |
11 | 4 | from django.views.generic.base import RedirectView
|
12 |
| -from django.core.exceptions import ObjectDoesNotExist, EmptyResultSet, PermissionDenied |
13 |
| - |
14 |
| -from ninja import NinjaAPI, Swagger |
15 |
| - |
16 |
| -# TODO: explore adding https://eadwincode.github.io/django-ninja-extra/ |
17 |
| - |
18 |
| -from api.auth import API_AUTH_METHODS |
19 |
| -from ..config import VERSION, COMMIT_HASH |
20 |
| - |
21 |
| -# from ninja.renderers import BaseRenderer |
22 |
| - |
23 |
| -# class ORJSONRenderer(BaseRenderer): |
24 |
| -# media_type = "application/json" |
25 |
| - |
26 |
| -# def render(self, request, data, *, response_status): |
27 |
| -# return { |
28 |
| -# "success": True, |
29 |
| -# "errors": [], |
30 |
| -# "result": data, |
31 |
| -# "stdout": ansi_to_html(stdout.getvalue().strip()), |
32 |
| -# "stderr": ansi_to_html(stderr.getvalue().strip()), |
33 |
| -# } |
34 |
| -# return orjson.dumps(data) |
35 |
| - |
36 |
| - |
37 |
| -class NinjaAPIWithIOCapture(NinjaAPI): |
38 |
| - def create_temporal_response(self, request: HttpRequest) -> HttpResponse: |
39 |
| - stdout, stderr = StringIO(), StringIO() |
40 |
| - |
41 |
| - with redirect_stderr(stderr): |
42 |
| - with redirect_stdout(stdout): |
43 |
| - request.stdout = stdout |
44 |
| - request.stderr = stderr |
45 |
| - |
46 |
| - response = super().create_temporal_response(request) |
47 |
| - |
48 |
| - print('RESPONDING NOW', response) |
49 |
| - |
50 |
| - return response |
51 |
| - |
52 |
| -html_description=f''' |
53 |
| -<h3>Welcome to your ArchiveBox server's REST API <code>[v1 ALPHA]</code> homepage!</h3> |
54 |
| -<br/> |
55 |
| -<i><b>WARNING: This API is still in an early development stage and may change!</b></i> |
56 |
| -<br/> |
57 |
| -<ul> |
58 |
| -<li>⬅️ Manage your server: <a href="/admin/api/"><b>Setup API Keys</b></a>, <a href="/admin/">Go to your Server Admin UI</a>, <a href="/">Go to your Snapshots list</a> |
59 |
| -<li>💬 Ask questions and get help here: <a href="https://zulip.archivebox.io">ArchiveBox Chat Forum</a></li> |
60 |
| -<li>🐞 Report API bugs here: <a href="https://github.com/ArchiveBox/ArchiveBox/issues">Github Issues</a></li> |
61 |
| -<li>📚 ArchiveBox Documentation: <a href="https://github.com/ArchiveBox/ArchiveBox/wiki">Github Wiki</a></li> |
62 |
| -<li>📜 See the API source code: <a href="https://github.com/ArchiveBox/ArchiveBox/blob/dev/archivebox/api"><code>archivebox/api/</code></a></li> |
63 |
| -</ul> |
64 |
| -<small>Served by ArchiveBox v{VERSION} (<a href="https://github.com/ArchiveBox/ArchiveBox/commit/{COMMIT_HASH}"><code>{COMMIT_HASH[:8]}</code></a>), API powered by <a href="https://django-ninja.dev/"><code>django-ninja</code></a>.</small> |
65 |
| -''' |
66 |
| - |
67 |
| -api = NinjaAPIWithIOCapture( |
68 |
| - title='ArchiveBox API', |
69 |
| - description=html_description, |
70 |
| - version='1.0.0', |
71 |
| - csrf=False, |
72 |
| - auth=API_AUTH_METHODS, |
73 |
| - urls_namespace="api", |
74 |
| - docs=Swagger(settings={"persistAuthorization": True}), |
75 |
| - # docs_decorator=login_required, |
76 |
| - # renderer=ORJSONRenderer(), |
77 |
| -) |
78 |
| -api.add_router('/auth/', 'api.routes_auth.router') |
79 |
| -api.add_router('/core/', 'api.routes_core.router') |
80 |
| -api.add_router('/cli/', 'api.routes_cli.router') |
81 |
| - |
82 |
| - |
83 |
| -@api.exception_handler(Exception) |
84 |
| -def generic_exception_handler(request, err): |
85 |
| - status = 503 |
86 |
| - if isinstance(err, (ObjectDoesNotExist, EmptyResultSet, PermissionDenied)): |
87 |
| - status = 404 |
88 |
| - |
89 |
| - print(''.join(format_exception(err))) |
90 |
| - |
91 |
| - return api.create_response( |
92 |
| - request, |
93 |
| - { |
94 |
| - "succeeded": False, |
95 |
| - "errors": [ |
96 |
| - ''.join(format_exception(err)), |
97 |
| - # or send simpler exception-only summary without full traceback: |
98 |
| - # f'{err.__class__.__name__}: {err}', |
99 |
| - # *([str(err.__context__)] if getattr(err, '__context__', None) else []), |
100 |
| - ], |
101 |
| - }, |
102 |
| - status=status, |
103 |
| - ) |
104 | 5 |
|
| 6 | +from .v1_api import urls as v1_api_urls |
105 | 7 |
|
106 | 8 | urlpatterns = [
|
107 |
| - path("v1/", api.urls), |
| 9 | + path("", RedirectView.as_view(url='/api/v1')), |
108 | 10 |
|
| 11 | + path("v1/", v1_api_urls), |
109 | 12 | path("v1", RedirectView.as_view(url='/api/v1/docs')),
|
110 |
| - path("", RedirectView.as_view(url='/api/v1/docs')), |
| 13 | + |
| 14 | + # ... v2 can be added here ... |
| 15 | + # path("v2/", v2_api_urls), |
| 16 | + # path("v2", RedirectView.as_view(url='/api/v2/docs')), |
111 | 17 | ]
|
0 commit comments