Add functional to send static files
Add - internal project file iterator function - path function to locate user files (first allocate as static-files) - primitive HTML page files for demonstrate server functional Change - Response class as iterator - code for send response to client
This commit is contained in:
parent
742d62aa71
commit
887e8da01b
8 changed files with 107 additions and 25 deletions
0
__init__.py
Normal file
0
__init__.py
Normal file
|
@ -1,5 +1,13 @@
|
|||
from server.url import path
|
||||
|
||||
|
||||
SETUP = {
|
||||
"server": {
|
||||
"port": 8080,
|
||||
}
|
||||
}
|
||||
|
||||
urls = [
|
||||
path("/", "static-file", "index.html"),
|
||||
path("/template", "template", "index.html")
|
||||
]
|
||||
|
|
7
main.py
Executable file
7
main.py
Executable file
|
@ -0,0 +1,7 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
from server.main import start
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
start()
|
10
server/file_read.py
Normal file
10
server/file_read.py
Normal file
|
@ -0,0 +1,10 @@
|
|||
def fileiter(filename):
|
||||
with open(filename, "rb") as f:
|
||||
while True:
|
||||
file_data = f.read(1024)
|
||||
|
||||
if len(file_data) >= 1024:
|
||||
yield file_data
|
||||
else:
|
||||
yield file_data
|
||||
break
|
65
__main__.py → server/main.py
Executable file → Normal file
65
__main__.py → server/main.py
Executable file → Normal file
|
@ -1,11 +1,11 @@
|
|||
#!/usr/bin/python3.12
|
||||
|
||||
import threading
|
||||
import socket
|
||||
import logging
|
||||
|
||||
import config
|
||||
|
||||
from .file_read import fileiter
|
||||
|
||||
|
||||
MAX_REQLINE = 64 * 1024
|
||||
|
||||
|
@ -17,24 +17,42 @@ STATUS_CODE = {
|
|||
|
||||
|
||||
class Response:
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
def __init__(self, status_code=200, additional_headers={}, data=None):
|
||||
self.status_code = status_code
|
||||
self.additional_headers = additional_headers
|
||||
self.data = data
|
||||
self.first = True
|
||||
|
||||
def get(self):
|
||||
resp = f"HTTP/1.1 {self.status_code} {STATUS_CODE[self.status_code]}\r\n"
|
||||
def __next__(self):
|
||||
if self.first:
|
||||
resp = "HTTP/1.1 {} {}\r\n"
|
||||
resp += "Server: cnserv\r\n"
|
||||
resp += "Connection: close\r\n"
|
||||
for key, val in self.additional_headers.items():
|
||||
resp += "{}: {}\r\n".format(key, val)
|
||||
resp += "\r\n"
|
||||
|
||||
resp = resp.format(self.status_code, STATUS_CODE[self.status_code])
|
||||
resp = resp.encode("UTF-8")
|
||||
|
||||
if self.data:
|
||||
if type(self.data) == bytes:
|
||||
resp += self.data
|
||||
|
||||
self.first = False
|
||||
return resp
|
||||
|
||||
else:
|
||||
if type(self.data) == bytes:
|
||||
raise StopIteration
|
||||
|
||||
elif hasattr(self.data, "__iter__"):
|
||||
try:
|
||||
return next(self.data)
|
||||
except StopIteration:
|
||||
raise StopIteration
|
||||
|
||||
class HTTPHandler:
|
||||
http_type = ""
|
||||
|
@ -124,21 +142,34 @@ class HTTPHandler:
|
|||
self.send_form_data()
|
||||
|
||||
def send_form_data(self):
|
||||
if self.http_type == "GET":
|
||||
if self.http_address == "/":
|
||||
r = Response(data=b"Tested!")
|
||||
self.write_fb.write(r.get())
|
||||
found = False
|
||||
|
||||
elif self.http_address == "/server-status":
|
||||
form_data = "{\"server-name\": \"cnserv\", \"state\": \"running\"}"
|
||||
r = Response(data=form_data.encode("UTF-8"))
|
||||
self.write_fb.write(r.get())
|
||||
for elem in config.urls:
|
||||
if self.http_address in elem.keys():
|
||||
url_metadata = elem[self.http_address]
|
||||
|
||||
if self.http_type in url_metadata[0]:
|
||||
found = True
|
||||
|
||||
if url_metadata[1] == "static-file":
|
||||
r = Response(data=fileiter(url_metadata[2]))
|
||||
|
||||
for i in r:
|
||||
self.write_fb.write(i)
|
||||
self.write_fb.flush()
|
||||
else:
|
||||
form_data = "Not found!"
|
||||
r = Response(status_code=404, data=form_data.encode("UTF-8"))
|
||||
self.write_fb.write(r.get())
|
||||
logging.warning("Address configured on server, but not allowed URL type in URLs list")
|
||||
r = Response(status_code=404, data=b"Address configured on server, but not allowed URL type in URLs list")
|
||||
|
||||
for i in r:
|
||||
self.write_fb.write(i)
|
||||
self.write_fb.flush()
|
||||
|
||||
if not found:
|
||||
r = Response(status_code=404, data=b"Not found!")
|
||||
|
||||
for i in r:
|
||||
self.write_fb.write(i)
|
||||
self.write_fb.flush()
|
||||
|
||||
self.write_fb.close()
|
||||
|
@ -146,7 +177,7 @@ class HTTPHandler:
|
|||
self.conn.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
def start():
|
||||
logging.basicConfig(filename="main.log", filemode="a", encoding="UTF-8",
|
||||
level=logging.DEBUG, format="[%(asctime)s][%(levelname)s] %(message)s")
|
||||
|
6
server/url.py
Normal file
6
server/url.py
Normal file
|
@ -0,0 +1,6 @@
|
|||
def path(path="/", _type="static-file", _file="index.html", methods=("GET",)):
|
||||
if _type == "static-file":
|
||||
return {path: (methods, _type, "static/{}".format(_file))}
|
||||
|
||||
elif _type == "template":
|
||||
return {path: (methods, _type, "template/{}".format(_file))}
|
10
static/index.html
Normal file
10
static/index.html
Normal file
|
@ -0,0 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>CatNet static file</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Static file has been loaded</h1>
|
||||
<p>Static data</p>
|
||||
</body>
|
||||
</html>
|
10
template/index.html
Normal file
10
template/index.html
Normal file
|
@ -0,0 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>CatNet Template</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Template has been loaded</h1>
|
||||
<p>{template_data}</p>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in a new issue