Commit 38ccb863 authored by Давид Ли's avatar Давид Ли

completed 38 lesson

parent 28a10bc3
venv
.idea
__pycache__*
\ No newline at end of file
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<module type="PYTHON_MODULE" version="4"> <module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager"> <component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" /> <content url="file://$MODULE_DIR$" />
<orderEntry type="jdk" jdkName="Python 3.11" jdkType="Python SDK" /> <orderEntry type="jdk" jdkName="Python 3.11 (http_framework)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
</component> </component>
</module> </module>
\ No newline at end of file
...@@ -3,5 +3,5 @@ ...@@ -3,5 +3,5 @@
<component name="MarkdownSettingsMigration"> <component name="MarkdownSettingsMigration">
<option name="stateVersion" value="1" /> <option name="stateVersion" value="1" />
</component> </component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11" project-jdk-type="Python SDK" /> <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11 (http_framework)" project-jdk-type="Python SDK" />
</project> </project>
\ No newline at end of file
from request import Request
from response import Response
class BaseController:
def __init__(self, request: Request, response: Response):
self.request = request
self.response = response
from .base import BaseController
class PagesController(BaseController):
def home(self):
self.response.add_header('Content-Type', 'text/html')
self.response.set_body('<h1>This is homepage</h1>')
def about_us(self):
self.response.add_header('Content-Type', 'text/html')
self.response.set_body('<h1>This is about us page</h1>')
from controllers.base import BaseController
def id_generator():
count = 0
while True:
count += 1
yield count
id_gen = id_generator()
class PostsController(BaseController):
posts_db = [
{'id': next(id_gen), 'title': 'This is 1 post'},
{'id': next(id_gen), 'title': 'This is 2 post'},
{'id': next(id_gen), 'title': 'This is 3 post'},
]
def get_list(self):
body = (
'<h1>This is posts page</h1>'
'<br><form action="/posts" method="POST">'
'<label>'
'<input type="text" name="title">'
'</label>'
'<input type="submit">'
'</form><br>'
)
for post in self.posts_db:
body += f'<h3>{post["id"]} - {post["title"]}'
self.response.add_header('Content-Type', 'text/html')
self.response.set_body(body)
def create(self):
id_ = next(id_gen)
self.posts_db.append(
{
'id': id_,
'title': f'This is {id_} post'
}
)
self.response.add_header('Content-Type', 'text/html')
self.response.set_body('<a href="/posts"">Back to posts list</a>')
from request import Request
from response import Response
def not_found(request: Request, response: Response):
response.add_header('Content-Type', 'text/html')
response.set_status(Response.HTTP_NOT_FOUND)
response.set_body('<h1>404 Not Found</h1>')
def internal_server_error(request: Request, response: Response):
response.add_header('Content-Type', 'text/html')
response.set_status(Response.HTTP_INTERNAL_SERVER_ERROR)
response.set_body('<h1>500 Internal Server Error</h1>')
import urllib.parse
from typing import BinaryIO from typing import BinaryIO
...@@ -32,4 +33,16 @@ class Request: ...@@ -32,4 +33,16 @@ class Request:
def parse_body(self) -> None: def parse_body(self) -> None:
if 'Content-Length' in self.headers: if 'Content-Length' in self.headers:
content_length = int(self.headers['Content-Length']) content_length = int(self.headers['Content-Length'])
body = self.file.read(content_length)
if isinstance(body, bytes):
decoded = body.decode()
parsed = urllib.parse.parse_qs(decoded)
for k, v in parsed.items():
parsed[k] = ' '.join(v) # noqa
self.body = parsed
else:
self.body = self.file.read(content_length) self.body = self.file.read(content_length)
import errors
from controllers.base import BaseController
from request import Request
from response import Response
class Router:
def __init__(self):
self.routes = {
'get': [],
'post': []
}
def add(self, http_method: str, uri: str, ctrl: BaseController, ctrl_method: str):
self.routes[http_method].append(
{
'uri': uri,
'ctrl': ctrl,
'ctrl_method': ctrl_method
}
)
def get(self, *args):
self.add('get', *args)
def post(self, *args):
self.add('post', *args)
def run(self, request: Request, response: Response):
http_method = request.method.lower() # post
method_routes = self.routes[http_method] # [{'uri': 'some_uri', 'ctrl': Ctrl. 'ctrl_method': 'home'}]
route = None
for r in method_routes:
if r['uri'] == request.uri:
route = r
break
print(route)
if not route:
return errors.not_found(request, response)
try:
ctrl = route['ctrl'](request, response)
getattr(ctrl, route['ctrl_method'])()
except BaseException as e:
print(e)
return errors.internal_server_error(request, response)
import socketserver import socketserver
from controllers.pages import PagesController
from controllers.posts import PostsController
from request import Request from request import Request
from response import Response from response import Response
from router import Router
from static_responder import StaticResponder from static_responder import StaticResponder
import errors
HOST, PORT = '127.0.0.1', 1025 HOST, PORT = '127.0.0.1', 1025
# CRUDL - Create, Read, Update, Delete, List
# /posts
# GET - /posts
# GET - /posts/{id}
# POST - /posts
# PUT/PATCH - /posts/{id}
# DELETE - /posts/{id}
router = Router()
router.get('/', PagesController, 'home')
router.get('/about-us', PagesController, 'about_us')
router.get('/posts', PostsController, 'get_list')
router.post('/posts', PostsController, 'create')
class MyTCPHandler(socketserver.StreamRequestHandler): class MyTCPHandler(socketserver.StreamRequestHandler):
def handle(self) -> None: def handle(self) -> None:
request = Request(file=self.rfile) request = Request(file=self.rfile)
response = Response(file=self.wfile) response = Response(file=self.wfile)
static_responder = StaticResponder(request, response, 'static') static_responder = StaticResponder(request, response, 'static')
if static_responder.file: router.run(request, response)
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( print(
f'Method: {request.method}\n' f'Method: {request.method}\n'
......
<!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
...@@ -2,6 +2,10 @@ ...@@ -2,6 +2,10 @@
text-align: center; text-align: center;
} }
h1 {
color: red
}
.container { .container {
margin: 0 auto; margin: 0 auto;
width: 80%; width: 80%;
......
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="../static/styles.css">
<title>Title</title>
</head>
<body>
<h1>Hello {{ user.name|title }} {{ user.surname|title }} </h1>
<h3>Today: {{ user.current_datetime }}</h3>
<h4>Phone: {{ user.phone }}</h4>
<form action="/posts" method="POST">
<label>
<input type="text" name="title">
</label>
</form>
{{ user.contacts|join(', ') }}
<!-- <ol>-->
<!-- {% for i in user.contacts %}-->
<!-- <li>{{ i }}</li>-->
<!-- {% endfor %}-->
<!-- </ol>-->
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Assumenda nostrum quasi voluptate. Ad blanditiis deserunt distinctio error facilis incidunt maxime nostrum, numquam placeat? Error hic obcaecati quas quis saepe velit.</p>
</body>
</html>
\ No newline at end of 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