init
This commit is contained in:
commit
929428279c
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
venv/
|
||||||
|
__pycache__
|
33
echo360/__init__.py
Normal file
33
echo360/__init__.py
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import falcon
|
||||||
|
|
||||||
|
from .tools import JsonRequest, JsonResponse, error_handler
|
||||||
|
from .controllers import *
|
||||||
|
|
||||||
|
class AboutResource():
|
||||||
|
|
||||||
|
def on_get(self, req, resp):
|
||||||
|
r = {"about": {
|
||||||
|
"name": "echo360py API",
|
||||||
|
"version": "1",
|
||||||
|
"docs": "TODO"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resp.body = json.dumps(r, indent=4)
|
||||||
|
|
||||||
|
|
||||||
|
app = application = falcon.API(request_type=JsonRequest, response_type=JsonResponse)
|
||||||
|
app.add_error_handler(ValueError, error_handler)
|
||||||
|
app.add_route("/", AboutResource())
|
||||||
|
|
||||||
|
app.add_route("/Task", TaskResource())
|
||||||
|
app.add_route("/Tasks", TasksCollection())
|
||||||
|
app.add_route("/Tasks/{TaskId}", TasksCollection())
|
||||||
|
|
||||||
|
app.add_route("/Videos/{VideoUuid}/Streams/{StreamId}", StreamCollection())
|
||||||
|
|
||||||
|
FilesStoragePath = Path("files")
|
||||||
|
FilesStoragePath.mkdir(parents=True, exist_ok=True)
|
||||||
|
app.add_route("/File/{FileId}", FileCollection(FilesStoragePath))
|
90
echo360/controllers.py
Normal file
90
echo360/controllers.py
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
from enum import IntEnum
|
||||||
|
from pathlib import Path
|
||||||
|
from falcon import HTTPNotFound
|
||||||
|
|
||||||
|
class TaskStatus(IntEnum):
|
||||||
|
Created = 0
|
||||||
|
Starting = 1
|
||||||
|
Running = 2
|
||||||
|
Finished = 3
|
||||||
|
Error = 4
|
||||||
|
|
||||||
|
tasks = [
|
||||||
|
{
|
||||||
|
"TaskId":0,
|
||||||
|
"Progress":0,
|
||||||
|
"SourceStreamId":0,
|
||||||
|
"DestinationStreamId":1,
|
||||||
|
"TaskStatus":TaskStatus.Created
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
streams = [
|
||||||
|
{
|
||||||
|
"StreamId":0,
|
||||||
|
"MimeType":"application/x-shockwave-flash",
|
||||||
|
"Uris":[
|
||||||
|
{"Uri":"http://10.42.0.1:8080/File/00000000.swf"},
|
||||||
|
{"Uri":"http://10.42.0.1:8080/File/00015000.swf"},
|
||||||
|
{"Uri":"http://10.42.0.1:8080/File/00030000.swf"}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"StreamId":1,
|
||||||
|
"MimeType":"video/x-m4v",
|
||||||
|
"Uris":[]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
class TaskResource():
|
||||||
|
def on_get(self, req, resp):
|
||||||
|
for task in tasks:
|
||||||
|
if task["TaskStatus"] in (TaskStatus.Created, TaskStatus.Error):
|
||||||
|
#task["TaskStatus"] = TaskStatus.Starting
|
||||||
|
resp.json = task
|
||||||
|
return
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise HTTPNotFound()
|
||||||
|
|
||||||
|
class TasksCollection():
|
||||||
|
|
||||||
|
def on_get(self, req, resp, TaskId=None):
|
||||||
|
if TaskId:
|
||||||
|
TaskId = int(TaskId)
|
||||||
|
try:
|
||||||
|
resp.json = tasks[TaskId]
|
||||||
|
except IndexError:
|
||||||
|
raise HTTPNotFound()
|
||||||
|
else:
|
||||||
|
resp.json = tasks
|
||||||
|
|
||||||
|
def on_post(self, req, resp):
|
||||||
|
task = req.json
|
||||||
|
tasks.append(task)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class StreamCollection():
|
||||||
|
|
||||||
|
def on_get(self, req, resp, VideoUuid, StreamId):
|
||||||
|
print(VideoUuid, StreamId)
|
||||||
|
StreamId = int(StreamId)
|
||||||
|
try:
|
||||||
|
resp.json = streams[StreamId]
|
||||||
|
except IndexError:
|
||||||
|
raise HTTPNotFound()
|
||||||
|
|
||||||
|
class FileCollection():
|
||||||
|
def __init__(self, path):
|
||||||
|
self.path = path
|
||||||
|
|
||||||
|
def on_get(self, req, resp, FileId):
|
||||||
|
File = Path(FileId).name
|
||||||
|
File = self.path/File
|
||||||
|
try:
|
||||||
|
with File.open("rb") as f:
|
||||||
|
resp.content_type = "application/octet-stream"
|
||||||
|
resp.body= f.read()
|
||||||
|
except FileNotFoundError:
|
||||||
|
raise HTTPNotFound()
|
51
echo360/tools.py
Normal file
51
echo360/tools.py
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import json
|
||||||
|
|
||||||
|
from falcon import Request as FalconRequest
|
||||||
|
from falcon import Response as FalconResponse
|
||||||
|
from falcon.errors import HTTPBadRequest, HTTPMissingParam, HTTPError
|
||||||
|
import falcon.status_codes as status
|
||||||
|
|
||||||
|
|
||||||
|
class JsonRequest(FalconRequest):
|
||||||
|
|
||||||
|
#__slots__ = set(FalconRequest.__slots__ + ("_json", "_args"))
|
||||||
|
|
||||||
|
|
||||||
|
@property
|
||||||
|
def json(self):
|
||||||
|
if not hasattr(self, "_json"):
|
||||||
|
if not self.client_accepts_json:
|
||||||
|
raise falcon.HTTPUnsupportedMediaType(
|
||||||
|
'This API only supports the JSON formated data')
|
||||||
|
try:
|
||||||
|
self._json = json.loads(self.stream.read().decode('utf8'))
|
||||||
|
except json.decoder.JSONDecodeError as err:
|
||||||
|
raise HTTPBadRequest("JSONDecodeError", str(err))
|
||||||
|
return self._json
|
||||||
|
|
||||||
|
|
||||||
|
class JsonResponse(FalconResponse):
|
||||||
|
|
||||||
|
#__slots__ = set(FalconRequest.__slots__ + ("_json",))
|
||||||
|
|
||||||
|
|
||||||
|
@property
|
||||||
|
def json(self):
|
||||||
|
return self._json
|
||||||
|
|
||||||
|
@json.setter
|
||||||
|
def json(self, value):
|
||||||
|
self._json = value
|
||||||
|
self.body = json.dumps(value, indent=4)
|
||||||
|
|
||||||
|
def error_handler(ex, req, resp, params):
|
||||||
|
raise HTTPBadRequest(type(ex).__name__, str(ex))
|
||||||
|
|
||||||
|
class TODOException(HTTPError):
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super(TODOException, self).__init__(status.HTTP_NOT_IMPLEMENTED, **kwargs)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def has_representation(self):
|
||||||
|
return False
|
BIN
files/00000000.swf
Normal file
BIN
files/00000000.swf
Normal file
Binary file not shown.
BIN
files/00015000.swf
Normal file
BIN
files/00015000.swf
Normal file
Binary file not shown.
BIN
files/00030000.swf
Normal file
BIN
files/00030000.swf
Normal file
Binary file not shown.
1
requirements.txt
Normal file
1
requirements.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
falcon
|
23
uwsgi.ini
Normal file
23
uwsgi.ini
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
[uwsgi]
|
||||||
|
plugin=http
|
||||||
|
plugin=python3
|
||||||
|
plugin=python
|
||||||
|
master=true
|
||||||
|
virtualenv=venv
|
||||||
|
processes=1
|
||||||
|
need-app=true
|
||||||
|
|
||||||
|
[dev]
|
||||||
|
ini=:uwsgi
|
||||||
|
http=:8080
|
||||||
|
#static-map2=/=../web
|
||||||
|
#static-index=index.html
|
||||||
|
mount=/api/v1=wsgi.py
|
||||||
|
manage-script-name = true
|
||||||
|
py-autoreload=1
|
||||||
|
|
||||||
|
[prod]
|
||||||
|
ini=:uwsgi
|
||||||
|
module=echo360
|
||||||
|
chdir=/srv/http/echo360py/
|
||||||
|
socket=/run/uwsgi/echo360py
|
Loading…
Reference in New Issue
Block a user