PythonでWebフレームワークを使わずにWebサイトを作成する方法【Webの仕組みを利用しよう!】
2024年8月23日
こんにちは!
今回の記事では、PythonでWebフレームワークを使わずにWEbサイトを作成する方法について解説します。
Pythonには、DjangoやFlaskといった様々なWebフレームワークがあります。Webフレームワークを使うことで、簡単にWebサイトを作成することが可能です。
しかし、今回はあえてWebフレームワークを使用しません。Webフレームワークを使わないことで、Webサイトをどのように作成できるのか、低レイヤー部分を理解することが可能になります。
Webの仕組みをくわしく知りたい方は是非お読みください!
Webの基本的な仕組み
PythonでWebサイトを作成する前に、基本的なWebの仕組みについておさらいしましょう。
クライアントとサーバ
Webはクライアントとサーバの通信によって成り立っています。
クライアント(通常はWebブラウザ)は、ユーザーが指定したURLに基づいてサーバにリクエストを送信します。
サーバはそのリクエストを受け取り、適切なレスポンス(HTMLページ)をクライアントに返します。
この通信は主にHTTP(Hypertext Transfer Protocol)というプロトコルに基づいて行われます。HTTPは、クライアントがサーバにリソースをリクエストし、サーバがそのリソースを提供するためのルールを定めたものです。
HTTPリクエストとレスポンス
次にクライアントとサーバーの通信の中身を見てみましょう。
HTTPリクエストは、クライアントがサーバに対して行う要求です。リクエストは通常、以下のような形式を取ります。
GET / HTTP/1.1
Host: localhost:8000
GETはリクエストのメソッドです。これは、サーバからデータを取得することを意味します。
/はリクエストするリソースのパスを示しています。この例では、ホームページをリクエストしています。HTTP/1.1は使用するHTTPプロトコルのバージョンです。
サーバはこのリクエストを受け取り、以下のようなHTTPレスポンスを返します。
HTTP/1.1 200 OK
Content-Type: text/html
<html>
<body>
<h1>Hello, World!</h1>
</body>
</html>
HTTP/1.1 200 OKは、リクエストが成功したことを示すステータスラインです。
Content-Type: text/htmlは、レスポンスの内容がHTMLであることを示すヘッダーです。
空行の後に続く部分が実際のレスポンスボディであり、クライアントに表示されるコンテンツです。
このようなやりとりを行いWebページを表示しています。
socketモジュールを使用してWebサーバを構築する
次に、これらの基本的な仕組みを理解した上で、socketモジュールを使用して実際にHTTPサーバを構築してみましょう。
Pythonには、http.serverというライブラリがありますが、socketモジュールを使うことで、先ほど説明したような低レイヤーの仕組みを理解することが可能です。
ソケット(socket)とは?
まずは、今回使用するソケットについて簡単に説明します。
ソケット(socket)は、ネットワーク通信においてデータの送受信を行うためのエンドポイントのことです。
具体的には、ソケットは通信を行うための一種のインターフェースであり、IPアドレスとポート番号を組み合わせて、ネットワーク上の特定のプロセス(アプリケーション)を識別します。
シンプルなWebサーバの実装
ここでは、シンプルなWebサーバーを作成します。Webページへアクセスすると、「Hello, World!」と表示するサイトです。
以下のコードを記述したpythonファイルを作成しましょう。ファイル名はhttp_server.pyとします。
import socket
HOST, PORT = '', 8000
# ソケットを作成
listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
listen_socket.bind((HOST, PORT)) # ホスト名とポート番号を指定
listen_socket.listen(1) # 最大接続数を指定
print(f"サーバを起動しました。http://localhost:{PORT} でアクセスできます。")
while True:
client_connection, client_address = listen_socket.accept() # クライアントからの接続を待つ
request = client_connection.recv(1024).decode('utf-8') # クライアントからのリクエストを受信
print(request)
# HTTPレスポンスを作成
http_response = """\
HTTP/1.1 200 OK
<html><body><h1>Hello, World!</h1></body></html>
"""
client_connection.sendall(http_response.encode('utf-8')) # レスポンスをクライアントに送信
client_connection.close() # 接続を閉じる
コードの解説は後ほど行います。
Webサーバーの起動
続いて、先ほど作成したpythonファイルからWebサーバーを起動してみます。
以下のコマンドを実行してみましょう。
python http_server.py
コマンドを実行すると、「サーバを起動しました。http://localhost:8000 でアクセスできます。」というメッセージが表示します。
この状態で、ブラウザからhttp://localhost:8000へアクセスしてみましょう。
以下のように「Hello, World!」と表示されたら成功です。
このように、Webフレームワークを使わなくても、Webサーバーとして起動することができました。
ソースコードの解説
次に、http_server.pyファイルのコードを解説します。
このコードを理解することで、Webサーバーがどのような仕組みで動作しているのかがわかります。
インポート
まず1行目
import socket
ここでは、ネットワーク通信を行うための標準ライブラリであるsocketモジュールをインポートしています。socketモジュールを使用することで、Pythonでソケット通信(TCP/IP通信)を行うことができます。
ホストとポートの設定
続いて、3行目
HOST, PORT = '', 8000
HOSTはサーバがバインドするホスト名を指定します。空文字列(”)は、全ての利用可能なネットワークインターフェース(ローカルホストを含む)にバインドすることを意味します。
PORTはサーバがリクエストを受け付けるポート番号を指定します。今回は、8000番ポートを使用します。
ソケットの作成と設定
続いて6~8行目では、ソケットの作成と設定を行なっています。
listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.socket()は、新しいソケットオブジェクトを作成します。
socket.AF_INETは、IPv4アドレスファミリを指定します。つまり、IPv4プロトコルを使用して通信を行うことを意味します。
socket.SOCK_STREAMは、TCPプロトコルを指定します。TCPは信頼性の高い接続指向のプロトコルで、データの順序や誤りの検出を保証します。
listen_socket.bind((HOST, PORT))
bind()メソッドは、ソケットを特定のホスト名とポート番号にバインドします。3行目で設定したHOSTとPORTの値を使って、サーバがリクエストを受け取るアドレスとポートを設定します。
listen_socket.listen(1)
listen()メソッドは、ソケットをサーバモードにして、クライアントからの接続を待ち受けます。引数1は、同時に待ち受けられる接続の最大数を指定しています。今回は、同時に1つの接続のみを受け付けます。
サーバの起動メッセージ
続いて、10行目
print(f"サーバを起動しました。http://localhost:{PORT} でアクセスできます。")
print()関数で、サーバが起動し、指定されたポート(この場合は8000)でアクセス可能であることをユーザーに通知します。
クライアント接続の処理ループ
続いて、12~24行目は、クライアント接続の処理ループを行い、常にクライアントからのWeb通信を受信できるようにします。
while True:
while True:で無限ループを開始します。これにより、サーバは常にクライアントからの接続を受け付けるようになります。
client_connection, client_address = listen_socket.accept()
accept()メソッドは、クライアントからの接続要求を受け入れます。このメソッドはブロッキングメソッドで、クライアントが接続してくるまで処理が止まります。
client_connectionにはクライアントとの通信に使用するソケットオブジェクトが、client_addressには接続してきたクライアントのアドレスが格納されます。
request = client_connection.recv(1024).decode('utf-8')
recv()メソッドを使用して、クライアントから送信されたデータを受信します。1024は受信するデータの最大バイト数を指定しています。
decode(‘utf-8’)は、バイトデータをUTF-8エンコーディングでデコードし、人間が読める文字列に変換します。
print(request)
printで受信したリクエストをコンソールに出力します。これはHTTPリクエストの内容が表示されます。
HTTPレスポンスの作成と送信
ループ内の18行目では、レスポンスを生成しています。
http_response = """\
HTTP/1.1 200 OK
<html><body><h1>Hello, World!</h1></body></html>
"""
http_response変数には、サーバからクライアントに返すHTTPレスポンスの内容が格納されています。
このレスポンスは、HTTP/1.1 200 OKというステータスラインを持ち、クライアントにリクエストが正常に処理されたことを示します。
レスポンスのボディ部分には、HTMLで記述された「Hello, World!」というメッセージが含まれています。
19行目では、レスポンスをクライアントに送信します。
client_connection.sendall(http_response.encode('utf-8'))
sendall()メソッドは、レスポンスデータをクライアントに送信します。encode(‘utf-8’)を使って文字列をバイトデータにエンコードしています。
最後に、最後に、close()メソッドを使用してクライアントとの接続を閉じます。
client_connection.close()
これにより、サーバは新たなクライアント接続を受け付ける準備が整います。
このようなsocketの動きでWebサーバーの処理を実装しています。
まとめ
今回の記事では、pythonで非常にシンプルなHTTPサーバを構築しました。
サーバは、クライアント(通常はWebブラウザ)からの接続を受け付け、リクエストを処理して簡単なHTMLレスポンスを返すという基本的な機能を持っています。
PythonでWebフレームワークを使わないことで、Webの基本的な仕組みを理解し、TCP/IPやHTTPプロトコルの基本を学ぶことができました。
このように1からWebサーバーを実装することで、知識が深掘りできたと思います。
今回の記事が何かのお役になれば幸いです。
ここまでお読みいただきありがとうございました。
Pythonの基礎から応用まで学べる
Python WebAcademy
Python WebAcademyでは、Pythonの基礎からアーキテクチャなどの応用的な内容まで幅広く学べます。また、ブラウザ上で直接Pythonコードを試すことができ、実践的なスキルを身につけることが可能です。
無料で試すインフラの学習はInfraAcademy
おすすめの記事