almost ready now pwease? uwu
This commit is contained in:
@@ -7,17 +7,18 @@ Every save I do increments the build number by 1, I won't publish all of them, b
|
|||||||
Once a milestone is hit (e.g. a new feature fully implemented), I'll publish a release!
|
Once a milestone is hit (e.g. a new feature fully implemented), I'll publish a release!
|
||||||
|
|
||||||
## Currently working features:
|
## Currently working features:
|
||||||
* New configuration is ~75% done, most features work.
|
* New configuration is ~95% done, most features work.
|
||||||
* Fixed **A LOT** of unreported bugs from the old code.
|
* Fixed **A LOT** of unreported bugs from the old code.
|
||||||
* More resilliency against errors.
|
* More resilliency against errors.
|
||||||
* Improved security.
|
* Improved security.
|
||||||
|
* Proxy almost working!
|
||||||
|
|
||||||
## Project status:
|
## Project status:
|
||||||
Amethyst will stay in beta for a while, I want all features to work, put I will make pre-release versions that are mostly stable.
|
Amethyst will stay in beta for a while, I want all features to work, but I will make pre-release versions that are mostly stable.
|
||||||
They can be found as the `amethyst-prerel-0.a.b` releases. I won't guarantee 100% stability, but waay more than just some random build.
|
They can be found as the `amethyst-prerel-0.a.b` releases. I won't guarantee 100% stability, but waay more than just some random build.
|
||||||
|
|
||||||
## Install instructions:
|
## Install instructions:
|
||||||
Install Python, and change the provided config.
|
Install Python, execute `amethyst.py` and change the provided config.
|
||||||
|
|
||||||
## Minimum requirements:
|
## Minimum requirements:
|
||||||
Python 3.8+
|
Python 3.8+
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
# WARNING: This is an alpha spec of NSCL 2.0!!
|
||||||
|
|
||||||
|
host * {
|
||||||
|
directory:./html
|
||||||
|
apimode:0
|
||||||
|
block-ua:match("Discordbot")
|
||||||
|
}
|
||||||
|
|
||||||
|
globals {
|
||||||
|
http:1
|
||||||
|
https:1
|
||||||
|
port:8080
|
||||||
|
https-port:8443
|
||||||
|
key:./key.pem
|
||||||
|
cert./cert.pem
|
||||||
|
}
|
||||||
+161
-115
@@ -52,7 +52,7 @@ import sys
|
|||||||
try:
|
try:
|
||||||
if not os.getcwd() in sys.path:
|
if not os.getcwd() in sys.path:
|
||||||
sys.path.append(f"{os.getcwd()}")
|
sys.path.append(f"{os.getcwd()}")
|
||||||
from certgen import AutoCertGen
|
from .certgen import AutoCertGen
|
||||||
except ImportError:
|
except ImportError:
|
||||||
# just do nothing, it's not working anyway.
|
# just do nothing, it's not working anyway.
|
||||||
print(
|
print(
|
||||||
@@ -61,7 +61,7 @@ except ImportError:
|
|||||||
)
|
)
|
||||||
# pass
|
# pass
|
||||||
|
|
||||||
AMETHYST_BUILD_NUMBER = "0053"
|
AMETHYST_BUILD_NUMBER = "b0.2.0-0072"
|
||||||
AMETHYST_REPO = "https://git.novacow.ch/Nova/PyWebServer/"
|
AMETHYST_REPO = "https://git.novacow.ch/Nova/PyWebServer/"
|
||||||
|
|
||||||
|
|
||||||
@@ -119,21 +119,19 @@ class ConfigParser:
|
|||||||
|
|
||||||
|
|
||||||
class FileHandler:
|
class FileHandler:
|
||||||
CONFIG_FILE = "pywebsrv.conf"
|
|
||||||
new_conf = "new_conf.conf"
|
|
||||||
|
|
||||||
def __init__(self, base_dir=None):
|
def __init__(self, base_dir=None):
|
||||||
# this is a fucking clusterfuck.
|
# this is a fucking clusterfuck.
|
||||||
self.config_path = os.path.join(os.getcwd(), self.CONFIG_FILE)
|
self.config_file = "amethyst.conf"
|
||||||
self.new_conf = os.path.join(os.getcwd(), self.new_conf)
|
self.config_path = os.path.join(os.getcwd(), self.config_file)
|
||||||
self.base_dir = self.read_config("directory")
|
with open(self.config_path, "r") as f:
|
||||||
with open(self.new_conf, "r") as f:
|
|
||||||
self.cfg = ConfigParser(f.read())
|
self.cfg = ConfigParser(f.read())
|
||||||
|
self.base_dir = self.read_config("directory")
|
||||||
if not os.path.exists(self.config_path):
|
if not os.path.exists(self.config_path):
|
||||||
|
# uuh???
|
||||||
print(
|
print(
|
||||||
"The pywebsrv.conf file needs to be in the same directory "
|
"The amethyst.conf file needs to be in the same directory "
|
||||||
"as pywebsrv.py! Get the default config file from:\n"
|
"as amethyst.py! Get the default config file from:\n"
|
||||||
"https://git.novacow.ch/Nova/PyWebServer/raw/branch/main/pywebsrv.conf"
|
"https://git.novacow.ch/Nova/PyWebServer/raw/branch/2.0/amethyst.conf"
|
||||||
)
|
)
|
||||||
exit(1)
|
exit(1)
|
||||||
# TODO: fix this please!!
|
# TODO: fix this please!!
|
||||||
@@ -167,72 +165,7 @@ class FileHandler:
|
|||||||
f.write(data)
|
f.write(data)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def read_config(self, option):
|
def read_config(self, key, host_name=None):
|
||||||
"""
|
|
||||||
clean code, whats that????
|
|
||||||
TODO: docs
|
|
||||||
"""
|
|
||||||
option = option.lower()
|
|
||||||
valid_options = [
|
|
||||||
"port",
|
|
||||||
"directory",
|
|
||||||
"host",
|
|
||||||
"http",
|
|
||||||
"https",
|
|
||||||
"port-https",
|
|
||||||
"allow-localhost",
|
|
||||||
"disable-autocertgen",
|
|
||||||
"key-file",
|
|
||||||
"cert-file",
|
|
||||||
"block-ua",
|
|
||||||
]
|
|
||||||
if option not in valid_options:
|
|
||||||
return None
|
|
||||||
with open(self.config_path, "r") as f:
|
|
||||||
for line in f:
|
|
||||||
if line.startswith("#"):
|
|
||||||
continue
|
|
||||||
try:
|
|
||||||
key, value = line.strip().split(":", 1)
|
|
||||||
except ValueError:
|
|
||||||
return None
|
|
||||||
key = key.lower()
|
|
||||||
if key == option:
|
|
||||||
if option == "host":
|
|
||||||
seperated_values = value.split(",", -1)
|
|
||||||
return [value.lower() for value in seperated_values]
|
|
||||||
if option == "block-ua":
|
|
||||||
seperated_values = value.split(",", -1)
|
|
||||||
host_to_match = []
|
|
||||||
literal_blocks = []
|
|
||||||
for val in seperated_values:
|
|
||||||
if val.startswith("match(") and val.endswith(")"):
|
|
||||||
idx = val.index("(")
|
|
||||||
idx2 = val.index(")")
|
|
||||||
ua_to_match = val[idx + 1 : idx2]
|
|
||||||
host_to_match.append(ua_to_match)
|
|
||||||
else:
|
|
||||||
literal_blocks.append(val)
|
|
||||||
return host_to_match, literal_blocks
|
|
||||||
if option == "port" or option == "port-https":
|
|
||||||
return int(value)
|
|
||||||
if (
|
|
||||||
option == "http"
|
|
||||||
or option == "https"
|
|
||||||
or option == "allow-localhost"
|
|
||||||
or option == "disable-autocertgen"
|
|
||||||
):
|
|
||||||
return bool(int(value))
|
|
||||||
if option == "directory":
|
|
||||||
if value == "<Enter directory here>":
|
|
||||||
return os.path.join(os.getcwd(), "html")
|
|
||||||
if value.endswith("/"):
|
|
||||||
value = value.rstrip("/")
|
|
||||||
return value
|
|
||||||
return value
|
|
||||||
return None
|
|
||||||
|
|
||||||
def read_new_config(self, key, host_name=None):
|
|
||||||
print(
|
print(
|
||||||
f"\n\n\nQuery!\nkey: {key}\nhost_name: {host_name}\nret: {self.cfg.query_config(key, host_name)}"
|
f"\n\n\nQuery!\nkey: {key}\nhost_name: {host_name}\nret: {self.cfg.query_config(key, host_name)}"
|
||||||
)
|
)
|
||||||
@@ -250,7 +183,7 @@ class FileHandler:
|
|||||||
class RequestParser:
|
class RequestParser:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.file_handler = FileHandler()
|
self.file_handler = FileHandler()
|
||||||
self.hosts = self.file_handler.read_new_config("hosts")
|
self.hosts = self.file_handler.read_config("hosts")
|
||||||
print(f"Hosts: {self.hosts}")
|
print(f"Hosts: {self.hosts}")
|
||||||
|
|
||||||
def parse_request_line(self, line, host):
|
def parse_request_line(self, line, host):
|
||||||
@@ -258,28 +191,40 @@ class RequestParser:
|
|||||||
try:
|
try:
|
||||||
method, path, version = line.split(" ")
|
method, path, version = line.split(" ")
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return "DELETE", "/this/is/a/bogus/request", "HTTP/1.0"
|
return None, None, None
|
||||||
if path.endswith("/") or ("." not in path):
|
if path.endswith("/") or ("." not in path):
|
||||||
if not path.endswith("/"):
|
if not path.endswith("/"):
|
||||||
path += "/"
|
path += "/"
|
||||||
index = self.file_handler.read_new_config("index", host) or "index.html"
|
index = self.file_handler.read_config("index", host) or "index.html"
|
||||||
path += f"{index}"
|
path += f"{index}"
|
||||||
return method, path, version
|
return method, path, version
|
||||||
|
|
||||||
|
def parse_match_blocks(self, to_parse: str | list):
|
||||||
|
if isinstance(to_parse, str):
|
||||||
|
to_parse = [to_parse]
|
||||||
|
match = []
|
||||||
|
literal = []
|
||||||
|
for block in to_parse:
|
||||||
|
if block.startswith('match("'):
|
||||||
|
adx = block[7:-2]
|
||||||
|
match.append(adx)
|
||||||
|
else:
|
||||||
|
literal.append(block)
|
||||||
|
return match, literal
|
||||||
|
|
||||||
def ua_is_allowed(self, ua, host=None):
|
def ua_is_allowed(self, ua, host=None):
|
||||||
"""Parses and matches UA to block"""
|
"""Parses and matches UA to block"""
|
||||||
return True
|
|
||||||
# del host
|
|
||||||
# _list = self.file_handler.read_config("block-ua")
|
|
||||||
# if _list is None:
|
|
||||||
# return True
|
|
||||||
# match, literal = self.file_handler.parse_match_blocks(_list)
|
|
||||||
# if ua in literal:
|
|
||||||
# return False
|
|
||||||
# for _ua in match:
|
|
||||||
# if _ua.lower() in ua.lower():
|
|
||||||
# return False
|
|
||||||
# return True
|
# return True
|
||||||
|
_list = self.file_handler.read_config("block-ua", host)
|
||||||
|
if _list is None:
|
||||||
|
return True
|
||||||
|
match, literal = self.parse_match_blocks(_list)
|
||||||
|
if ua in literal:
|
||||||
|
return False
|
||||||
|
for _ua in match:
|
||||||
|
if _ua.lower() in ua.lower():
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
def is_method_allowed(self, method, host=None):
|
def is_method_allowed(self, method, host=None):
|
||||||
"""
|
"""
|
||||||
@@ -288,11 +233,7 @@ class RequestParser:
|
|||||||
Falls back to allowing only 'GET' if the file does not exist.
|
Falls back to allowing only 'GET' if the file does not exist.
|
||||||
Should (for now) only be GET as I haven't implemented the logic for PUT
|
Should (for now) only be GET as I haven't implemented the logic for PUT
|
||||||
"""
|
"""
|
||||||
# allowed_methods = ["GET"]
|
allowed_methods = self.file_handler.read_config("allowed-methods", host)
|
||||||
# While the logic for PUT, DELETE, etc. is not added, we shouldn't
|
|
||||||
# allow for it to attempt it.
|
|
||||||
# Prepatched for new update.
|
|
||||||
allowed_methods = self.file_handler.read_new_config("allowed-methods", host)
|
|
||||||
if allowed_methods is None:
|
if allowed_methods is None:
|
||||||
allowed_methods = ["GET"]
|
allowed_methods = ["GET"]
|
||||||
return method in allowed_methods
|
return method in allowed_methods
|
||||||
@@ -308,18 +249,101 @@ class RequestParser:
|
|||||||
host = host.rsplit(":", 1)[0]
|
host = host.rsplit(":", 1)[0]
|
||||||
host = host.lstrip()
|
host = host.lstrip()
|
||||||
host = host.rstrip()
|
host = host.rstrip()
|
||||||
if (
|
|
||||||
host == "localhost" or host == "127.0.0.1" or host == "[::1]"
|
|
||||||
) and self.file_handler.read_new_config("allow-localhost"):
|
|
||||||
return True
|
|
||||||
if self.hosts is None:
|
if self.hosts is None:
|
||||||
return True
|
return True
|
||||||
if host not in self.hosts:
|
if host not in self.hosts:
|
||||||
|
if "*" in self.hosts:
|
||||||
|
return "catchall"
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
class ProxyServer:
|
||||||
|
def __init__(self, fh):
|
||||||
|
self.file_handler: FileHandler = fh
|
||||||
|
|
||||||
|
def try_connection(
|
||||||
|
self, host: str, port: int, data: bytes, chost: str, force_tls: bool = None
|
||||||
|
):
|
||||||
|
if port in [443, 8443, 9443]:
|
||||||
|
do_tls = True
|
||||||
|
else:
|
||||||
|
if force_tls is True:
|
||||||
|
do_tls = True
|
||||||
|
else:
|
||||||
|
do_tls = False
|
||||||
|
print(f"\n\n\nchost: {chost}\n\n\n")
|
||||||
|
nhost = self.file_handler.read_config("proxy", chost)
|
||||||
|
print(f"\n\n\nnhost: {nhost}\n\n\n")
|
||||||
|
if ":" in nhost:
|
||||||
|
nport = int(nhost.split(":")[1])
|
||||||
|
nhost = nhost.split(":")[0]
|
||||||
|
else:
|
||||||
|
nport = port
|
||||||
|
print(f"{nhost}, {nport}, {data}")
|
||||||
|
data = self.reset_host(nhost, nport, data)
|
||||||
|
try:
|
||||||
|
return self.tcp_send(host, port, data, do_tls)
|
||||||
|
except Exception:
|
||||||
|
if do_tls is False:
|
||||||
|
print("Retrying with TLS...")
|
||||||
|
return self.try_connection(host, port, data, chost, True)
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def reset_host(host: str, port: int, data: bytes):
|
||||||
|
data = data.decode()
|
||||||
|
data = data.splitlines()
|
||||||
|
for line in data:
|
||||||
|
print(line)
|
||||||
|
if line.startswith("Host:"):
|
||||||
|
if port not in [80, 443]:
|
||||||
|
new_line = f"Host: {host}:{port}"
|
||||||
|
else:
|
||||||
|
new_line = f"Host: {host}"
|
||||||
|
idx = data.index(line)
|
||||||
|
data[idx] = new_line
|
||||||
|
print(f"\n\n\n{idx}\n\n\n")
|
||||||
|
if line.startswith("Connection:"):
|
||||||
|
idx = data.index(line)
|
||||||
|
new_line = "Connection: close"
|
||||||
|
data[idx] = new_line
|
||||||
|
data = "\r\n".join(data)
|
||||||
|
data = f"{data}\r\n\r\n"
|
||||||
|
print(data)
|
||||||
|
return data.encode()
|
||||||
|
# return data
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def create_tls_context():
|
||||||
|
# Create a context that by default verifies with system CAs
|
||||||
|
ctx = ssl.create_default_context()
|
||||||
|
ctx.check_hostname = False
|
||||||
|
ctx.verify_mode = ssl.CERT_NONE
|
||||||
|
return ctx
|
||||||
|
|
||||||
|
def tcp_send(self, host, port, data: bytes, do_tls: bool):
|
||||||
|
try:
|
||||||
|
with socket.create_connection((host, port), timeout=10) as raw_sock:
|
||||||
|
raw_sock.settimeout(10)
|
||||||
|
if do_tls:
|
||||||
|
ctx = self.create_tls_context()
|
||||||
|
server_hostname = host
|
||||||
|
with ctx.wrap_socket(
|
||||||
|
raw_sock, server_hostname=server_hostname
|
||||||
|
) as ssock:
|
||||||
|
ssock.sendall(data)
|
||||||
|
print("data reached")
|
||||||
|
return ssock.recv(512000)
|
||||||
|
else:
|
||||||
|
raw_sock.sendall(data)
|
||||||
|
return raw_sock.recv(512000)
|
||||||
|
except Exception:
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
class WebServer:
|
class WebServer:
|
||||||
def __init__(
|
def __init__(
|
||||||
self, http_port=8080, https_port=8443, cert_file="cert.pem", key_file="key.pem"
|
self, http_port=8080, https_port=8443, cert_file="cert.pem", key_file="key.pem"
|
||||||
@@ -328,8 +352,8 @@ class WebServer:
|
|||||||
self.https_port = int(https_port)
|
self.https_port = int(https_port)
|
||||||
self.file_handler = FileHandler()
|
self.file_handler = FileHandler()
|
||||||
self.parser = RequestParser()
|
self.parser = RequestParser()
|
||||||
self.cert_file = self.file_handler.read_new_config("cert") or cert_file
|
self.cert_file = self.file_handler.read_config("cert") or cert_file
|
||||||
self.key_file = self.file_handler.read_new_config("key") or key_file
|
self.key_file = self.file_handler.read_config("key") or key_file
|
||||||
self.skip_ssl = False
|
self.skip_ssl = False
|
||||||
|
|
||||||
# me when no certificate and key file
|
# me when no certificate and key file
|
||||||
@@ -362,6 +386,8 @@ class WebServer:
|
|||||||
self.https_socket = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
|
self.https_socket = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
|
||||||
self.https_socket.bind(("::", self.https_port))
|
self.https_socket.bind(("::", self.https_port))
|
||||||
|
|
||||||
|
self.proxy_handler = ProxyServer(self.file_handler)
|
||||||
|
|
||||||
if self.skip_ssl is False:
|
if self.skip_ssl is False:
|
||||||
# https gets the ssl treatment!! yaaaay :3
|
# https gets the ssl treatment!! yaaaay :3
|
||||||
self.ssl_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
|
self.ssl_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
|
||||||
@@ -438,7 +464,7 @@ class WebServer:
|
|||||||
|
|
||||||
def handle_connection(self, conn, addr):
|
def handle_connection(self, conn, addr):
|
||||||
try:
|
try:
|
||||||
data = conn.recv(512)
|
data = conn.recv(32768)
|
||||||
request = data.decode(errors="ignore")
|
request = data.decode(errors="ignore")
|
||||||
if not data:
|
if not data:
|
||||||
response = self.build_response(
|
response = self.build_response(
|
||||||
@@ -452,6 +478,7 @@ class WebServer:
|
|||||||
if isinstance(response, str):
|
if isinstance(response, str):
|
||||||
response = response.encode()
|
response = response.encode()
|
||||||
|
|
||||||
|
print(len(response))
|
||||||
conn.sendall(response)
|
conn.sendall(response)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error handling connection: {e}")
|
print(f"Error handling connection: {e}")
|
||||||
@@ -474,6 +501,9 @@ class WebServer:
|
|||||||
if "Host" in line:
|
if "Host" in line:
|
||||||
host = line.split(":", 1)[1].strip()
|
host = line.split(":", 1)[1].strip()
|
||||||
allowed = self.parser.host_parser(host)
|
allowed = self.parser.host_parser(host)
|
||||||
|
if allowed == "catchall":
|
||||||
|
host = "*"
|
||||||
|
allowed = True
|
||||||
if not allowed:
|
if not allowed:
|
||||||
return self.build_response(
|
return self.build_response(
|
||||||
403, "Connecting via this host is disallowed."
|
403, "Connecting via this host is disallowed."
|
||||||
@@ -485,7 +515,7 @@ class WebServer:
|
|||||||
for line in data.splitlines():
|
for line in data.splitlines():
|
||||||
if "User-Agent" in line:
|
if "User-Agent" in line:
|
||||||
ua = line.split(":", 1)[1].strip()
|
ua = line.split(":", 1)[1].strip()
|
||||||
allowed = self.parser.ua_is_allowed(ua)
|
allowed = self.parser.ua_is_allowed(ua, host)
|
||||||
if not allowed:
|
if not allowed:
|
||||||
return self.build_response(
|
return self.build_response(
|
||||||
403, "This UA has been blocked by the owner of this site."
|
403, "This UA has been blocked by the owner of this site."
|
||||||
@@ -495,31 +525,47 @@ class WebServer:
|
|||||||
return self.build_response(400, "You cannot connect without a User-Agent.")
|
return self.build_response(400, "You cannot connect without a User-Agent.")
|
||||||
|
|
||||||
if ":" in host:
|
if ":" in host:
|
||||||
host2 = host.rsplit(":", 1)[0]
|
host = host.rsplit(":", 1)[0]
|
||||||
else:
|
else:
|
||||||
host2 = host
|
host = host
|
||||||
|
|
||||||
method, path, version = self.parser.parse_request_line(request_line, host2)
|
method, path, version = self.parser.parse_request_line(request_line, host)
|
||||||
|
|
||||||
if not all([method, path, version]):
|
if not all([method, path, version]):
|
||||||
return self.build_response(400, "Bad Request")
|
return self.build_response(400, "Bad Request")
|
||||||
|
|
||||||
|
if self.file_handler.read_config("proxy", host) is not None:
|
||||||
|
orig_host = host
|
||||||
|
value = self.file_handler.read_config("proxy", host)
|
||||||
|
if ":" in value:
|
||||||
|
host = value.split(":")[0]
|
||||||
|
port = int(value.split(":")[1])
|
||||||
|
else:
|
||||||
|
host = value
|
||||||
|
port = 443
|
||||||
|
return self.proxy_handler.try_connection(
|
||||||
|
host,
|
||||||
|
port,
|
||||||
|
data.encode(),
|
||||||
|
orig_host,
|
||||||
|
)
|
||||||
|
|
||||||
# Figure out a better way to reload config
|
# Figure out a better way to reload config
|
||||||
if path == "/?pywebsrv_reload_conf=1":
|
if path == "/?pywebsrv_reload_conf=1":
|
||||||
print("Got reload command! Reloading configuration...")
|
print("Got reload command! Reloading configuration...")
|
||||||
self.file_handler = FileHandler()
|
self.file_handler = FileHandler()
|
||||||
self.parser = RequestParser()
|
self.parser = RequestParser()
|
||||||
return self.build_response(302, "", host=host2)
|
return self.build_response(302, "", host=host)
|
||||||
|
|
||||||
if not self.parser.is_method_allowed(method):
|
if not self.parser.is_method_allowed(method):
|
||||||
return self.build_response(405, self.http_405_html)
|
return self.build_response(405, self.http_405_html)
|
||||||
|
|
||||||
directory = (
|
directory = (
|
||||||
self.file_handler.read_new_config("directory", host2)
|
self.file_handler.read_config("directory", host)
|
||||||
or self.file_handler.base_dir
|
or self.file_handler.base_dir
|
||||||
)
|
)
|
||||||
|
|
||||||
if self.file_handler.read_new_config("apimode", host2) is True:
|
if self.file_handler.read_config("apimode", host) is True:
|
||||||
if not os.path.join(os.getcwd(), directory) in sys.path:
|
if not os.path.join(os.getcwd(), directory) in sys.path:
|
||||||
sys.path.append(f"{os.path.join(os.getcwd(), directory)}")
|
sys.path.append(f"{os.path.join(os.getcwd(), directory)}")
|
||||||
import api
|
import api
|
||||||
@@ -657,11 +703,11 @@ def main():
|
|||||||
input("Press <Enter> to continue. ")
|
input("Press <Enter> to continue. ")
|
||||||
file_handler = FileHandler()
|
file_handler = FileHandler()
|
||||||
file_handler.base_dir = file_handler.read_config("directory")
|
file_handler.base_dir = file_handler.read_config("directory")
|
||||||
http_port = file_handler.read_new_config("port") or 8080
|
http_port = file_handler.read_config("port") or 8080
|
||||||
https_port = file_handler.read_new_config("https-port") or 8443
|
https_port = file_handler.read_config("https-port") or 8443
|
||||||
http_enabled = bool(file_handler.read_new_config("http")) or True
|
http_enabled = bool(file_handler.read_config("http")) or True
|
||||||
print(http_enabled)
|
print(http_enabled)
|
||||||
https_enabled = bool(file_handler.read_new_config("https")) or False
|
https_enabled = bool(file_handler.read_config("https")) or False
|
||||||
print(https_enabled)
|
print(https_enabled)
|
||||||
server = WebServer(http_port=http_port, https_port=https_port)
|
server = WebServer(http_port=http_port, https_port=https_port)
|
||||||
server.start(http_enabled, https_enabled)
|
server.start(http_enabled, https_enabled)
|
||||||
+1
-1
@@ -8,7 +8,7 @@
|
|||||||
<h1>Hello from Amethyst!</h1>
|
<h1>Hello from Amethyst!</h1>
|
||||||
<h2>This page confirms Amethyst can read files from your PC or server and serve them to your browser!</h2>
|
<h2>This page confirms Amethyst can read files from your PC or server and serve them to your browser!</h2>
|
||||||
<p>This is a test page, if you aren't the server owner, they might not have finished setting up their site, be patient. If this doesn't go away after a while, tell them they've made an oopsie</p>
|
<p>This is a test page, if you aren't the server owner, they might not have finished setting up their site, be patient. If this doesn't go away after a while, tell them they've made an oopsie</p>
|
||||||
<p>This server runs Amethyst Pre-Rel Build 0053</p>
|
<p>This server runs Amethyst Pre-Rel 0.2.0-0072</p>
|
||||||
</center>
|
</center>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
# WARNING: This is an alpha spec of NSCL 2.0!!
|
|
||||||
|
|
||||||
host 192.168.2.196 {
|
|
||||||
directory:/home/nova/Downloads/test/html
|
|
||||||
allowed-methods:GET
|
|
||||||
block-ua:match("Discordbot"),match("Google")
|
|
||||||
}
|
|
||||||
|
|
||||||
host localhost {
|
|
||||||
directory:/home/nova/PyWebServer/html2
|
|
||||||
allowed-methods:GET,PUT
|
|
||||||
block-ip:10.1.100.2
|
|
||||||
apimode:0
|
|
||||||
block-ua:match("Discordbot")
|
|
||||||
}
|
|
||||||
|
|
||||||
host 192.168.1.213 {
|
|
||||||
directory:/home/nova/PyWebServer/html
|
|
||||||
allowed-methods:GET,PUT
|
|
||||||
block-ip:10.1.100.2
|
|
||||||
block-ua:match("Discordbot")
|
|
||||||
}
|
|
||||||
|
|
||||||
globals {
|
|
||||||
http:1
|
|
||||||
https:1
|
|
||||||
port:8080
|
|
||||||
https-port:8443
|
|
||||||
allow-localhost:1
|
|
||||||
key:/home/nova/PyWebServer/ssl/key.pem
|
|
||||||
cert:/home/nova/PyWebServer/ssl/cert.pem
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
# Using NSCL 1.3
|
|
||||||
# Port defenition. What ports to use.
|
|
||||||
# port is the HTTP port, port-https is the HTTPS port
|
|
||||||
port:8080
|
|
||||||
port-https:8443
|
|
||||||
# Here you choose what directory PyWebServer looks in for files.
|
|
||||||
directory:/home/nova/PyWebServer/html
|
|
||||||
# Host defenition, what hosts you can connect via.
|
|
||||||
# You can use FQDNs, IP-addresses and localhost,
|
|
||||||
# Support for multiple hosts is coming.
|
|
||||||
host:localhost,10.185.213.118
|
|
||||||
# Enables HTTP support. (Only enables/disables the HTTP port.)
|
|
||||||
http:1
|
|
||||||
# Enables HTTPS support. (Only enables/disables the HTTPS port.)
|
|
||||||
https:1
|
|
||||||
# Allows the use of localhost to connect.
|
|
||||||
# The default is on, this is seperate of the host defenition.
|
|
||||||
allow-localhost:1
|
|
||||||
# If you're using the webserver in a library form,
|
|
||||||
# you can disable the AutoCertGen and never trigger it.
|
|
||||||
disable-autocertgen:0
|
|
||||||
# If you wish to block IP-addresses, this function is coming though.
|
|
||||||
# block-ip:0.0.0.0,1.1.1.1,2.2.2.2
|
|
||||||
# If you wish to block User-Agents.
|
|
||||||
block-ua:match(Discordbot),match(google)
|
|
||||||
|
|
||||||
# TEST: experimental non-defined keys go here:
|
|
||||||
# keyfile key
|
|
||||||
key-file:/home/nova/PyWebServer/key.pem
|
|
||||||
# certfile keys
|
|
||||||
cert-file:/home/nova/PyWebServer/cert.pem
|
|
||||||
# allowed-methods, csv's
|
|
||||||
allowed-methods:GET
|
|
||||||
Reference in New Issue
Block a user