Commit 1fcad6e3 authored by Давид Ли's avatar Давид Ли

lesson 38

parent c9d1f438
class BaseController:
def __init__(self, request, 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(self):
self.response.add_header('Content-Type', 'text/html')
self.response.set_body('<h1>This is about</h1>')
from .base import BaseController
class PostsController(BaseController):
def get_list(self):
posts_bd = [
{'id': 1, 'title': 'This is 1st post'},
{'id': 2, 'title': 'This is 2st post'},
{'id': 3, 'title': 'This is 3st post'},
]
body = '<h1>This is our posts</h1>'
for post in posts_bd:
body += f'<h3>{post["id"]} - {post["title"]}'
self.response.add_header('Content-Type', 'text/html')
self.response.set_body(body)
from response import Response
from request import Request
def not_found(request, response):
response.set_status(Response.HTTP_NOT_FOUND)
response.add_header('Content-Type', 'text/html')
response.set_body('<h1>404 Not Found</h1>')
def internal_server_error(request, response):
response.set_status(Response.HTTP_INTERNAL_SERVER_ERROR)
response.add_header('Content-Type', 'text/html')
response.set_body('<h1>500 INTERNAL_SERVER_ERROR</h1>')
from request import Request
from response import Response
from static_responder import StaticResponder
import socketserver
class Handler(socketserver.StreamRequestHandler):
# self.request - client socket
def handle(self):
request = Request(self.rfile)
response = Response(self.wfile)
static_responder = StaticResponder(request, response)
print(request)
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>')
response.send()
ADDRESS = ('localhost', 1027)
socketserver.ThreadingTCPServer.allow_reuse_address = True
with socketserver.ThreadingTCPServer(ADDRESS, Handler) as server:
server.serve_forever()
from request import Request
from response import Response
import errors
from static_responder import StaticResponder
import socketserver
from controllers.pages import PagesController
from controllers.posts import PostsController
from errors import not_found
from errors import not_found
from router import Router
#REST RESTfull
#CRUDL - Create, Read, Update, Delete, List
#/posts
#GET - /posts
#GET - /posts/{id}
#POST - /posts
#PUT\PATH - /posts/{id}
#DELETE - /posts/{id}
router = Router()
router.get('/', PagesController, 'home')
router.get('/about', PagesController, 'about')
router.get('/posts', PostsController, 'get_list')
class Handler(socketserver.StreamRequestHandler):
# self.request - client socket
def handle(self):
request = Request(self.rfile)
response = Response(self.wfile)
response.add_header('Connection', 'close')
# static_responder = StaticResponder(request, response)
print(request)
router.run(request, response)
response.send()
ADDRESS = ('localhost', 1027)
socketserver.ThreadingTCPServer.allow_reuse_address = True
with socketserver.ThreadingTCPServer(ADDRESS, Handler) as server:
server.serve_forever()
class Request:
def __init__(self, rfile):
self.file = rfile
self.method = None
self.uri = None
self.protocol = None
self.headers = {}
self.body = None
self.__parse_request_line()
self.__parse_headers()
self.__parse_body()
def __parse_request_line(self):
request_line = self.__readline()
# GET / HTTP/1.1 ['GET', '/', 'HTTP/1.1']
self.method, self.uri, self.protocol = request_line.split()
def __readline(self):
return self.file.readline().decode().strip()
def __parse_headers(self):
while True:
header = self.__readline()
if header == '':
break
name, value = header.split(': ')
self.headers[name] = value
def __parse_body(self):
if 'Content-Length' in self.headers:
content_length = int(self.headers['Content-Length'])
self.body = self.file.read(content_length)
def __str__(self):
return (
f'{"-" * 30}\n'
f'{self.method} {self.uri}'
)
class Request:
def __init__(self, rfile):
self.file = rfile
self.method = None
self.uri = None
self.protocol = None
self.headers = {}
self.body = None
self.__parse_request_line()
self.__parse_headers()
self.__parse_body()
def __parse_request_line(self):
request_line = self.__readline()
# GET / HTTP/1.1 ['GET', '/', 'HTTP/1.1']
self.method, self.uri, self.protocol = request_line.split()
def __readline(self):
return self.file.readline().decode().strip()
def __parse_headers(self):
while True:
header = self.__readline()
if header == '':
break
name, value = header.split(': ')
self.headers[name] = value
def __parse_body(self):
if 'Content-Length' in self.headers:
content_length = int(self.headers['Content-Length'])
self.body = self.file.read(content_length)
def __str__(self):
return (
f'{"-" * 30}\n'
f'{self.method} {self.uri}'
)
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, wfile):
self.wfile = wfile
self.status = self.HTTP_OK
self.headers = {}
self.body = None
self.file_body = None
def add_header(self, name, value):
self.headers[name] = value
def set_body(self, body):
self.body = body.encode()
self.add_header('Content-Length', len(self.body))
def set_file_body(self, file):
self.file_body = file
size = fstat(file.fileno()).st_size
self.add_header('Content-Length', size)
def __get_status_line(self):
message = self.MESSAGES[self.status]
return f'{self.PROTOCOL} {self.status} {message}'
def __get_headers(self):
headers = []
for name, value in self.headers.items():
headers.append(f'{name}: {value}')
return headers
def _write_file_body(self):
while True:
data = self.file_body.read(1024)
if not data:
break
self.wfile.write(data)
def send(self):
status_line = self.__get_status_line()
headers = self.__get_headers()
response_str = '\r\n'.join([status_line] + headers) + '\r\n\r\n'
self.wfile.write(response_str.encode())
if self.body:
self.wfile.write(self.body)
elif self.file_body:
self._write_file_body()
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, wfile):
self.wfile = wfile
self.status = self.HTTP_OK
self.headers = {}
self.body = None
self.file_body = None
def set_status(self, new_status: int) -> None:
self.status = new_status
def add_header(self, name, value):
self.headers[name] = value
def set_body(self, body):
self.body = body.encode()
self.add_header('Content-Length', len(self.body))
def set_file_body(self, file):
self.file_body = file
size = fstat(file.fileno()).st_size
self.add_header('Content-Length', size)
def __get_status_line(self):
message = self.MESSAGES[self.status]
return f'{self.PROTOCOL} {self.status} {message}'
def __get_headers(self):
headers = []
for name, value in self.headers.items():
headers.append(f'{name}: {value}')
return headers
def _write_file_body(self):
while True:
data = self.file_body.read(1024)
if not data:
break
self.wfile.write(data)
def send(self):
status_line = self.__get_status_line()
headers = self.__get_headers()
response_str = '\r\n'.join([status_line] + headers) + '\r\n\r\n'
self.wfile.write(response_str.encode())
if self.body:
self.wfile.write(self.body)
elif self.file_body:
self._write_file_body()
\ No newline at end of file
# router = Router()
#
# router.get('/', PagesController, 'home')
#
# router.post('/posts', PostController, 'create')
#
# router.run()
from errors import not_found, internal_server_error
class Router:
def __init__(self):
self.routes = {
'get': [],
'post': []
}
def add(self, http_method: str, uri: str, ctrl, ctrl_method):
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, response):
http_method = request.method.lower()
method_routes = self.routes[http_method]
route = None
for r in method_routes:
if r['uri'] == request.uri:
route = r
break
if not route:
return not_found(request, response)
try:
ctrl = route['ctrl'](request, response)
getattr(ctrl, route['ctrl_method'])()
except BaseException:
return internal_server_error(request, response)
from glob import glob
import os
class StaticResponder:
def __init__(self, request, response, static_dir='static'):
self.request = request
self.response = response
self.static_dir = static_dir
self.file = None
self._check_file()
# http://localhost:1027/cat.jpg
def _check_file(self):
file_uri = self.request.uri.replace('..', '')
path = './' + self.static_dir + file_uri
files = glob(path)
if len(files) > 0 and os.path.isfile(files[0]):
self.file = files[0]
def prepare_response(self):
file = open(self.file, 'rb')
self.response.set_file_body(file)
from glob import glob
import os
class StaticResponder:
def __init__(self, request, response, static_dir='static'):
self.request = request
self.response = response
self.static_dir = static_dir
self.file = None
self._check_file()
# http://localhost:1027/cat.jpg
def _check_file(self):
file_uri = self.request.uri.replace('..', '')
path = './' + self.static_dir + file_uri
files = glob(path)
if len(files) > 0 and os.path.isfile(files[0]):
self.file = files[0]
def prepare_response(self):
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