It's now easier to develop web apps using web frameworks like Django and Flask, but it doesn't really make sense to just learn how to use the framework without understanding the roots. , I decided to understand the mechanism by implementing a simple blog app using only python's built-in functions and standard library without using the web framework.
Since the web server returns (displays) something when accessed from a web browser, create the index page to be displayed first in html. I created an index page that outputs Hello, World !.
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<p>Hello, World!</p>
</body>
</html>
webserver.py
from http.server import HTTPServer, SimpleHTTPRequestHandler
def run(server_class=HTTPServer, handler_class=SimpleHTTPRequestHandler):
server_address = ('', 8000)
httpd = server_class(server_address, handler_class)
httpd.serve_forever()
if __name__ == '__main__':
run()
HTTP Server is one of the standard python libraries for implementing web server functionality. In the HTTPServer argument, specify the server name and port number tuple and request handler. First of all, as a test, as an argument of HTTPServer, specify the server name (default is localhost) and the port number (identification number of the accessing program) 8000, and it is one of the request handlers that manages requests from clients. It specifies two SimpleHTTPRequestHandlers (simple classes that return files that correspond to client access).
Terminal
$ python webserver.py
When I access localhost: 8000 with a browser, Hello, World
is output.
If you refer to the official documentation [^ 1], there is a warning that it is not suitable for http.server commercial use.
Warning http.server is not recommended for production. It only implements basic security checks.
Since the built-in server is slow and cannot withstand the load, it is common to use a web server application such as Apache or Nginx for commercial use. This time, the purpose is to understand and implement the mechanism of the web application, so we will use the built-in server as it is.
In the HTTP server executed in the test earlier, SimpleRequestHandler was specified as the request handler, but since this was a process that only returned index.html, next we will add our own process.
Override the ability to display the formatted string in html in SimpleRequestHandler to the do_GET method. In the first place, the do_GET method performs the process of returning an HTTP response and returning the corresponding file.
webserver.py
with open('index.html', 'r')as f:
index_file = f.read()
class OriginalHTTPRequestHandler(SimpleHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.end_headers()
html = index_file.format(
title = 'Blog title',
content = 'Blog content'
)
self.wfile.write(html.encode('utf-8'))
return None
Fix the part where Hello, World
was hard-coded in the html file so far.
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>{title}</h1>
<p>{content}</p>
</body>
</html>
When you start the server and access localhost: 8000
, you can see that it is displayed as follows.
Blog title
Blog content
Now you can display the formatted string in html, but since the blog has a posting function and it is assumed that you can see the post list, next post using HTML form tags Implement the function. Rewrite index.html as follows.
index.html
<body>
<h1>{title}</h1>
<p>{content}</p>
<form method = 'POST' action="/result.html">
<textarea name="titlefield" id="titlefield" cols="30" rows="3" maxlength=15 placeholder="enter title"></textarea><br>
<textarea name="contentfield" id="contentfield" cols="30" rows="10" placeholder="Enter the content of the post"></textarea><br>
<input type="submit"><br>
</form>
</body>
Change the method of the form tag to'POST' and the action to'result.html' to display the post result. Create result.html to display the post result.
result.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>{header}</h1>
<h2>{title}</h2>
<p>{content}</p>
<p><a href="{link}">Return to the posting screen</a></p>
</body>
</html>
Then modify the server program. Add a do_POST () method to process the submitted Form information. Utilize the FieldStorage class of the cgi module to process the value submitted by the Form. FieldStorage is an object that manages the information submitted in the form.
webserver.py
from cgi import FieldStorage
from http.server import HTTPServer, SimpleHTTPRequestHandler
with open('index.html', 'r') as f:
index_file = f.read()
with open('result.html', 'r') as f:
result_file = f.read()
class OriginalHTTPRequestHandler(SimpleHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.end_headers()
html = index_file.format(
header = 'Post screen',
title = 'Blog title',
content = 'Blog content'
)
self.wfile.write(html.encode('UTF-8'))
return None
def do_POST(self):
form = FieldStorage(
fp = self.rfile,
headers=self.headers,
environ={'REQUEST_METHOD':'POST'})
title_form = form['titlefield'].value
content_form = form['contentfield'].value
self.send_response(200)
self.end_headers()
html = result_file.format(
header = 'Posting result',
title_message = 'title:',
content_message = 'Posted content:',
title = title_form,
content = content_form,
link = '/result.html'
)
self.wfile.write(html.encode('utf-8'))
return None
def run(server_class=HTTPServer, handler_class=OriginalHTTPRequestHandler):
server_address = ('', 8000)
httpd = server_class(server_address, handler_class)
httpd.serve_forever()
if __name__ == '__main__':
run()
When I run the server and access localhost: 8000 with a browser, the Form tag
is output.
The database that can be handled by the standard library of python is Sqlite3 or DBM that can be handled like a file operation, so from the next time onward, we will use Sqlite3 of RDB to save the data.
[^ 1]: Python official documentation --- HTTP server
Recommended Posts