Commit 28a10bc3 authored by Давид Ли's avatar Давид Ли

init

parents
File added
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="jdk" jdkName="Python 3.11" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
\ No newline at end of file
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="PyPackageRequirementsInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ignoredPackages">
<value>
<list size="189">
<item index="0" class="java.lang.String" itemvalue="aiohttp" />
<item index="1" class="java.lang.String" itemvalue="nodeenv" />
<item index="2" class="java.lang.String" itemvalue="identify" />
<item index="3" class="java.lang.String" itemvalue="pre-commit" />
<item index="4" class="java.lang.String" itemvalue="setuptools" />
<item index="5" class="java.lang.String" itemvalue="packaging" />
<item index="6" class="java.lang.String" itemvalue="toml" />
<item index="7" class="java.lang.String" itemvalue="zeep" />
<item index="8" class="java.lang.String" itemvalue="attrs" />
<item index="9" class="java.lang.String" itemvalue="pyyaml" />
<item index="10" class="java.lang.String" itemvalue="filelock" />
<item index="11" class="java.lang.String" itemvalue="platformdirs" />
<item index="12" class="java.lang.String" itemvalue="certifi" />
<item index="13" class="java.lang.String" itemvalue="virtualenv" />
<item index="14" class="java.lang.String" itemvalue="multidict" />
<item index="15" class="java.lang.String" itemvalue="distlib" />
<item index="16" class="java.lang.String" itemvalue="lxml" />
<item index="17" class="java.lang.String" itemvalue="yarl" />
<item index="18" class="java.lang.String" itemvalue="urllib3" />
<item index="19" class="java.lang.String" itemvalue="pytz" />
<item index="20" class="java.lang.String" itemvalue="cfgv" />
<item index="21" class="java.lang.String" itemvalue="httpcore" />
<item index="22" class="java.lang.String" itemvalue="zope-event" />
<item index="23" class="java.lang.String" itemvalue="greenlet" />
<item index="24" class="java.lang.String" itemvalue="zope-interface" />
<item index="25" class="java.lang.String" itemvalue="ruamel-yaml" />
<item index="26" class="java.lang.String" itemvalue="gevent" />
<item index="27" class="java.lang.String" itemvalue="ruamel-yaml-clib" />
<item index="28" class="java.lang.String" itemvalue="remote-procedure" />
<item index="29" class="java.lang.String" itemvalue="django-healthchecks" />
<item index="30" class="java.lang.String" itemvalue="PyYAML" />
<item index="31" class="java.lang.String" itemvalue="defusedxml" />
<item index="32" class="java.lang.String" itemvalue="django-nested-admin" />
<item index="33" class="java.lang.String" itemvalue="pycparser" />
<item index="34" class="java.lang.String" itemvalue="redis" />
<item index="35" class="java.lang.String" itemvalue="coreschema" />
<item index="36" class="java.lang.String" itemvalue="pyasn1-modules" />
<item index="37" class="java.lang.String" itemvalue="django-behaviors" />
<item index="38" class="java.lang.String" itemvalue="sentry-sdk" />
<item index="39" class="java.lang.String" itemvalue="shadiakiki1986-python-ntlm3" />
<item index="40" class="java.lang.String" itemvalue="jsonschema" />
<item index="41" class="java.lang.String" itemvalue="xlrd" />
<item index="42" class="java.lang.String" itemvalue="asgiref" />
<item index="43" class="java.lang.String" itemvalue="reportlab" />
<item index="44" class="java.lang.String" itemvalue="gunicorn" />
<item index="45" class="java.lang.String" itemvalue="click" />
<item index="46" class="java.lang.String" itemvalue="boto3" />
<item index="47" class="java.lang.String" itemvalue="drf-jwt" />
<item index="48" class="java.lang.String" itemvalue="humanize" />
<item index="49" class="java.lang.String" itemvalue="msgpack" />
<item index="50" class="java.lang.String" itemvalue="idna" />
<item index="51" class="java.lang.String" itemvalue="PyJWT" />
<item index="52" class="java.lang.String" itemvalue="rsa" />
<item index="53" class="java.lang.String" itemvalue="django-environ" />
<item index="54" class="java.lang.String" itemvalue="python-crontab" />
<item index="55" class="java.lang.String" itemvalue="cffi" />
<item index="56" class="java.lang.String" itemvalue="djangorestframework-camel-case" />
<item index="57" class="java.lang.String" itemvalue="google-cloud-storage" />
<item index="58" class="java.lang.String" itemvalue="django-storages" />
<item index="59" class="java.lang.String" itemvalue="pyasn1" />
<item index="60" class="java.lang.String" itemvalue="requests" />
<item index="61" class="java.lang.String" itemvalue="drf-yasg" />
<item index="62" class="java.lang.String" itemvalue="pyrsistent" />
<item index="63" class="java.lang.String" itemvalue="celery" />
<item index="64" class="java.lang.String" itemvalue="ruamel.yaml.clib" />
<item index="65" class="java.lang.String" itemvalue="grpcio-status" />
<item index="66" class="java.lang.String" itemvalue="prompt-toolkit" />
<item index="67" class="java.lang.String" itemvalue="djangorestframework" />
<item index="68" class="java.lang.String" itemvalue="django-cors-headers" />
<item index="69" class="java.lang.String" itemvalue="uritemplate" />
<item index="70" class="java.lang.String" itemvalue="drf-recaptcha" />
<item index="71" class="java.lang.String" itemvalue="tornado" />
<item index="72" class="java.lang.String" itemvalue="botocore" />
<item index="73" class="java.lang.String" itemvalue="django-celery-results" />
<item index="74" class="java.lang.String" itemvalue="phonenumbers" />
<item index="75" class="java.lang.String" itemvalue="amqp" />
<item index="76" class="java.lang.String" itemvalue="et-xmlfile" />
<item index="77" class="java.lang.String" itemvalue="flower" />
<item index="78" class="java.lang.String" itemvalue="python-monkey-business" />
<item index="79" class="java.lang.String" itemvalue="Django" />
<item index="80" class="java.lang.String" itemvalue="django-axes" />
<item index="81" class="java.lang.String" itemvalue="cachetools" />
<item index="82" class="java.lang.String" itemvalue="itypes" />
<item index="83" class="java.lang.String" itemvalue="google-api-python-client" />
<item index="84" class="java.lang.String" itemvalue="click-repl" />
<item index="85" class="java.lang.String" itemvalue="inflection" />
<item index="86" class="java.lang.String" itemvalue="Pillow" />
<item index="87" class="java.lang.String" itemvalue="protobuf" />
<item index="88" class="java.lang.String" itemvalue="googleapis-common-protos" />
<item index="89" class="java.lang.String" itemvalue="django-split-settings" />
<item index="90" class="java.lang.String" itemvalue="python-dateutil" />
<item index="91" class="java.lang.String" itemvalue="psycopg2-binary" />
<item index="92" class="java.lang.String" itemvalue="kombu" />
<item index="93" class="java.lang.String" itemvalue="MarkupSafe" />
<item index="94" class="java.lang.String" itemvalue="drf-spectacular" />
<item index="95" class="java.lang.String" itemvalue="pyparsing" />
<item index="96" class="java.lang.String" itemvalue="vine" />
<item index="97" class="java.lang.String" itemvalue="google-api-core" />
<item index="98" class="java.lang.String" itemvalue="django-celery-beat" />
<item index="99" class="java.lang.String" itemvalue="google-crc32c" />
<item index="100" class="java.lang.String" itemvalue="tablib" />
<item index="101" class="java.lang.String" itemvalue="django-import-export" />
<item index="102" class="java.lang.String" itemvalue="cryptography" />
<item index="103" class="java.lang.String" itemvalue="zope.interface" />
<item index="104" class="java.lang.String" itemvalue="whitenoise" />
<item index="105" class="java.lang.String" itemvalue="bcrypt" />
<item index="106" class="java.lang.String" itemvalue="odfpy" />
<item index="107" class="java.lang.String" itemvalue="django-filter" />
<item index="108" class="java.lang.String" itemvalue="charset-normalizer" />
<item index="109" class="java.lang.String" itemvalue="django-smtp-ntlm-backend" />
<item index="110" class="java.lang.String" itemvalue="CacheControl" />
<item index="111" class="java.lang.String" itemvalue="google-cloud-core" />
<item index="112" class="java.lang.String" itemvalue="fcm-django" />
<item index="113" class="java.lang.String" itemvalue="diff-match-patch" />
<item index="114" class="java.lang.String" itemvalue="django-ckeditor" />
<item index="115" class="java.lang.String" itemvalue="firebase-admin" />
<item index="116" class="java.lang.String" itemvalue="httplib2" />
<item index="117" class="java.lang.String" itemvalue="wcwidth" />
<item index="118" class="java.lang.String" itemvalue="click-didyoumean" />
<item index="119" class="java.lang.String" itemvalue="Jinja2" />
<item index="120" class="java.lang.String" itemvalue="sqlparse" />
<item index="121" class="java.lang.String" itemvalue="google-resumable-media" />
<item index="122" class="java.lang.String" itemvalue="google-auth-httplib2" />
<item index="123" class="java.lang.String" itemvalue="django-phonenumber-field" />
<item index="124" class="java.lang.String" itemvalue="zope.event" />
<item index="125" class="java.lang.String" itemvalue="billiard" />
<item index="126" class="java.lang.String" itemvalue="pyotp" />
<item index="127" class="java.lang.String" itemvalue="six" />
<item index="128" class="java.lang.String" itemvalue="ruamel.yaml" />
<item index="129" class="java.lang.String" itemvalue="tzdata" />
<item index="130" class="java.lang.String" itemvalue="xlwt" />
<item index="131" class="java.lang.String" itemvalue="MarkupPy" />
<item index="132" class="java.lang.String" itemvalue="django-admin-list-filter-dropdown" />
<item index="133" class="java.lang.String" itemvalue="prometheus-client" />
<item index="134" class="java.lang.String" itemvalue="jmespath" />
<item index="135" class="java.lang.String" itemvalue="coreapi" />
<item index="136" class="java.lang.String" itemvalue="django-ipware" />
<item index="137" class="java.lang.String" itemvalue="s3transfer" />
<item index="138" class="java.lang.String" itemvalue="pyspnego" />
<item index="139" class="java.lang.String" itemvalue="django-js-asset" />
<item index="140" class="java.lang.String" itemvalue="proto-plus" />
<item index="141" class="java.lang.String" itemvalue="django-timezone-field" />
<item index="142" class="java.lang.String" itemvalue="grpcio" />
<item index="143" class="java.lang.String" itemvalue="click-plugins" />
<item index="144" class="java.lang.String" itemvalue="google-cloud-firestore" />
<item index="145" class="java.lang.String" itemvalue="google-auth" />
<item index="146" class="java.lang.String" itemvalue="openpyxl" />
<item index="147" class="java.lang.String" itemvalue="pytest-coverage" />
<item index="148" class="java.lang.String" itemvalue="alembic" />
<item index="149" class="java.lang.String" itemvalue="pytest-splinter" />
<item index="150" class="java.lang.String" itemvalue="pytest-cover" />
<item index="151" class="java.lang.String" itemvalue="trio-websocket" />
<item index="152" class="java.lang.String" itemvalue="pluggy" />
<item index="153" class="java.lang.String" itemvalue="python-dotenv" />
<item index="154" class="java.lang.String" itemvalue="h11" />
<item index="155" class="java.lang.String" itemvalue="mako" />
<item index="156" class="java.lang.String" itemvalue="sniffio" />
<item index="157" class="java.lang.String" itemvalue="httptools" />
<item index="158" class="java.lang.String" itemvalue="markupsafe" />
<item index="159" class="java.lang.String" itemvalue="trio" />
<item index="160" class="java.lang.String" itemvalue="selenium" />
<item index="161" class="java.lang.String" itemvalue="pytest-cov" />
<item index="162" class="java.lang.String" itemvalue="starlette" />
<item index="163" class="java.lang.String" itemvalue="anyio" />
<item index="164" class="java.lang.String" itemvalue="uvicorn" />
<item index="165" class="java.lang.String" itemvalue="python-jose" />
<item index="166" class="java.lang.String" itemvalue="uvloop" />
<item index="167" class="java.lang.String" itemvalue="outcome" />
<item index="168" class="java.lang.String" itemvalue="passlib" />
<item index="169" class="java.lang.String" itemvalue="websockets" />
<item index="170" class="java.lang.String" itemvalue="coverage" />
<item index="171" class="java.lang.String" itemvalue="watchfiles" />
<item index="172" class="java.lang.String" itemvalue="pydantic" />
<item index="173" class="java.lang.String" itemvalue="pytest-sugar" />
<item index="174" class="java.lang.String" itemvalue="asyncpg" />
<item index="175" class="java.lang.String" itemvalue="pytest" />
<item index="176" class="java.lang.String" itemvalue="iniconfig" />
<item index="177" class="java.lang.String" itemvalue="ecdsa" />
<item index="178" class="java.lang.String" itemvalue="splinter" />
<item index="179" class="java.lang.String" itemvalue="typing-extensions" />
<item index="180" class="java.lang.String" itemvalue="pytest-asyncio" />
<item index="181" class="java.lang.String" itemvalue="sqlalchemy" />
<item index="182" class="java.lang.String" itemvalue="wsproto" />
<item index="183" class="java.lang.String" itemvalue="sortedcontainers" />
<item index="184" class="java.lang.String" itemvalue="termcolor" />
<item index="185" class="java.lang.String" itemvalue="fastapi" />
<item index="186" class="java.lang.String" itemvalue="faker" />
<item index="187" class="java.lang.String" itemvalue="pysocks" />
<item index="188" class="java.lang.String" itemvalue="async-generator" />
</list>
</value>
</option>
</inspection_tool>
<inspection_tool class="PyUnresolvedReferencesInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ignoredIdentifiers">
<list>
<option value="type.with_ui" />
<option value="type.without_ui" />
</list>
</option>
</inspection_tool>
</profile>
</component>
\ No newline at end of file
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MarkdownSettingsMigration">
<option name="stateVersion" value="1" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11" project-jdk-type="Python SDK" />
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/http_framework.iml" filepath="$PROJECT_DIR$/.idea/http_framework.iml" />
</modules>
</component>
</project>
\ No newline at end of file
from typing import BinaryIO
class Request:
def __init__(self, file: BinaryIO) -> None:
self.file = file
self.body = self.method = self.uri = self.protocol = ''
self.headers = {}
self.parse_request_line()
self.parse_headers()
self.parse_body()
def readline(self):
return self.file.readline().decode().strip()
def parse_request_line(self) -> None:
request_line = self.readline()
self.method, self.uri, self.protocol = request_line.split()
def parse_headers(self) -> None:
while True:
header = self.readline()
if not header:
break
header_name, header_value = header.split(': ')
self.headers[header_name] = header_value
def parse_body(self) -> None:
if 'Content-Length' in self.headers:
content_length = int(self.headers['Content-Length'])
self.body = self.file.read(content_length)
from typing import BinaryIO
from os import fstat
class Response:
HTTP_OK = 200
HTTP_BAD_REQUEST = 400
HTTP_NOT_FOUND = 404
HTTP_INTERNAL_SERVER_ERROR = 500
MESSAGES = {
HTTP_OK: 'OK',
HTTP_BAD_REQUEST: 'Bad Request',
HTTP_NOT_FOUND: 'Not Found',
HTTP_INTERNAL_SERVER_ERROR: 'Internal Server Error'
}
PROTOCOL = 'HTTP/1.1'
def __init__(self, file: BinaryIO) -> None:
self.file = file
self.__status = self.HTTP_OK
self.__headers: list[dict] = []
self.body = None
self.file_body = None
def set_status(self, new_status: int) -> None:
self.__status = new_status
def set_body(self, body: str) -> None:
self.body = body.encode()
self.add_header('Content-Type', str(len(self.body)))
def set_file_body(self, file: BinaryIO) -> None:
self.file_body = file
size = fstat(file.fileno()).st_size
self.add_header('Content-Length', str(size))
def add_header(self, name: str, value: str) -> None:
self.__headers.append({name: value})
def __get_status_line(self) -> str:
message = self.MESSAGES[self.__status]
return f'{self.PROTOCOL} {self.__status} {message}'
def __get_response_head(self) -> bytes:
status_line = self.__get_status_line()
# for example
# headers = [': '.join(list(*header.items())) for header in self.__headers]
# print(headers)
# /for example
headers: list[str] = []
for header in self.__headers:
k, v = list(*header.items())
headers.append(f'{k}: {v}')
head_str = '\r\n'.join([status_line] + headers)
head_str += '\r\n\r\n'
return head_str.encode()
def __write_file_body(self) -> None:
# Chunk load
while True:
data = self.file_body.read(1024)
if not data:
break
self.file.write(data)
def send(self):
head = self.__get_response_head()
self.file.write(head)
if self.body:
self.file.write(self.body)
elif self.file_body:
self.__write_file_body()
import socketserver
from request import Request
from response import Response
from static_responder import StaticResponder
HOST, PORT = '127.0.0.1', 1025
class MyTCPHandler(socketserver.StreamRequestHandler):
def handle(self) -> None:
request = Request(file=self.rfile)
response = Response(file=self.wfile)
static_responder = StaticResponder(request, response, 'static')
if static_responder.file:
static_responder.prepare_response()
else:
response.add_header('Content-Type', 'text/html')
response.add_header('Connection', 'close')
response.set_body('<h1>Hello world!</h1>')
print(
f'Method: {request.method}\n'
f'URI: {request.uri}\n'
f'Protocol: {request.protocol}\n'
)
response.send()
socketserver.TCPServer.allow_reuse_address = True
with socketserver.ThreadingTCPServer((HOST, PORT), MyTCPHandler) as server:
server.serve_forever()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>Hello world!</h1>
</body>
</html>
\ No newline at end of file
* {
text-align: center;
}
.container {
margin: 0 auto;
width: 80%;
}
from glob import glob
import os
from request import Request
from response import Response
class StaticResponder:
def __init__(self, request: Request, response: Response, static_dir: str) -> None:
self.request = request
self.response = response
self.static_dir = static_dir
self.file = None
self._check_file()
def _check_file(self):
path = './' + self.static_dir + self.request.uri
# path = ./ static /styles.css
files: list[str] = glob(path)
if len(files) > 0 and os.path.isfile(files[0]):
self.file = files[0]
def prepare_response(self):
if self.file:
file = open(self.file, 'rb')
self.response.set_file_body(file)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment