1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Webアプリのネットワーク設定に半日はまった話

Posted at

フロントエンドにReact、バックエンドにFlaskを使用してWebアプリを作ろうとしたときハマったことを、備忘録としてまとめておきます。間違っている部分、追加部分ございましたらどんどん教えてください。

ハマった内容

  1. post先の関数名が間違っている。
  2. テーブルへのデータ書き込みは事前に行う
  3. net::ERR_EMPTY_RESPONSE が起きる。
  4. CORS エラーが起きる。

Postを送る前に確認すべきこと

1. 関数名間違い

Postの送り先の関数名が合っているか確認する(大文字、小文字も合わせる)。

フロントエンド側
フロントエンド.png

バックエンド側
バックエンド.png

2. テーブルへのデータ書き込み確認

バックエンド側で事前にデバッグを行っておくと、フロントエンド側との連携がスムーズになります。テーブルにデータを書き込む確認は、以下のように簡単に行うことができます。

import os

from flask import Flask, flash, jsonify, render_template, request
from flask_cors import CORS
from flask_marshmallow import Marshmallow
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.exc import IntegrityError, SQLAlchemyError

from src.utils import get_db_connect_url

URI = get_db_connect_url("postgres")

def create_app(uri: str) -> Flask:
    """
    Flaskアプリを作成する
    """
    app = Flask(__name__)
    app.config["SQLALCHEMY_DATABASE_URI"] = uri
    app.config["SECRET_KEY"] = os.environ.get("SECRET_KEY")
    return app

app = create_app(URI)
db = SQLAlchemy(app)
ma = Marshmallow(app)
CORS(app, origins=["http://127.0.0.1:5173"])

class Base(db.Model):
    __abstract__ = True

class tableUser(Base):
    """
    ユーザーのテーブル
    """

    __tablename__ = "User"
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)
    password = db.Column(db.String(120), nullable=False)

if __name__ == "__main__":
		# 値の書き込み確認
		username = "hogehoge"
		email = "hogehoge@gmial.com"
		password = "hogehoge"
		new_user = tableUser(username=username, email=email, password=password)

relationを使っている場合、この段階でエラーが発生しデータの書き込みができません。フロントエンド側と合わせてデバッグを行おうとすると、CORS エラーなど他のエラーとしてブラウザ側に表示されるため、発見が難しいです(この辺り、まとめてデバッグする方法もあるかもしれません…)。よって、事前のデバッグがおすすめです。

Docker を使用した開発で確認すべきこと

1. net::ERR_EMPTY_RESPONSE が起き

1.1. 原因

Dockerコンテナは -p コマンドもしくはdocker-compose.ymlの設定を使用してhostマシンとコンテナのポートを繋げておかないと(マッピングという)、コンテナの外部から内部にアクセスができない仕組みになっています。

例えば、docker run を使用してコンテナを構築する際には以下のようなコマンドを使用することができます。

docker run -d --name http_server -p 3000:3000 python:3.11 python -m http.server -b localhost

docker-compose.ymlを使用する場合は、以下のように記述します。

version: "3"

services:
  react-app:
    build:
      args:
        - BASE_IMAGE=node:latest
      context: .
      dockerfile: ./app/react_Dockerfile
    tty: true
    volumes:
      - ../app:/home/
    ports:
      - 3000:3000

この設定により、host側のポート3000をコンテナ側のポート3000にマッピングしました。しかし、この状態でlocalhost:3000にアクセスしてもコンテナ内のサーバにまでアクセスすることはできません。これは、ホスト側のlocalhostとコンテナ側のlocalhostが異なるためです。下記の記事で詳細に解説されています。

1.2. 解決方法

記事で述べられている通り、コンテナ側のサーバのIPアドレスを0.0.0.0にすることで問題を解決できました。

Flask の場合、以下のようにすることでサーバのIPアドレスとポートを指定することができます。

app.run(debug=True, host="0.0.0.0", port=5000)

2. CORS エラーが起きる

2.1. 原因

上記のエラーと同様、フロントエンド側からバックエンド側にアクセスする際に発生するエラーです。メッセージは以下の通りです。

Access to XMLHttpRequest at 'http://localhost:5000/register' from origin 'http://127.0.0.1:5173' has been blocked by CORS policy

CORSとは、オリジン間リソース共有 (Cross-Origin Resource Sharing) の略で、異なるオリジンからのアクセスを制限する仕組みのこと。

オリジンとは、URL中のスキーム (プロトコル)、 ホスト (ドメイン)、 ポート番号の組み合わせのこと

  • http://example.com の場合
    • スキーム:http
    • ホスト:example.com
    • ポート: 80 (省略可能)
  • 以下のようにスキーム (http) とホスト名 (example.com) が同じ場合は同一オリジン
    • http://example.com/app1/index.html
    • http://example.com/app2/index.html

下記の記事を参考にしました。

2.2. 解決方法

バックエンド側にflask_corsを追加することで解決しました。

以下、GitHub Cpilotの回答になります。

この問題を解決するには、FlaskアプリケーションでCORSを許可する必要があります。Flask-CORSという拡張を使用すると、簡単にCORSを設定できます。

まず、Flask-CORSをインストールします:

pip install -U flask-cors

次に、FlaskアプリケーションでCORSを有効にします:

from flask_cors import CORS

app = Flask(__name__)
CORS(app)

これで、すべてのオリジンからのリクエストが許可されます。特定のオリジンのみを許可するには、CORS関数にオリジンを指定します:

CORS(app, origins=["http://127.0.0.1:5173"])

これで、CORSエラーが解消されるはずです。

CORS(app, origins=["****"]) の * * * * 部分はフロントエンド側のデバッグの際にブラウザに表示されているURLとポートを指定してください。

url.png

まとめ

以上が今回ハマったエラーになります。Webアプリは初心者のため1回ハマると1つ解決するだけでもとても時間がかかりました。この情報が何かお役に立てればと思います。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?