taskops-cli 0.5.4__py3-none-any.whl → 0.5.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- taskops/_version.py +1 -1
- taskops/http/handler.py +17 -2
- taskops/ui/app.js +10 -10
- {taskops_cli-0.5.4.dist-info → taskops_cli-0.5.6.dist-info}/METADATA +1 -1
- {taskops_cli-0.5.4.dist-info → taskops_cli-0.5.6.dist-info}/RECORD +7 -7
- {taskops_cli-0.5.4.dist-info → taskops_cli-0.5.6.dist-info}/WHEEL +0 -0
- {taskops_cli-0.5.4.dist-info → taskops_cli-0.5.6.dist-info}/entry_points.txt +0 -0
taskops/_version.py
CHANGED
taskops/http/handler.py
CHANGED
|
@@ -75,8 +75,16 @@ class Handler(BaseHTTPRequestHandler):
|
|
|
75
75
|
elif tail.startswith("ui"):
|
|
76
76
|
page.answer(self, board, tail[2:]) # 0.5.0's address, kept — links were pasted
|
|
77
77
|
elif self.mounts.ui is None and NAME.match(board) and (not tail or static.asset(tail)):
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
if not tail and not self.path.partition("?")[0].endswith("/"):
|
|
79
|
+
# The page's assets are RELATIVE (./app.js — one bundle, three mounts),
|
|
80
|
+
# so the slashless /<board> resolves them against the root and renders
|
|
81
|
+
# blank: exactly the address people paste. One hop repairs them all —
|
|
82
|
+
# keeping the query, because ?token= is how a window authenticates.
|
|
83
|
+
_, sep, query = self.path.partition("?")
|
|
84
|
+
self._redirect(f"/{board}/{sep}{query}")
|
|
85
|
+
else:
|
|
86
|
+
# the page at the board's OWN address; assets are a CLOSED set
|
|
87
|
+
page.answer(self, board, tail)
|
|
80
88
|
elif (found := static.at_root(self.mounts.ui, self.path)) is not None:
|
|
81
89
|
self._send(200, *found) # a WINDOW serves its page at the ROOT
|
|
82
90
|
else:
|
|
@@ -170,6 +178,13 @@ class Handler(BaseHTTPRequestHandler):
|
|
|
170
178
|
def _json(self, status: int, body: dict[str, Any]) -> None:
|
|
171
179
|
self._send(status, json.dumps(body).encode(), "application/json")
|
|
172
180
|
|
|
181
|
+
def _redirect(self, location: str) -> None:
|
|
182
|
+
"""One permanent hop, no body — the only writer of a Location header."""
|
|
183
|
+
self.send_response(301)
|
|
184
|
+
self.send_header("Location", location)
|
|
185
|
+
self.send_header("Content-Length", "0")
|
|
186
|
+
self.end_headers()
|
|
187
|
+
|
|
173
188
|
def _send(self, status: int, data: bytes, kind: str) -> None:
|
|
174
189
|
"""Content-Length on EVERY answer: this is HTTP/1.1 with keep-alive, and a body
|
|
175
190
|
without one leaves the next request on the socket unparseable."""
|