kopia lustrzana https://github.com/cirospaciari/socketify.py
fixed try_end, removed use of uWebSockets/capi/Makefile
rodzic
dc9677a347
commit
45a29a276b
|
@ -8,8 +8,8 @@ from os import path
|
||||||
mimetypes.init()
|
mimetypes.init()
|
||||||
|
|
||||||
async def home(res, req):
|
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
|
#there is also a helper called static with an sendfile method see static_files.py for examples of usage
|
||||||
#here is an sample implementation, a more complete one is in static.send_file
|
#here is an sample implementation, a more complete one is in static.sendfile
|
||||||
|
|
||||||
filename = "./public/media/flower.webm"
|
filename = "./public/media/flower.webm"
|
||||||
#read headers before the first await
|
#read headers before the first await
|
||||||
|
|
|
@ -7,7 +7,7 @@ mimetypes.init()
|
||||||
# We have an version of this using aiofile and aiofiles
|
# We have an version of this using aiofile and aiofiles
|
||||||
# This is an sync version without any dependencies is normally much faster in CPython and PyPy3
|
# This is an sync version without any dependencies is normally much faster in CPython and PyPy3
|
||||||
# In production we highly recomend to use CDN like CloudFlare or/and NGINX or similar for static files
|
# In production we highly recomend to use CDN like CloudFlare or/and NGINX or similar for static files
|
||||||
async def send_file(res, req, filename):
|
async def sendfile(res, req, filename):
|
||||||
#read headers before the first await
|
#read headers before the first await
|
||||||
if_modified_since = req.get_header('if-modified-since')
|
if_modified_since = req.get_header('if-modified-since')
|
||||||
range_header = req.get_header('range')
|
range_header = req.get_header('range')
|
||||||
|
@ -62,7 +62,6 @@ async def send_file(res, req, filename):
|
||||||
#tells the browser that we support range
|
#tells the browser that we support range
|
||||||
res.write_header(b'Accept-Ranges', b'bytes')
|
res.write_header(b'Accept-Ranges', b'bytes')
|
||||||
res.write_header(b'Content-Range', 'bytes %d-%d/%d' % (start, end, total_size))
|
res.write_header(b'Content-Range', 'bytes %d-%d/%d' % (start, end, total_size))
|
||||||
|
|
||||||
pending_size = size
|
pending_size = size
|
||||||
#keep sending until abort or done
|
#keep sending until abort or done
|
||||||
while not res.aborted:
|
while not res.aborted:
|
||||||
|
@ -95,11 +94,11 @@ def static_route(app, route, directory):
|
||||||
if url.startswith("/"):
|
if url.startswith("/"):
|
||||||
url = url[1::]
|
url = url[1::]
|
||||||
filename = path.join(path.realpath(directory), url)
|
filename = path.join(path.realpath(directory), url)
|
||||||
|
|
||||||
if not in_directory(filename, directory):
|
if not in_directory(filename, directory):
|
||||||
res.write_status(404).end_without_body()
|
res.write_status(404).end_without_body()
|
||||||
return
|
return
|
||||||
res.run_async(send_file(res, req, filename))
|
res.run_async(sendfile(res, req, filename))
|
||||||
if route.startswith("/"):
|
if route.startswith("/"):
|
||||||
route = route[1::]
|
route = route[1::]
|
||||||
app.get("%s/*" % route, route_handler)
|
app.get("%s/*" % route, route_handler)
|
|
@ -6,7 +6,7 @@ from os import path
|
||||||
|
|
||||||
mimetypes.init()
|
mimetypes.init()
|
||||||
# In production we highly recomend to use CDN like CloudFlare or/and NGINX or similar for static files
|
# In production we highly recomend to use CDN like CloudFlare or/and NGINX or similar for static files
|
||||||
async def send_file(res, req, filename):
|
async def sendfile(res, req, filename):
|
||||||
#read headers before the first await
|
#read headers before the first await
|
||||||
if_modified_since = req.get_header('if-modified-since')
|
if_modified_since = req.get_header('if-modified-since')
|
||||||
range_header = req.get_header('range')
|
range_header = req.get_header('range')
|
||||||
|
@ -99,7 +99,7 @@ def static_route(app, route, directory):
|
||||||
if not in_directory(filename, directory):
|
if not in_directory(filename, directory):
|
||||||
res.write_status(404).end_without_body()
|
res.write_status(404).end_without_body()
|
||||||
return
|
return
|
||||||
res.run_async(send_file(res, req, filename))
|
res.run_async(sendfile(res, req, filename))
|
||||||
if route.startswith("/"):
|
if route.startswith("/"):
|
||||||
route = route[1::]
|
route = route[1::]
|
||||||
app.get("%s/*" % route, route_handler)
|
app.get("%s/*" % route, route_handler)
|
|
@ -6,7 +6,7 @@ from os import path
|
||||||
|
|
||||||
mimetypes.init()
|
mimetypes.init()
|
||||||
# In production we highly recomend to use CDN like CloudFlare or/and NGINX or similar for static files
|
# In production we highly recomend to use CDN like CloudFlare or/and NGINX or similar for static files
|
||||||
async def send_file(res, req, filename):
|
async def sendfile(res, req, filename):
|
||||||
#read headers before the first await
|
#read headers before the first await
|
||||||
if_modified_since = req.get_header('if-modified-since')
|
if_modified_since = req.get_header('if-modified-since')
|
||||||
range_header = req.get_header('range')
|
range_header = req.get_header('range')
|
||||||
|
@ -99,7 +99,7 @@ def static_route(app, route, directory):
|
||||||
if not in_directory(filename, directory):
|
if not in_directory(filename, directory):
|
||||||
res.write_status(404).end_without_body()
|
res.write_status(404).end_without_body()
|
||||||
return
|
return
|
||||||
res.run_async(send_file(res, req, filename))
|
res.run_async(sendfile(res, req, filename))
|
||||||
if route.startswith("/"):
|
if route.startswith("/"):
|
||||||
route = route[1::]
|
route = route[1::]
|
||||||
app.get("%s/*" % route, route_handler)
|
app.get("%s/*" % route, route_handler)
|
|
@ -31,7 +31,7 @@
|
||||||
|
|
||||||
from socketify import App
|
from socketify import App
|
||||||
from helpers.static import static_route
|
from helpers.static import static_route
|
||||||
from helpers.static import send_file
|
from helpers.static import sendfile
|
||||||
|
|
||||||
|
|
||||||
app = App()
|
app = App()
|
||||||
|
@ -40,7 +40,7 @@ app = App()
|
||||||
#send home page index.html
|
#send home page index.html
|
||||||
async def home(res, req):
|
async def home(res, req):
|
||||||
#sends the whole file with 304 and bytes range support
|
#sends the whole file with 304 and bytes range support
|
||||||
await send_file(res, req, "./public/index.html")
|
await sendfile(res, req, "./public/index.html")
|
||||||
|
|
||||||
app.get("/", home)
|
app.get("/", home)
|
||||||
|
|
||||||
|
|
19
setup.py
19
setup.py
|
@ -18,11 +18,10 @@ import subprocess
|
||||||
|
|
||||||
_ROOT = pathlib.Path(__file__).parent
|
_ROOT = pathlib.Path(__file__).parent
|
||||||
|
|
||||||
UWS_CAPI_DIR = str(_ROOT / "build" / "uWebSockets" / "capi")
|
UWS_LIB_PATH = str(_ROOT / "build" / "native" / "libuwebsockets.so")
|
||||||
UWS_LIB_PATH = str(_ROOT / "build" / "uWebSockets" / "capi" / "libuwebsockets.so")
|
|
||||||
UWS_DIR = str(_ROOT / "src" / "socketify" /"uWebSockets")
|
UWS_DIR = str(_ROOT / "src" / "socketify" /"uWebSockets")
|
||||||
UWS_BUILD_DIR = str(_ROOT / "build" /"uWebSockets")
|
UWS_BUILD_DIR = str(_ROOT / "build" /"uWebSockets")
|
||||||
UWS_LIB_OUTPUT = str(_ROOT / "src" / "socketify" / "libuwebsockets.so")
|
UWS_LIB_OUTPUT = str(_ROOT / "src" / "socketify" / "native" / "libuwebsockets.so")
|
||||||
|
|
||||||
|
|
||||||
NATIVE_CAPI_DIR = str(_ROOT / "build" / "native")
|
NATIVE_CAPI_DIR = str(_ROOT / "build" / "native")
|
||||||
|
@ -37,7 +36,8 @@ NATIVE_LIB_OUTPUT = str(_ROOT / "src" / "socketify" / "native"/ "libsocketify.so
|
||||||
class Prepare(sdist):
|
class Prepare(sdist):
|
||||||
def run(self):
|
def run(self):
|
||||||
super().run()
|
super().run()
|
||||||
|
|
||||||
|
|
||||||
class Makefile(build_ext):
|
class Makefile(build_ext):
|
||||||
def run(self):
|
def run(self):
|
||||||
env = os.environ.copy()
|
env = os.environ.copy()
|
||||||
|
@ -46,16 +46,13 @@ class Makefile(build_ext):
|
||||||
shutil.rmtree(UWS_BUILD_DIR)
|
shutil.rmtree(UWS_BUILD_DIR)
|
||||||
shutil.copytree(UWS_DIR, UWS_BUILD_DIR)
|
shutil.copytree(UWS_DIR, UWS_BUILD_DIR)
|
||||||
|
|
||||||
subprocess.run(["make", "shared"], cwd=UWS_CAPI_DIR, env=env, check=True)
|
|
||||||
shutil.move(UWS_LIB_PATH, UWS_LIB_OUTPUT)
|
|
||||||
|
|
||||||
|
|
||||||
if os.path.exists(NATIVE_CAPI_DIR):
|
if os.path.exists(NATIVE_CAPI_DIR):
|
||||||
shutil.rmtree(NATIVE_CAPI_DIR)
|
shutil.rmtree(NATIVE_CAPI_DIR)
|
||||||
shutil.copytree(NATIVE_DIR, NATIVE_CAPI_DIR)
|
shutil.copytree(NATIVE_DIR, NATIVE_CAPI_DIR)
|
||||||
|
|
||||||
subprocess.run(["make"], cwd=NATIVE_CAPI_DIR, env=env, check=True)
|
subprocess.run(["make", "shared"], cwd=NATIVE_CAPI_DIR, env=env, check=True)
|
||||||
shutil.move(NATIVE_LIB_PATH, NATIVE_LIB_OUTPUT)
|
shutil.move(NATIVE_LIB_PATH, NATIVE_LIB_OUTPUT)
|
||||||
|
shutil.move(UWS_LIB_PATH, UWS_LIB_OUTPUT)
|
||||||
|
|
||||||
super().run()
|
super().run()
|
||||||
|
|
||||||
|
@ -86,8 +83,8 @@ setuptools.setup(
|
||||||
package_dir={"": "src"},
|
package_dir={"": "src"},
|
||||||
package_data={"": ['./*.so', './uWebSockets/*','./uWebSockets/*/*','./uWebSockets/*/*/*', './native/*','./native/*/*','./native/*/*/*']},
|
package_data={"": ['./*.so', './uWebSockets/*','./uWebSockets/*/*','./uWebSockets/*/*/*', './native/*','./native/*/*','./native/*/*/*']},
|
||||||
python_requires=">=3.7",
|
python_requires=">=3.7",
|
||||||
install_requires=["cffi>=1.0.0"],
|
install_requires=["cffi>=1.0.0", "setuptools>=60.0.0"],
|
||||||
has_ext_modules=lambda: True,
|
has_ext_modules=lambda: True,
|
||||||
cmdclass={'sdist': Prepare,'build_ext': Makefile},
|
cmdclass={'sdist': Prepare, 'build_ext': Makefile},
|
||||||
include_package_data=True
|
include_package_data=True
|
||||||
)
|
)
|
|
@ -1,5 +1,23 @@
|
||||||
LIBRARY_NAME := libsocketify
|
LIBRARY_NAME := libsocketify
|
||||||
|
UWS_LIBRARY_NAME := libuwebsockets
|
||||||
|
|
||||||
|
clean:
|
||||||
|
cd ../uWebSockets/uSockets && rm -f *.o $(LIBRARY_NAME).a $(LIBRARY_NAME).so $(UWS_LIBRARY_NAME).a $(UWS_LIBRARY_NAME).so
|
||||||
|
cd ../uWebSockets/ && rm -f *.o $(LIBRARY_NAME).a $(LIBRARY_NAME).so $(UWS_LIBRARY_NAME).a $(UWS_LIBRARY_NAME).so
|
||||||
|
rm -f *.o $(LIBRARY_NAME).a $(LIBRARY_NAME).so $(UWS_LIBRARY_NAME).a $(UWS_LIBRARY_NAME).so
|
||||||
|
|
||||||
|
shared:
|
||||||
|
|
||||||
|
$(MAKE) clean
|
||||||
|
|
||||||
|
cd ../uWebSockets/uSockets && $(CC) -pthread -DLIBUS_USE_OPENSSL -DLIBUS_USE_LIBUV -std=c11 -Isrc -flto -fPIC -O3 -c src/*.c src/eventing/*.c src/crypto/*.c
|
||||||
|
cd ../uWebSockets/uSockets && $(CXX) -std=c++17 -flto -fPIC -O3 -c src/crypto/*.cpp
|
||||||
|
cd ../uWebSockets/uSockets && $(AR) rvs uSockets.a *.o
|
||||||
|
|
||||||
|
$(CXX) -c -O3 -std=c++17 -lz -luv -flto -fPIC -I ../uWebSockets/src -I ../uWebSockets/uSockets/src ../uWebSockets/capi/$(UWS_LIBRARY_NAME).cpp
|
||||||
|
$(CXX) -shared -o $(UWS_LIBRARY_NAME).so $(UWS_LIBRARY_NAME).o ../uWebSockets/uSockets/uSockets.a -fPIC -lz -luv -lssl -lcrypto
|
||||||
|
|
||||||
default:
|
|
||||||
$(CC) -c -O3 -luv -flto -fPIC -I ./src ./src/$(LIBRARY_NAME).c
|
$(CC) -c -O3 -luv -flto -fPIC -I ./src ./src/$(LIBRARY_NAME).c
|
||||||
$(CC) -shared -o $(LIBRARY_NAME).so $(LIBRARY_NAME).o -luv
|
$(CC) -shared -o $(LIBRARY_NAME).so $(LIBRARY_NAME).o -luv
|
||||||
|
|
||||||
|
rm -f *.o
|
|
@ -225,7 +225,7 @@ void uws_req_for_each_header(uws_req_t *res, uws_get_headers_server_handler hand
|
||||||
|
|
||||||
""")
|
""")
|
||||||
|
|
||||||
library_path = os.path.join(os.path.dirname(__file__), "libuwebsockets.so")
|
library_path = os.path.join(os.path.dirname(__file__), "native", "libuwebsockets.so")
|
||||||
|
|
||||||
lib = ffi.dlopen(library_path)
|
lib = ffi.dlopen(library_path)
|
||||||
@ffi.callback("void(const char *, size_t, const char *, size_t, void *)")
|
@ffi.callback("void(const char *, size_t, const char *, size_t, void *)")
|
||||||
|
@ -583,9 +583,11 @@ class AppResponse:
|
||||||
def send_chunk(self, buffer, total_size):
|
def send_chunk(self, buffer, total_size):
|
||||||
self._chunkFuture = self.loop.create_future()
|
self._chunkFuture = self.loop.create_future()
|
||||||
self._lastChunkOffset = 0
|
self._lastChunkOffset = 0
|
||||||
|
|
||||||
def is_aborted(self):
|
def is_aborted(self):
|
||||||
self.aborted = True
|
self.aborted = True
|
||||||
try:
|
try:
|
||||||
|
print("aborted!", self._chunkFuture.done())
|
||||||
if not self._chunkFuture.done():
|
if not self._chunkFuture.done():
|
||||||
self._chunkFuture.set_result((False, True)) #if aborted set to done True and ok False
|
self._chunkFuture.set_result((False, True)) #if aborted set to done True and ok False
|
||||||
except:
|
except:
|
||||||
|
@ -650,10 +652,10 @@ class AppResponse:
|
||||||
lib.uws_res_override_write_offset(self.SSL, self.res, ffi.cast("uintmax_t", offset))
|
lib.uws_res_override_write_offset(self.SSL, self.res, ffi.cast("uintmax_t", offset))
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def try_end(self, message, total_size, close_connection=False):
|
def try_end(self, message, total_size, end_connection=False):
|
||||||
try:
|
try:
|
||||||
if self.aborted:
|
if self.aborted:
|
||||||
return (False, False)
|
return (False, True)
|
||||||
if self._write_jar != None:
|
if self._write_jar != None:
|
||||||
self.write_header("Set-Cookie", self._write_jar.output(header=""))
|
self.write_header("Set-Cookie", self._write_jar.output(header=""))
|
||||||
self._write_jar = None
|
self._write_jar = None
|
||||||
|
@ -662,11 +664,11 @@ class AppResponse:
|
||||||
elif isinstance(message, bytes):
|
elif isinstance(message, bytes):
|
||||||
data = message
|
data = message
|
||||||
else:
|
else:
|
||||||
return (False, False)
|
return (False, True)
|
||||||
result = lib.uws_res_try_end(self.SSL, self.res, data, len(data),ffi.cast("uintmax_t", total_size), 1 if end_connection else 0)
|
result = lib.uws_res_try_end(self.SSL, self.res, data, len(data),ffi.cast("uintmax_t", total_size), 1 if end_connection else 0)
|
||||||
return (bool(result.ok), bool(result.has_responded))
|
return (bool(result.ok), bool(result.has_responded))
|
||||||
except:
|
except:
|
||||||
return (False, False)
|
return (False, True)
|
||||||
|
|
||||||
def cork_end(self, message, end_connection=False):
|
def cork_end(self, message, end_connection=False):
|
||||||
self.cork(lambda res: res.end(message, end_connection))
|
self.cork(lambda res: res.end(message, end_connection))
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit a9a248486dcd4883dfac4456658080ca33059cb2
|
Subproject commit d38dbd88348d42292f5c2c4ab7daf9b5aa1bb657
|
Ładowanie…
Reference in New Issue