file_stream.py and static_file.py examples added

pull/39/head
Ciro 2022-10-26 21:36:37 -03:00
rodzic 39041a9453
commit bce55b4c0f
12 zmienionych plików z 277 dodań i 16 usunięć

Wyświetl plik

@ -552,7 +552,7 @@ class AppResponse:
return self._chunkFuture
#failed to send chunk
self._lastChunkOffset = self.get_write_offset()
return self._chunkFuture
def get_data(self):

Wyświetl plik

@ -18,36 +18,80 @@
# try_end
# get_full_url
# for_each_header
# https://github.com/uNetworking/uWebSockets.js/blob/master/examples/VideoStreamer.js
from socketify import App
import os
# import os
import multiprocessing
import asyncio
import aiofiles
from aiofiles import os
import time
import mimetypes
mimetypes.init()
#need to fix get_data using sel._data etc
async def home(res, req):
# res.write_header("Content-Type", "plain/text")
# await asyncio.sleep(0)
# res.write_header("Content-Type", "audio/mpeg")
res.write_header("Content-Type", "application/octet-stream")
filename = "./file_example_MP3_5MG.mp3"
total = os.stat(filename).st_size
async with aiofiles.open(filename, "rb") as fd:
while not res.aborted:
buffer = await fd.read(16*1024)
(ok, done) = await res.send_chunk(buffer, total)
if not ok or done: #if cannot send probably aborted
break
if_modified_since = req.get_header('if-modified-since')
range_header = req.get_header('range')
bytes_range = None
start = 0
end = -1
if range_header:
bytes_range = range_header.replace("bytes=", '').split('-')
start = int(bytes_range[0])
if bytes_range[1]:
end = int(bytes_range[1])
try:
exists = await os.path.exists(filename)
if not exists:
return res.write_status(404).end(b'Not Found')
stats = await os.stat(filename)
total_size = stats.st_size
last_modified = time.strftime('%a, %d %b %Y %H:%M:%S GMT', time.gmtime(stats.st_mtime))
if if_modified_since == last_modified:
res.write_status(304).end_without_body()
return
res.write_header(b'Last-Modified', last_modified)
(content_type, encoding) = mimetypes.guess_type(filename, strict=True)
if content_type and encoding:
res.write_header(b'Content-Type', '%s; %s' % (content_type, encoding))
elif content_type:
res.write_header(b'Content-Type', content_type)
async with aiofiles.open(filename, "rb") as fd:
if start > 0 or not end == -1:
if end < 1 or end >= total_size:
end = total_size
total_size = end - start
await fd.seek(start)
res.write_status(206)
else:
end = total_size
res.write_status(200)
#tells the browser that we support ranges
res.write_header(b'Accept-Ranges', b'bytes')
res.write_header(b'Content-Range', 'bytes %d-%d/%d' % (start, end, total_size))
while not res.aborted:
buffer = await fd.read(16384) #16kb chunks
(ok, done) = await res.send_chunk(buffer, total_size)
if not ok or done: #if cannot send probably aborted
break
except Exception as error:
print(str(error))
res.write_status(500).end("Internal Error")
def run_app():
app = App()
app.get("/", home)
app.listen(3000, lambda config: print("PID %d Listening on port http://localhost:%d now\n" % (os.getpid(), config.port)))
app.listen(3000, lambda config: print("Listening on port http://localhost:%d now\n" % (config.port)))
app.run()
def create_fork():

Wyświetl plik

@ -0,0 +1,65 @@
from socketify import App
import aiofiles
from aiofiles import os
import time
import mimetypes
from os import path
mimetypes.init()
async def home(res, req):
#there is also a helper called static with an send_file method see static_files.py for examples of usage
#here is an sample implementation, a more complete one is in static.send_file
filename = "./public/media/flower.webm"
#read headers before the first await
if_modified_since = req.get_header('if-modified-since')
try:
exists = await os.path.exists(filename)
#not found
if not exists:
return res.write_status(404).end(b'Not Found')
#get size and last modified date
stats = await os.stat(filename)
total_size = stats.st_size
last_modified = time.strftime('%a, %d %b %Y %H:%M:%S GMT', time.gmtime(stats.st_mtime))
#check if modified since is provided
if if_modified_since == last_modified:
res.write_status(304).end_without_body()
return
#tells the broswer the last modified date
res.write_header(b'Last-Modified', last_modified)
#add content type
(content_type, encoding) = mimetypes.guess_type(filename, strict=True)
if content_type and encoding:
res.write_header(b'Content-Type', '%s; %s' % (content_type, encoding))
elif content_type:
res.write_header(b'Content-Type', content_type)
async with aiofiles.open(filename, "rb") as fd:
res.write_status(200)
pending_size = total_size
#keep sending until abort or done
while not res.aborted:
chunk_size = 16384 #16kb chunks
if chunk_size > pending_size:
chunk_size = pending_size
buffer = await fd.read(chunk_size)
pending_size = pending_size - chunk_size
(ok, done) = await res.send_chunk(buffer, total_size)
if not ok or done or pending_size <= 0: #if cannot send probably aborted
break
except Exception as error:
res.write_status(500).end("Internal Error")
app = App()
app.get("/", home)
app.listen(3000, lambda config: print("Listening on port http://localhost:%d now\n" % config.port))
app.run()

Wyświetl plik

@ -0,0 +1,105 @@
import aiofiles
from aiofiles import os
import time
import mimetypes
from os import path
mimetypes.init()
#try with https://github.com/mosquito/aiofile
async def send_file(res, req, filename):
#read headers before the first await
if_modified_since = req.get_header('if-modified-since')
range_header = req.get_header('range')
bytes_range = None
start = 0
end = -1
#parse range header
if range_header:
bytes_range = range_header.replace("bytes=", '').split('-')
start = int(bytes_range[0])
if bytes_range[1]:
end = int(bytes_range[1])
try:
exists = await os.path.exists(filename)
#not found
if not exists:
return res.write_status(404).end(b'Not Found')
#get size and last modified date
stats = await os.stat(filename)
total_size = stats.st_size
size = total_size
last_modified = time.strftime('%a, %d %b %Y %H:%M:%S GMT', time.gmtime(stats.st_mtime))
#check if modified since is provided
if if_modified_since == last_modified:
return res.write_status(304).end_without_body()
#tells the broswer the last modified date
res.write_header(b'Last-Modified', last_modified)
#add content type
(content_type, encoding) = mimetypes.guess_type(filename, strict=True)
if content_type and encoding:
res.write_header(b'Content-Type', '%s; %s' % (content_type, encoding))
elif content_type:
res.write_header(b'Content-Type', content_type)
async with aiofiles.open(filename, "rb") as fd:
#check range and support it
if start > 0 or not end == -1:
if end < 0 or end >= size:
end = size - 1
size = end - start + 1
await fd.seek(start)
if start > total_size or size > total_size or size < 0 or start < 0:
return res.write_status(416).end_without_body()
res.write_status(206)
else:
end = size - 1
res.write_status(200)
#tells the browser that we support range
#TODO: FIX BYTE RANGE IN ASYNC
# res.write_header(b'Accept-Ranges', b'bytes')
# res.write_header(b'Content-Range', 'bytes %d-%d/%d' % (start, end, total_size))
pending_size = size
#keep sending until abort or done
while not res.aborted:
chunk_size = 16384 #16kb chunks
if chunk_size > pending_size:
chunk_size = pending_size
buffer = await fd.read(chunk_size)
pending_size = pending_size - chunk_size
(ok, done) = await res.send_chunk(buffer, size)
if not ok or done: #if cannot send probably aborted
break
except Exception as error:
res.write_status(500).end("Internal Error")
def in_directory(file, directory):
#make both absolute
directory = path.join(path.realpath(directory), '')
file = path.realpath(file)
#return true, if the common prefix of both is equal to directory
#e.g. /a/b/c/d.rst and directory is /a/b, the common prefix is /a/b
return path.commonprefix([file, directory]) == directory
def static_route(app, route, directory):
def route_handler(res, req):
url = req.get_url()
res.grab_aborted_handler()
url = url[len(route)::]
if url.startswith("/"):
url = url[1::]
filename = path.join(path.realpath(directory), url)
if not in_directory(filename, directory):
res.write_status(404).end_without_body()
return
res.run_async(send_file(res, req, filename))
if route.startswith("/"):
route = route[1::]
app.get("%s/*" % route, route_handler)

Wyświetl plik

@ -0,0 +1,3 @@
h1 {
color:red
}

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 11 KiB

Wyświetl plik

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Static Test</title>
<link rel="icon" type="image/x-icon" href="/images/favicon.png">
<link rel="stylesheet" href="/css/main.css">
<script defer src="/js/main.js"></script>
</head>
<body>
<h1>This title Must be red</h1>
<video controls>
<source src="/media/flower.webm" type="video/webm">
</video>
</body>
</html>

Wyświetl plik

@ -0,0 +1,3 @@
div = document.createElement("div")
div.innerText = "This Element was added via scripts.js"
document.body.appendChild(div)

Plik binarny nie jest wyświetlany.

Wyświetl plik

@ -0,0 +1 @@
User-agent: * Disallow: /

Wyświetl plik

@ -1,3 +1,4 @@
aiohttp
aiofiles
redis
git+https://github.com/cirospaciari/socketify.py.git@main#socketify --global-option="build_ext"

Wyświetl plik

@ -0,0 +1,20 @@
from socketify import App
from helpers.static import static_route
from helpers.static import send_file
app = App()
#serve all files in public folder under / route (main route but can be like /assets)
static_route(app, "/", "./public")
#send home page index.html
async def home(res, req):
#sends the whole file with 304 and bytes range support
await send_file(res, req, "./public/index.html")
app.get("/", home)
app.listen(3000, lambda config: print("Listening on port http://localhost:%d now\n" % config.port))
app.run()