#wip: Socker HTTP Server Driver.
This commit is contained in:
parent
711e347346
commit
fef6627c83
22
Dockers/Dockerfile.sass.gemini
Normal file
22
Dockers/Dockerfile.sass.gemini
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# Usamos la imagen oficial de Dart Sass basada en Alpine
|
||||||
|
FROM dart:stable AS build
|
||||||
|
|
||||||
|
# Descargamos e instalamos la última versión de Dart Sass
|
||||||
|
RUN apt-get update && apt-get install -y curl tar
|
||||||
|
RUN curl -L https://github.com/sass/dart-sass/releases/download/1.101.0/dart-sass-1.101.0-linux-x64.tar.gz | tar -xzf - -C /opt
|
||||||
|
|
||||||
|
# Imagen final limpia y ligera
|
||||||
|
FROM alpine:latest
|
||||||
|
RUN apk add --no-cache libc6-compat libstdc++
|
||||||
|
|
||||||
|
# Copiamos los binarios desde la etapa anterior
|
||||||
|
COPY --from=build /opt/dart-sass /opt/dart-sass
|
||||||
|
|
||||||
|
# Añadimos SASS al PATH del contenedor
|
||||||
|
ENV PATH="/opt/dart-sass:${PATH}"
|
||||||
|
|
||||||
|
# Configuramos el directorio de trabajo
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
# Permitimos que reciba los comandos directamente
|
||||||
|
ENTRYPOINT ["sass"]
|
||||||
@ -67,6 +67,136 @@
|
|||||||
"default_routes_files" : "/JSON/AnP.routes.json",
|
"default_routes_files" : "/JSON/AnP.routes.json",
|
||||||
"AnP_RoutesManager_end" : null,
|
"AnP_RoutesManager_end" : null,
|
||||||
|
|
||||||
|
"AnP_HTTPAbstracts_start" : null,
|
||||||
|
"default_http_messages" : {
|
||||||
|
"100" : "Continue",
|
||||||
|
"101" : "Switching Protocols",
|
||||||
|
"102" : "Processing",
|
||||||
|
"103" : "Early Hints",
|
||||||
|
"200" : "OK",
|
||||||
|
"201" : "Created",
|
||||||
|
"202" : "Accepted",
|
||||||
|
"203" : "Non-Authoritative Information",
|
||||||
|
"204" : "No Content",
|
||||||
|
"205" : "Reset Content",
|
||||||
|
"206" : "Partial Content",
|
||||||
|
"207" : "Multi-Status",
|
||||||
|
"208" : "Already Reported",
|
||||||
|
"226" : "IM Used",
|
||||||
|
"300" : "Multiple Choices",
|
||||||
|
"301" : "Moved Permanently",
|
||||||
|
"302" : "Found",
|
||||||
|
"303" : "See Other",
|
||||||
|
"304" : "Not Modified",
|
||||||
|
"305" : "Use Proxy",
|
||||||
|
"306" : "Switch Proxy",
|
||||||
|
"307" : "Temporary Redirect",
|
||||||
|
"308" : "Permanent Redirect",
|
||||||
|
"400" : "Bad Request",
|
||||||
|
"401" : "Unauthorized",
|
||||||
|
"402" : "Payment Required",
|
||||||
|
"403" : "Forbidden",
|
||||||
|
"404" : "Not Found",
|
||||||
|
"405" : "Method Not Allowed",
|
||||||
|
"406" : "Not Acceptable",
|
||||||
|
"407" : "Proxy Authentication Required",
|
||||||
|
"408" : "Request Timeout",
|
||||||
|
"409" : "Conflict",
|
||||||
|
"410" : "Gone",
|
||||||
|
"411" : "Length Required",
|
||||||
|
"412" : "Precondition Failed",
|
||||||
|
"413" : "Payload Too Large",
|
||||||
|
"414" : "URI Too Long",
|
||||||
|
"415" : "Unsupported Media Type",
|
||||||
|
"416" : "Range Not Satisfiable",
|
||||||
|
"417" : "Expectation Failed",
|
||||||
|
"418" : "I'm a teapot",
|
||||||
|
"421" : "Misdirected Request",
|
||||||
|
"422" : "Unprocessable Content",
|
||||||
|
"423" : "Locked",
|
||||||
|
"424" : "Failed Dependency",
|
||||||
|
"425" : "Too Early",
|
||||||
|
"426" : "Upgrade Required",
|
||||||
|
"428" : "Precondition Required",
|
||||||
|
"429" : "Too Many Requests",
|
||||||
|
"431" : "Request Header Fields Too Large",
|
||||||
|
"451" : "Unavailable For Legal Reasons",
|
||||||
|
"500" : "Internal Server Error",
|
||||||
|
"501" : "Not Implemented",
|
||||||
|
"502" : "Bad Gateway",
|
||||||
|
"503" : "Service Unavailable",
|
||||||
|
"504" : "Gateway Timeout",
|
||||||
|
"505" : "HTTP Version Not Supported",
|
||||||
|
"506" : "Variant Also Negotiates",
|
||||||
|
"507" : "Insufficient Storage",
|
||||||
|
"508" : "Loop Detected",
|
||||||
|
"510" : "Not Extended",
|
||||||
|
"511" : "Network Authentication Required",
|
||||||
|
"218" : "This is fine",
|
||||||
|
"419" : "Page Expired",
|
||||||
|
"420" : "Method Failure",
|
||||||
|
"430" : "Request Header Fields Too Large",
|
||||||
|
"450" : "Blocked by Windows Parental Controls",
|
||||||
|
"498" : "Invalid Token",
|
||||||
|
"499" : "Token Required",
|
||||||
|
"509" : "Bandwidth Limit Exceeded",
|
||||||
|
"529" : "Site is overloaded",
|
||||||
|
"530" : "Site is frozen",
|
||||||
|
"540" : "Temporarily Disabled",
|
||||||
|
"598" : "Network read timeout error",
|
||||||
|
"599" : "Network Connect Timeout Error",
|
||||||
|
"783" : "Unexpected Token",
|
||||||
|
"440" : "Login Time-out",
|
||||||
|
"449" : "Retry With",
|
||||||
|
"444" : "No Response",
|
||||||
|
"494" : "Request header too large",
|
||||||
|
"495" : "SSL Certificate Error",
|
||||||
|
"496" : "SSL Certificate Required",
|
||||||
|
"497" : "HTTP Request Sent to HTTPS Port",
|
||||||
|
"520" : "Web Server Returned an Unknown Error",
|
||||||
|
"521" : "Web Server Is Down",
|
||||||
|
"522" : "Connection Timed Out",
|
||||||
|
"523" : "Origin Is Unreachable",
|
||||||
|
"524" : "A Timeout Occurred",
|
||||||
|
"525" : "SSL Handshake Failed",
|
||||||
|
"526" : "Invalid SSL Certificate",
|
||||||
|
"527" : "Railgun Error",
|
||||||
|
"561" : "Unauthorized",
|
||||||
|
"110" : "Response is Stale",
|
||||||
|
"111" : "Revalidation Failed",
|
||||||
|
"112" : "Disconnected Operation",
|
||||||
|
"113" : "Heuristic Expiration",
|
||||||
|
"199" : "Miscellaneous Warning",
|
||||||
|
"214" : "Transformation Applied",
|
||||||
|
"299" : "Miscellaneous Persistent Warning"
|
||||||
|
},
|
||||||
|
"protocol" : "HTTP",
|
||||||
|
"protocol_version" : "1.1",
|
||||||
|
"default_protocol_code" : 200,
|
||||||
|
"http_server_name" : "AnP",
|
||||||
|
"http_server_version" : "0.0.1",
|
||||||
|
"default_cors" : "*",
|
||||||
|
"http_access_control_maximum_age" : 84600,
|
||||||
|
"http_keep_alive_timeout" : 5,
|
||||||
|
"http_keep_alive_maximum" : 100,
|
||||||
|
"default_http_charset" : "UTF-8",
|
||||||
|
"default_http_mime" : "text/html",
|
||||||
|
"http_accept_range" : "bytes",
|
||||||
|
"http_response_header" : [
|
||||||
|
"{protocol}/{protocol_version} {protocol_code} {protocol_message}",
|
||||||
|
"Date: {date}",
|
||||||
|
"Server: {server}/{server_version}",
|
||||||
|
"Last-Modified: {last_modified} ",
|
||||||
|
"Accept-Ranges: {accept_range}",
|
||||||
|
"Content-Length: {response_length}",
|
||||||
|
"Access-Control-Max-Age: {access_control_max_age}",
|
||||||
|
"Keep-Alive: timeout={keep_alive_timeout}, max={keep_alive_maximum}",
|
||||||
|
"Access-Control-Allow-Origin: {cors}",
|
||||||
|
"Connection: Keep-Alive",
|
||||||
|
"Content-type: {mime}; charset={charset}"
|
||||||
|
],
|
||||||
|
"AnP_HTTPAbstracts_end" : null,
|
||||||
|
|
||||||
"AnP_WebSocketsServersManager_start" : null,
|
"AnP_WebSocketsServersManager_start" : null,
|
||||||
"default_web_sockets_servers" : {
|
"default_web_sockets_servers" : {
|
||||||
"anp" : {
|
"anp" : {
|
||||||
@ -80,7 +210,8 @@
|
|||||||
"AnP_HTTPServersManager_start" : null,
|
"AnP_HTTPServersManager_start" : null,
|
||||||
"default_http_servers" : {
|
"default_http_servers" : {
|
||||||
"anp" : {
|
"anp" : {
|
||||||
"type" : "HTTPDriver",
|
"type2" : "HTTPServerDriver",
|
||||||
|
"type" : "HTTPSocketServerDriver",
|
||||||
"host" : "",
|
"host" : "",
|
||||||
"port" : 18000
|
"port" : 18000
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from typing import Any, Self, Optional, Sequence
|
from typing import Any, Self, Optional, Sequence
|
||||||
from re import Match as REMath
|
from re import Match as REMath
|
||||||
|
import datetime
|
||||||
from Interfaces.Application.AnPInterface import AnPInterface
|
from Interfaces.Application.AnPInterface import AnPInterface
|
||||||
from Utils.Common import Common
|
from Utils.Common import Common
|
||||||
|
|
||||||
@ -14,18 +15,37 @@ class HTTPServersAbstract(ABC):
|
|||||||
|
|
||||||
def __init__(self:Self, anp:AnPInterface, key:str, inputs:Optional[dict[str, Any|None]|Sequence[Any|None]] = None) -> None:
|
def __init__(self:Self, anp:AnPInterface, key:str, inputs:Optional[dict[str, Any|None]|Sequence[Any|None]] = None) -> None:
|
||||||
self.anp:AnPInterface = anp
|
self.anp:AnPInterface = anp
|
||||||
self.__inputs:dict[str, Any|None] = Common.get_dictionary(inputs)
|
self._inputs:dict[str, Any|None] = Common.get_dictionary(inputs)
|
||||||
self.host:str = self.DEFAULT_PORT
|
self.host:str = self.DEFAULT_HOST
|
||||||
self.port:int = self.DEFAULT_HOST
|
self.port:int = self.DEFAULT_PORT
|
||||||
self._print_data:dict[str, Any|None] = {
|
self._print_data:dict[str, Any|None] = {
|
||||||
"port": self.port,
|
"port": self.port,
|
||||||
"host": self.host
|
"host": self.host
|
||||||
}
|
}
|
||||||
|
self.http_messages:dict[int, str] = {int(code): message for code, message in anp.settings.get((
|
||||||
|
"default_http_messages", "http_messages"
|
||||||
|
), inputs).items()}
|
||||||
|
self.protocol:str = anp.settings.get(("http_protocol", "protocol"), inputs, "HTTP")
|
||||||
|
self.protocol_version:str = anp.settings.get(("http_protocol_version", "protocol_version"), inputs, "1.1")
|
||||||
|
self.accept_range:str = anp.settings.get(("http_accept_range", "accept_range"), inputs, "bytes")
|
||||||
|
self.access_control_max_age:int = anp.settings.get(("http_access_control_max_age", "access_control_max_age"), inputs, 84600)
|
||||||
|
self.keep_alive_maximum:int = anp.settings.get(("http_keep_alive_maximum", "keep_alive_maximum"), inputs, 100)
|
||||||
|
self.keep_alive_timeout:int = anp.settings.get(("http_keep_alive_timeout", "keep_alive_timeout"), inputs, 5)
|
||||||
|
self.cors:str = anp.settings.get(("http_cors", "cors"), inputs, "*")
|
||||||
|
self.mime:str = anp.settings.get(("default_http_mime", "http_mime", "mime"), inputs, "text/html")
|
||||||
|
self.charset:str = anp.settings.get(("default_http_charset", "http_charset", "charset"), inputs, "UTF-8")
|
||||||
self._session_timeout:int = anp.settings.get(("sessions_timeout", "timeout"), inputs, 3600)
|
self._session_timeout:int = anp.settings.get(("sessions_timeout", "timeout"), inputs, 3600)
|
||||||
self.key:str = key
|
self.key:str = key
|
||||||
|
|
||||||
self.update()
|
self.update()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def format_datetime(datetime:datetime.datetime) -> str:
|
||||||
|
return datetime.strftime("%a, %d %b %Y %H:%M:%S GMT")
|
||||||
|
|
||||||
|
def get_http_message(self:Self, code:int) -> str:
|
||||||
|
return self.http_messages.get(code, "Unknown Status Code")
|
||||||
|
|
||||||
def __update_print_data(self:Self) -> None:
|
def __update_print_data(self:Self) -> None:
|
||||||
self._print_data["port"] = self.port
|
self._print_data["port"] = self.port
|
||||||
self._print_data["host"] = self.host
|
self._print_data["host"] = self.host
|
||||||
@ -40,8 +60,8 @@ class HTTPServersAbstract(ABC):
|
|||||||
|
|
||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
self.port = self.anp.settings.get(("http_server_port", "http_port", "port"), self.__inputs, self.DEFAULT_PORT)
|
self.port = self.anp.settings.get(("http_server_port", "http_port", "port"), self._inputs, self.DEFAULT_PORT)
|
||||||
self.host = self.anp.settings.get(("http_server_host", "http_host", "host"), self.__inputs, self.DEFAULT_HOST)
|
self.host = self.anp.settings.get(("http_server_host", "http_host", "host"), self._inputs, self.DEFAULT_HOST)
|
||||||
self.__update_print_data()
|
self.__update_print_data()
|
||||||
|
|
||||||
self.anp.settings.get(("http_server_autostart", "http_autostart", "autostart")) and self.start()
|
self.anp.settings.get(("http_server_autostart", "http_autostart", "autostart")) and self.start()
|
||||||
|
|||||||
@ -10,7 +10,7 @@ from http.server import BaseHTTPRequestHandler, HTTPServer
|
|||||||
from http.cookies import SimpleCookie
|
from http.cookies import SimpleCookie
|
||||||
from Abstracts.HTTPServersAbstract import HTTPServersAbstract
|
from Abstracts.HTTPServersAbstract import HTTPServersAbstract
|
||||||
|
|
||||||
class HTTPDriver(HTTPServersAbstract, ModelAbstract):
|
class HTTPServerDriver(HTTPServersAbstract, ModelAbstract):
|
||||||
|
|
||||||
class HTTPRequestHandler(BaseHTTPRequestHandler):
|
class HTTPRequestHandler(BaseHTTPRequestHandler):
|
||||||
|
|
||||||
193
Python/Drivers/HTTPSocketServerDriver.py
Normal file
193
Python/Drivers/HTTPSocketServerDriver.py
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from typing import Any, Optional, Self, Sequence
|
||||||
|
from threading import Thread
|
||||||
|
from socket import (
|
||||||
|
socket as Socket,
|
||||||
|
AF_INET as ADDRESS_FAMILY_IPV4,
|
||||||
|
SOCK_STREAM as SOCKET_STREAM,
|
||||||
|
SOL_SOCKET as SOCKET_LAYER,
|
||||||
|
SO_REUSEADDR as SOCKET_REUSE_ADDRESS
|
||||||
|
)
|
||||||
|
import datetime
|
||||||
|
from Interfaces.Application.AnPInterface import AnPInterface
|
||||||
|
from Abstracts.HTTPServersAbstract import HTTPServersAbstract
|
||||||
|
from Models.RequestModel import RequestModel
|
||||||
|
from Utils.Common import Common
|
||||||
|
from Utils.Checks import Check
|
||||||
|
from Utils.Patterns import RE
|
||||||
|
|
||||||
|
class HTTPSocketServerDriver(HTTPServersAbstract):
|
||||||
|
|
||||||
|
def __get(self:Self, keys:str|Sequence[str], default:Any|None = None) -> Any|None:
|
||||||
|
|
||||||
|
real_keys:list[str] = []
|
||||||
|
key:str
|
||||||
|
|
||||||
|
for key in Common.get_keys(keys):
|
||||||
|
|
||||||
|
header:str
|
||||||
|
|
||||||
|
for header in (
|
||||||
|
"http_socket_server_driver",
|
||||||
|
"http_server_driver",
|
||||||
|
"http_server",
|
||||||
|
"http",
|
||||||
|
""
|
||||||
|
):
|
||||||
|
|
||||||
|
final_key:str = (header + "_" if header else "") + key
|
||||||
|
|
||||||
|
if final_key not in keys:
|
||||||
|
real_keys.append(final_key)
|
||||||
|
|
||||||
|
return self.anp.settings.get(real_keys, self._inputs, default)
|
||||||
|
|
||||||
|
def __init__(self:Self,
|
||||||
|
anp:AnPInterface,
|
||||||
|
key:str,
|
||||||
|
inputs:Optional[dict[str, Any|None]|Sequence[Any|None]] = None
|
||||||
|
) -> None:
|
||||||
|
|
||||||
|
self.__server:Socket|None = None
|
||||||
|
self.__thread:Thread|None = None
|
||||||
|
self.__working:bool = False
|
||||||
|
super().__init__(anp, key, inputs)
|
||||||
|
self.__maximum_connections:int = self.__get("maximum_connections", 5)
|
||||||
|
self.__cache_size:int = self.__get("cache_size", 1024)
|
||||||
|
self.__response_header:str = self.__get("response_header")
|
||||||
|
|
||||||
|
def __listen(self:Self) -> None:
|
||||||
|
while self.__working:
|
||||||
|
try:
|
||||||
|
|
||||||
|
client:Socket
|
||||||
|
address:str
|
||||||
|
port:int
|
||||||
|
data:bytes = b""
|
||||||
|
header:str
|
||||||
|
body:str
|
||||||
|
header_lines:list[str]
|
||||||
|
line:str
|
||||||
|
request:RequestModel = RequestModel()
|
||||||
|
get_block:str
|
||||||
|
hash_block:str
|
||||||
|
response:bytes
|
||||||
|
response_body:bytes
|
||||||
|
|
||||||
|
client, (address, port) = self.__server.accept()
|
||||||
|
|
||||||
|
while True:
|
||||||
|
|
||||||
|
buffer:bytes = client.recv(self.__cache_size)
|
||||||
|
|
||||||
|
data += buffer
|
||||||
|
if len(buffer) < self.__cache_size:
|
||||||
|
break
|
||||||
|
|
||||||
|
header, body = RE.DOUBLE_NEW_LINE.split(data.decode("utf-8", errors = "ignore"), 1)
|
||||||
|
header_lines = RE.NEW_LINE.split(header)
|
||||||
|
(
|
||||||
|
request.method,
|
||||||
|
request.path,
|
||||||
|
get_block,
|
||||||
|
hash_block,
|
||||||
|
request.protocol,
|
||||||
|
request.protocol_version
|
||||||
|
) = RE.HTTP_REQUEST.match(header_lines[0]).groups()
|
||||||
|
|
||||||
|
for line in header_lines[1:]:
|
||||||
|
if RE.HTTP_HEADER_PARAMETER.match(line):
|
||||||
|
|
||||||
|
key:str
|
||||||
|
value:str
|
||||||
|
|
||||||
|
key, value = RE.HTTP_HEADER_PARAMETER.match(line).groups()
|
||||||
|
key = key.strip().lower()
|
||||||
|
value = value.strip()
|
||||||
|
if key in request.request_headers:
|
||||||
|
if Check.is_array(request.request_headers[key]):
|
||||||
|
request.request_headers[key].append(value)
|
||||||
|
else:
|
||||||
|
request.request_headers[key] = [request.request_headers[key], value]
|
||||||
|
else:
|
||||||
|
request.request_headers[key] = value
|
||||||
|
|
||||||
|
request.get_variables = self.get_variables_from(get_block)
|
||||||
|
request.post_variables = self.get_variables_from(body)
|
||||||
|
request.cookies = self.load_cookies(request.request_headers.get("cookie"))
|
||||||
|
request.hash_variables = self.get_variables_from(hash_block)
|
||||||
|
|
||||||
|
self.anp.routes.go([self.key], request.method, request.path, request)
|
||||||
|
|
||||||
|
response_body = (
|
||||||
|
request.response if Check.is_binary(request.response) else
|
||||||
|
request.response.encode() if Check.is_string(request.response) else
|
||||||
|
str(request.response).encode())
|
||||||
|
response = Common.string_variables(self.__response_header, {
|
||||||
|
"content_length" : len(response_body),
|
||||||
|
"protocol" : request.get("protocol", request.protocol or self.protocol),
|
||||||
|
"protocol_version" : request.get("protocol_version", request.protocol_version or self.protocol_version),
|
||||||
|
"http_code" : request.response_code,
|
||||||
|
"http_message" : self.get_http_message(request.response_code),
|
||||||
|
"date" : self.format_datetime(datetime.datetime.now(datetime.timezone.utc)),
|
||||||
|
"last_modified" : self.format_datetime(request.last_modified or request.get("last_modified") or datetime.datetime.now(datetime.timezone.utc)),
|
||||||
|
"accept_range" : request.get("accept_range", self.accept_range),
|
||||||
|
"response_length" : len(response_body),
|
||||||
|
"access_control_max_age" : request.get("access_control_max_age", self.access_control_max_age),
|
||||||
|
"keep_alive_maximum" : request.get("keep_alive_maximum", self.keep_alive_maximum),
|
||||||
|
"keep_alive_timeout" : request.get("keep_alive_timeout", self.keep_alive_timeout),
|
||||||
|
"cors" : request.get("cors", self.cors),
|
||||||
|
"mime" : request.response_mime or request.get("mime", self.mime),
|
||||||
|
"charset" : request.response_charset or request.get("charset", self.charset)
|
||||||
|
}).encode() + response_body
|
||||||
|
|
||||||
|
client.sendall(response)
|
||||||
|
client.close()
|
||||||
|
|
||||||
|
except Exception as exception:
|
||||||
|
self.anp.exception(exception, "anp_http_socket_server_driver_run_exception", {
|
||||||
|
"key" : self.key,
|
||||||
|
"host" : self.host,
|
||||||
|
"port" : self.port
|
||||||
|
})
|
||||||
|
|
||||||
|
def start(self:Self) -> None:
|
||||||
|
|
||||||
|
self.__working = True
|
||||||
|
self.__server = Socket(ADDRESS_FAMILY_IPV4, SOCKET_STREAM)
|
||||||
|
|
||||||
|
try:
|
||||||
|
|
||||||
|
self.__server.setsockopt(SOCKET_LAYER, SOCKET_REUSE_ADDRESS, 1)
|
||||||
|
self.__server.bind((self.host, self.port))
|
||||||
|
self.__server.listen(self.__maximum_connections)
|
||||||
|
|
||||||
|
self.__thread = Thread(target = self.__listen)
|
||||||
|
self.__thread.start()
|
||||||
|
|
||||||
|
except Exception as exception:
|
||||||
|
self.anp.exception(exception, "anp_http_socket_server_driver_start_exception", {
|
||||||
|
"key" : self.key,
|
||||||
|
"host" : self.host,
|
||||||
|
"port" : self.port
|
||||||
|
})
|
||||||
|
|
||||||
|
def close(self:Self) -> None:
|
||||||
|
|
||||||
|
self.__working = False
|
||||||
|
|
||||||
|
if self.__server:
|
||||||
|
try:
|
||||||
|
self.__server.close()
|
||||||
|
except Exception as _:
|
||||||
|
pass
|
||||||
|
self.__server = None
|
||||||
|
|
||||||
|
if self.__thread:
|
||||||
|
try:
|
||||||
|
self.__thread.join()
|
||||||
|
except Exception as _:
|
||||||
|
pass
|
||||||
|
self.__thread = None
|
||||||
@ -13,6 +13,7 @@ class RequestModel:
|
|||||||
self.post_variables:dict[str, Any|None] = {}
|
self.post_variables:dict[str, Any|None] = {}
|
||||||
self.get_variables:dict[str, Any|None] = {}
|
self.get_variables:dict[str, Any|None] = {}
|
||||||
self.url_variables:dict[str, Any|None] = {}
|
self.url_variables:dict[str, Any|None] = {}
|
||||||
|
self.hash_variables:dict[str, Any|None] = {}
|
||||||
self.cookies:dict[str, Any|None] = {}
|
self.cookies:dict[str, Any|None] = {}
|
||||||
self.variables:dict[str, Any|None] = {}
|
self.variables:dict[str, Any|None] = {}
|
||||||
self.request_headers:dict[str, Any|None] = {}
|
self.request_headers:dict[str, Any|None] = {}
|
||||||
@ -20,11 +21,15 @@ class RequestModel:
|
|||||||
self.route:RouteAbstract|None = None
|
self.route:RouteAbstract|None = None
|
||||||
self.response:str|bytes|None = None
|
self.response:str|bytes|None = None
|
||||||
self.response_mime:str|None = None
|
self.response_mime:str|None = None
|
||||||
|
self.response_charset:str|None = None
|
||||||
self.response_code:int = 0
|
self.response_code:int = 0
|
||||||
self.response_headers:dict[str, Any|None] = {}
|
self.response_headers:dict[str, Any|None] = {}
|
||||||
self.callback:Callable[[RequestModel, str|bytes|None], None]|None = None
|
self.callback:Callable[[RequestModel, str|bytes|None], None]|None = None
|
||||||
self.data:Any|None = None
|
self.data:Any|None = None
|
||||||
self.session:SessionModel|None = session
|
self.session:SessionModel|None = session
|
||||||
|
self.protocol:str|None = None
|
||||||
|
self.protocol_version:str|None = None
|
||||||
|
self.last_modified:str|None = None
|
||||||
|
|
||||||
def get(self:Self, key:str|Sequence[str], default:Optional[Any] = None) -> Any|None:
|
def get(self:Self, key:str|Sequence[str], default:Optional[Any] = None) -> Any|None:
|
||||||
if self.session is not None:
|
if self.session is not None:
|
||||||
@ -34,7 +39,13 @@ class RequestModel:
|
|||||||
if results is not None:
|
if results is not None:
|
||||||
return results
|
return results
|
||||||
return Common.get_value(key, (
|
return Common.get_value(key, (
|
||||||
self.cookies, self.url_variables, self.get_variables, self.post_variables, self.variables
|
self.cookies,
|
||||||
|
self.url_variables,
|
||||||
|
self.get_variables,
|
||||||
|
self.post_variables,
|
||||||
|
self.variables,
|
||||||
|
self.request_headers,
|
||||||
|
self.hash_variables,
|
||||||
), default)
|
), default)
|
||||||
|
|
||||||
def set_variables(self:Self, inputs:dict[str, Any|None], on:Optional[str] = None) -> None:
|
def set_variables(self:Self, inputs:dict[str, Any|None], on:Optional[str] = None) -> None:
|
||||||
@ -43,6 +54,7 @@ class RequestModel:
|
|||||||
self.url_variables if on == "url" else
|
self.url_variables if on == "url" else
|
||||||
self.get_variables if on == "get" else
|
self.get_variables if on == "get" else
|
||||||
self.post_variables if on == "post" else
|
self.post_variables if on == "post" else
|
||||||
|
self.hash_variables if on == "hash" else
|
||||||
self.variables).update(Common.get_dictionary(Common.load_json(inputs)))
|
self.variables).update(Common.get_dictionary(Common.load_json(inputs)))
|
||||||
|
|
||||||
def set_response(self:Self, data:Any|None) -> None:
|
def set_response(self:Self, data:Any|None) -> None:
|
||||||
|
|||||||
@ -16,3 +16,6 @@ class RE:
|
|||||||
NEW_LINE:REPattern = re_compile(r'\r\n|[\r\n]')
|
NEW_LINE:REPattern = re_compile(r'\r\n|[\r\n]')
|
||||||
HTTP_VARIABLE:REPattern = re_compile(r'([^=&]+)=([^&]*)')
|
HTTP_VARIABLE:REPattern = re_compile(r'([^=&]+)=([^&]*)')
|
||||||
PARENT_PATH:REPattern = re_compile(r'^(.*)[\/\\][^\/\\]+[\/\\]?$')
|
PARENT_PATH:REPattern = re_compile(r'^(.*)[\/\\][^\/\\]+[\/\\]?$')
|
||||||
|
DOUBLE_NEW_LINE:REPattern = re_compile(r'(?:\r\n){2}|\r{2}|\n{2}')
|
||||||
|
HTTP_HEADER_PARAMETER:REPattern = re_compile(r'([^:]+):\s*(.+)')
|
||||||
|
HTTP_REQUEST:REPattern = re_compile(r'^([^\s]+)\s([^\s\?\#]+)(?:\?([^#]+))?(?:\#([^\s]+))?\s([^\/]+)\/([0-9\.]+)$')
|
||||||
@ -5,7 +5,8 @@ from typing import Any
|
|||||||
from Application.AnP import AnP
|
from Application.AnP import AnP
|
||||||
from Controllers.AIController import AIController
|
from Controllers.AIController import AIController
|
||||||
from Drivers.WebSocketServerDriver import WebSocketServerDriver
|
from Drivers.WebSocketServerDriver import WebSocketServerDriver
|
||||||
from Drivers.HTTPDriver import HTTPDriver
|
from Drivers.HTTPSocketServerDriver import HTTPSocketServerDriver
|
||||||
|
from Drivers.HTTPServerDriver import HTTPServerDriver
|
||||||
from Drivers.OllamaDriver import OllamaDriver
|
from Drivers.OllamaDriver import OllamaDriver
|
||||||
from Drivers.FilesDriver import FilesDriver
|
from Drivers.FilesDriver import FilesDriver
|
||||||
|
|
||||||
@ -13,7 +14,8 @@ inputs:dict[str, dict[str, Any|None]] = {
|
|||||||
"default_models" : {
|
"default_models" : {
|
||||||
"AIController" : AIController,
|
"AIController" : AIController,
|
||||||
"WebSocketServerDriver" : WebSocketServerDriver,
|
"WebSocketServerDriver" : WebSocketServerDriver,
|
||||||
"HTTPDriver" : HTTPDriver,
|
"HTTPSocketServerDriver" : HTTPSocketServerDriver,
|
||||||
|
"HTTPServerDriver" : HTTPServerDriver,
|
||||||
"OllamaDriver" : OllamaDriver,
|
"OllamaDriver" : OllamaDriver,
|
||||||
"FilesDriver" : FilesDriver
|
"FilesDriver" : FilesDriver
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
directory=`dirname $(readlink -f "$0")`
|
directory=`dirname $(readlink -f "$0")`
|
||||||
sass $directory/../Public/scss/AnP.scss ../Public/scss/AnP.css;
|
# sass $directory/../Public/scss/AnP.scss $directory/../Public/scss/AnP.css
|
||||||
|
docker build -t dirt-sass -f $directory/../Dockers/Dockerfile.sass.gemini $directory
|
||||||
|
cd $directory/../Public/scss
|
||||||
|
docker run -it --rm -v $(pwd):$(pwd) -w $(pwd) dirt-sass AnP.scss AnP.css;
|
||||||
|
cd $directory
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user