목차
pip 업그레이드로 해결
python3 -m pip install --upgrade pip
#app.py
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/hello/')
@app.route('/hello/<name>')
def hello(name=None):
return render_template('hello.html', name=name)
<!--templates/hello.html-->
<!DOCTYPE html>
<title>Hello from Flask!</title>
{% if name %}
<h1>Hello {{ name }}!</h1>
{% else %}
<h1>Hello, World!</h1>
{% endif %}
/hello로 접속시 308 상태코드와 함께 /hello/로 이동함.
docker container 다 지우고 지난주 실습을 다시 진행해보자 ,,
(마운트한 로컬 위치를 바꾸는 방법을 모르겠다.)
# http_server.py
import os
import http
import http.server
import socketserver
import sqlite3
PREFIX = ''
FLAGS = _ = None
DEBUG = False
EXT = {'.html': 'text/html;charset=utf-8'}
CONN = sqlite3.connect('./Log.db')
CUR = CONN.cursor()
CUR.execute('''CREATE TABLE IF NOT EXISTS Log (
id INTEGER PRIMARY KEY AUTOINCREMENT,
ip TEXT,
request TEXT);''')
CONN.commit()
class MyHTTPDaemon(http.server.HTTPServer):
allow_reuse_address = True
class MyHTTPRequestHandler(http.server.BaseHTTPRequestHandler):
def __init__(self, *args, **kwargs):
self.rootdir = FLAGS.rootdir
self.conn = CONN
self.cur = CUR
super().__init__(*args, **kwargs)
def do_GET(self):
if DEBUG:
print(f'Command: {self.command}')
print(f'Path: {self.path}')
print(f'Headers: {self.headers}')
self.cur.execute('''INSERT INTO Log (ip, request)
VALUES (?, ?);''', (self.client_address[0], self.requestline))
self.conn.commit()
if not self.path.startswith(PREFIX):
return None
self.path = self.path[len(PREFIX):]
if self.path == '/':
path = 'index.html'
else:
path = self.path[1:]
path = os.path.join(self.rootdir, path)
if DEBUG:
print(f'Joined path: {self.rootdir} {self.path} {path}')
if not os.path.exists(path):
self.send_error(http.HTTPStatus.NOT_FOUND, 'File not found')
else:
ext = os.path.splitext(path)[-1].lower()
self.send_response(http.HTTPStatus.OK)
self.send_header('Content-Type', EXT[ext])
with open(path, 'rb') as f:
self.cur.execute('''SELECT MAX(id) FROM Log;''')
counter = self.cur.fetchone()[0]
body = f.read()
body = body.replace('{{ COUNTER }}'.encode('utf-8'), f'{counter}'.encode('utf-8'))
self.send_header('Content-Length', len(body))
self.end_headers()
self.wfile.write(body)
def main():
print(f'Parsed arguments: {FLAGS}')
print(f'Unparsed arguments: {_}')
with MyHTTPDaemon((FLAGS.host, FLAGS.port),
MyHTTPRequestHandler) as httpd:
try:
print(f'Start server {httpd.server_address}')
httpd.serve_forever()
except KeyboardInterrupt:
print(f'Stop server {httpd.server_address}')
httpd.shutdown()
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--debug', action='store_true',
help='Debug message')
parser.add_argument('--host', default='0.0.0.0', type=str,
help='IP address')
parser.add_argument('--port', default=8888, type=int,
help='Port number')
parser.add_argument('--rootdir', default='./dir', type=str,
help='Root directory')
FLAGS, _ = parser.parse_known_args()
DEBUG = FLAGS.debug
main()
<!-- dir/index.html -->
<!DOCTYPE html>
<html>
<body>
<h1>index.html</h1>
<p>총 방문자: {{ COUNTER }}</p>
</body>
</html>
# mynginx9 컨테이너
# nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
}
# mydb9 컨테이너
apt update
apt install python3.10 python3-pip python3-dev python3-venv python3-pip net-tools vim
apt-get install -y libmariadb-dev
pip install uvicorn fastapi sqlalchemy alembic mariadb
$ mariadb -uroot -p
pw : my-secret-pw
$ CREATE DATABASE pastebin;
$ CREATE USER IF NOT EXISTS pasteuser@pastebin IDENTIFIED BY 'user-secret-pw';
$ GRANT ALL PRIVILEGES ON pastebin.* TO 'pasteuser'@'%' IDENTIFIED BY 'user-secret-pw';
$ FLUSH PRIVILEGES;
# myback9 컨테이너
apt update
apt install python3.10 python3-pip python3-dev python3-venv python3-pip net-tools vim
apt-get install -y libmariadb-dev
pip install uvicorn fastapi sqlalchemy alembic mariadb
http_server.py의 PREFIX 수정
nginx.conf에서 proxy 수정
# mybp 컨테이너
apt update
apt install python3.10 python3-pip python3-dev python3-venv python3-pip net-tools vim
apt-get install -y libmariadb-dev
pip install uvicorn fastapi sqlalchemy alembic mariadb Flask
nginx.conf 설정
Flask 접속 위한 location 추가
mybp/app.py 수정
from flask import Flask, render_template, Blueprint
import urllib.request
import json
app = Flask(__name__)
@app.route('/hello/')
@app.route('/hello/<name>')
def hello(name=None):
return render_template('hello.html', name=name)
endpoint = 'http://mynginx9/pastebin/api'
bp = Blueprint('mybp', __name__,
static_folder='static',
static_url_path='/pastebin/static',
template_folder='templates',
url_prefix='/pastebin')
@bp.route(f'/', methods=['GET'])
@bp.route(f'/index.html', methods=['GET'])
def get_index():
count_users = 0
url = f'{endpoint}/users/'
data = None
headers = {'Accept': 'application/json'}
method = 'GET'
req = urllib.request.Request(url=url,
data=data,
headers=headers,
method=method)
with urllib.request.urlopen(req) as f:
data = json.loads(f.read())
count_users = len(data)
count_pastes = 0
url = f'{endpoint}/pastes/'
data = None
headers = {'Accept': 'application/json'}
method = 'GET'
req = urllib.request.Request(url=url,
data=data,
headers=headers,
method=method)
with urllib.request.urlopen(req) as f:
data = json.loads(f.read())
count_pastes = len(data)
return render_template('index.html',
count_users=count_users,
count_pastes=count_pastes)
app.register_blueprint(bp)
S
app/crud.py 수정
...
# 모든 메모 열람
def get_pastes(db: Session, skip: int = 0, limit: int = 100):
return db.query(models.Paste).order_by(models.Paste.id.asc()).offset(skip).limit(limit).all()
app/main.py 수정
...
# 모든 메모 열람
@app.get('/pastes/', response_model=List[schemas.Paste])
def get_pastes(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
pastes = crud.get_pastes(db, skip=skip, limit=limit)
return pastes
가장 하단의 #모든 메모 열람 부분을 추가해주어야한다.
mybp의 app.py에서 {endpoint}/users/와 {endpoint}/pastes/의 url을 urllib.request 패키지로 요청하기 때문에 해당 경로가 존재하지 않으면 urllib.error.HTTPError: HTTP Error 404: Not Found 와 같은 에러가 발생한다.