aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2020-03-05 11:36:44 +0100
committerAnton Khirnov <anton@khirnov.net>2020-03-05 11:36:44 +0100
commitb87b3ca2937fa4b24f8fc1627bdacad6194dcd59 (patch)
treea92f0c0bb075c5ba19a484554c0fd61985f21446
parentb388fe2ffe7d786eac61dc68ed4fbafc57450276 (diff)
dash_server: handle DELETE requests
-rw-r--r--README16
-rwxr-xr-xdash_server.py37
2 files changed, 44 insertions, 9 deletions
diff --git a/README b/README
index b05130b..83e986f 100644
--- a/README
+++ b/README
@@ -7,13 +7,15 @@ interpreter. No dependencies beyond the standard library are neded. The
executable takes one mandatory parameter, which is the path to the directory to
which the DASH media files shall be written.
-The server processes incoming HTTP GET, PUT and POST requests. PUT and POST are
-treated identically - request body is written into a file inside the media
-directory, with the name equal to decoded request target. For requests using
-chunked transfer encoding, the body shall also be temporarily cached in memory
-and will be available to incoming GET requests while it is being received.
-To GET requests the server will serve either the accordingly-named file from the
-media directory or the aforementioned cache entry.
+The server processes incoming HTTP GET, PUT, POST and DELETE requests. PUT and
+POST are treated identically - request body is written into a file inside the
+media directory, with the name equal to decoded request target. For requests
+using chunked transfer encoding, the body shall also be temporarily cached in
+memory and will be available to incoming GET requests while it is being
+received. To GET requests the server will serve either the accordingly-named
+file from the media directory or the aforementioned cache entry.
+DELETE requests make the server remove accordingly-named files in the media
+directory if they are not currently being uploaded.
The server is written to be as simple as possible and is intended to be deployed
as a backend behind a gateway HTTP server such as nginx (sample config is
diff --git a/dash_server.py b/dash_server.py
index 9e79c68..17a4ec8 100755
--- a/dash_server.py
+++ b/dash_server.py
@@ -159,14 +159,17 @@ class StreamCache:
def __getitem__(self, key):
self._logger.debug('reading from cache: %s', key)
with self._lock:
- return self._streams[key]
+ ret = self._streams[key]
+ if ret is None:
+ raise KeyError(key)
+ return ret
@contextlib.contextmanager
def add_entry(self, key, val):
self._logger.debug('cache add: %s', key)
with self._lock:
if key in self._streams:
- raise ValueError('Duplicate cache entry: %s' % key)
+ raise FileExistsError('Duplicate cache entry: %s' % key)
self._streams[key] = val
try:
yield val
@@ -295,6 +298,36 @@ class DashRequestHandler(hs.BaseHTTPRequestHandler):
def do_PUT(self):
return self.do_POST()
+ def do_DELETE(self):
+ self._log_request()
+
+ local_path = self._process_path(self.path)
+
+ # add a temporary None cache entry to make sure
+ # - it is not being uploaded right now
+ # - nobody starts uploading it until we are done with the deletion
+ with contextlib.ExitStack() as stack:
+ try:
+ stack.enter_context(self.server._streams.add_entry(local_path, None))
+ except FileExistsError:
+ self._logger.error('DELETE request for open stream: %s' %
+ local_path.decode('utf-8', errors = 'backslashreplace'))
+ self.send_error(HTTPStatus.CONFLICT)
+ return
+
+ targetpath = b'/'.join((self.server.serve_dir, local_path))
+ try:
+ os.remove(targetpath)
+ except FileNotFoundError:
+ self._logger.error('DELETE request for non-existing file: %s' %
+ local_path.decode('utf-8', errors = 'backslashreplace'))
+ self.send_error(HTTPStatus.NOT_FOUND)
+ return
+
+ self.send_response(HTTPStatus.NO_CONTENT)
+ self.send_header('Content-Length', '0')
+ self.end_headers()
+
class DashServer(hs.ThreadingHTTPServer):
serve_dir = None