admin管理员组

文章数量:1356808

I'm building my project from this template. When I deploy, I'm encountering persistent 404 NOT_FOUND errors for all Flask endpoints (e.g., /api/news-galore, /api/raw, /api/) and the root page (/) of my Next.js app fails to load on /. The deployment succeeds (READY state), but the backend doesn’t seem to be serving requests, and the frontend likely fails due to a dependent API call. I’ve tried updating vercel.json, adding pyproject.toml, and setting environment variables, but the issue persists.

Here is my directory -

nextjs-flask/
├── api/
│   ├── index.py
│   ├── requirements.txt
│   └── pyproject.toml
├── app/
│   ├── page.tsx
│   ├── components/
│   │   ├── FeedTray.tsx
│   │   ├── navbar.tsx
│   │   └── newsTile.tsx
│   └── routings/
│       ├── login/
│       │   └── page.tsx
│       ├── signup/
│       │   └── page.tsx
│       └── profile/
│           └── page.tsx
├── next.config.js
├── vercel.json
├── package.json
└── .vercelignore

Here are my endpoints file, api/index.py -

from flask import Flask, jsonify, request, make_response
from flask_cors import CORS
from dotenv import load_dotenv
import os
from news_lambda import news_app_lambda
from user_lambda import user_app_lambda
from mongoengine import connect
import boto3

load_dotenv()

app = Flask(__name__)
CORS(app, supports_credentials=True, origins=["http://localhost:3000", ";])

connect(host=os.getenv("MONGO_URI"))

@app.route('/', methods=['GET'])
def health_check():
    return jsonify({"status": "ok"}), 200

@app.route('/news-galore', methods=['GET'])
def news_galore():
    session = request.cookies.get('session')
    if not session:
        return jsonify({"error": "Unauthorized"}), 401
    lambda_client = boto3.client('lambda', region_name='us-east-1',
                                aws_access_key_id=os.getenv('AWS_ACCESS_KEY_ID'),
                                aws_secret_access_key=os.getenv('AWS_SECRET_ACCESS_KEY'))
    response = lambda_client.invoke(FunctionName='news-app-lambda',
                                   InvocationType='RequestResponse',
                                   Payload=bytes(json.dumps({"session": session}).encode()))
    return jsonify(json.loads(response['Payload'].read().decode('utf-8'))), 200

@app.route('/raw', methods=['GET'])
def hello_world():
    session = request.cookies.get('session')
    if not session:
        return jsonify({"error": "Unauthorized"}), 401
    lambda_client = boto3.client('lambda', region_name='us-east-1',
                                aws_access_key_id=os.getenv('AWS_ACCESS_KEY_ID'),
                                aws_secret_access_key=os.getenv('AWS_SECRET_ACCESS_KEY'))
    response = lambda_client.invoke(FunctionName='news-app-lambda',
                                   InvocationType='RequestResponse',
                                   Payload=bytes(json.dumps({"session": session}).encode()))
    return jsonify(json.loads(response['Payload'].read().decode('utf-8'))), 200

@app.route('/signup', methods=['POST'])
def signup():
    data = request.get_json()
    email = data.get('email')
    password = data.get('password')
    # Signup logic here
    return jsonify({"message": "Signup successful"}), 200

@app.route('/login', methods=['POST'])
def login():
    data = request.get_json()
    email = data.get('email')
    password = data.get('password')
    # Login logic here
    resp = make_response(jsonify({"message": "Login successful"}))
    resp.set_cookie('session', 'dummy_session_token', httponly=True)
    return resp, 200

@app.route('/logout', methods=['GET'])
def logout():
    resp = make_response(jsonify({"message": "Logout successful"}))
    resp.set_cookie('session', '', expires=0)
    return resp, 200

@app.route('/user', methods=['GET'])
def get_user():
    session = request.cookies.get('session')
    if not session:
        return jsonify({"error": "Unauthorized"}), 401
    # User logic here
    return jsonify({"user": "user_data"}), 200

@app.route('/preferences', methods=['POST'])
def update_preferences():
    session = request.cookies.get('session')
    if not session:
        return jsonify({"error": "Unauthorized"}), 401
    data = request.get_json()
    preferences = data.get('preferences')
    # Preferences logic here
    return jsonify({"message": "Preferences updated"}), 200

if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port=5000)

requirements.txt -

flask==2.3.3
flask-cors==4.0.0
requests==2.31.0
python-dotenv==1.0.0
boto3==1.28.57
werkzeug==3.0.1
mongoengine==0.27.0
pymongo==4.5.0

Here is pyproject.toml -

[tool.vercel]
runtime = "python3.9"

[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"

[project]
name = "news-app-flask"
version = "0.1.0"
dependencies = [
    "flask==2.3.3",
    "flask-cors==4.0.0",
    "requests==2.31.0",
    "python-dotenv==1.0.0",
    "boto3==1.28.57",
    "werkzeug==3.0.1",
    "mongoengine==0.27.0",
    "pymongo==4.5.0"
]

Here is next.config.js -

    /** @type {import('next').NextConfig} */
const nextConfig = {
    rewrites: async () => {
        return [
            {
                source: '/api/:path*',
                destination:
                    process.env.NODE_ENV === 'development'
                        ? 'http://127.0.0.1:5000/api/:path*'
                        : '/api/:path*',
            },
        ];
    },
};

module.exports = nextConfig;

app/page.tsx -

"use client";

import { useEffect, useState } from "react";
import FeedTray from "../components/FeedTray";

export default function Home() {
    const [isAuthenticated, setIsAuthenticated] = useState(false);

    useEffect(() => {
        fetch("/api/news-galore", { credentials: "include" })
            .then((response) => response.json())
            .then((data) => {
                if (data.error !== "Unauthorized") {
                    setIsAuthenticated(true);
                }
            })
            .catch((error) => console.error("Error fetching news:", error));
    }, []);

    return isAuthenticated ? <FeedTray /> : null;
}
...

here is vercel deployment log snippets -

[client-debug] 2025-04-03T18:25:45.297Z Deployment state changed to READY
[client-debug] 2025-04-03T18:25:45.297Z Yielding a 'ready' event
> [debug] [2025-04-03T18:25:45.297Z] Spinner invoked (Completing) with a 0ms delay
[client-debug] 2025-04-03T18:25:45.297Z Deployment alias assigned
❗️  Due to `builds` existing in your configuration file, the Build and Development Settings defined in your Project Settings will not apply. Learn More: /unused-build-settings

curl tests -

curl -X GET /api/news-galore -b "session=your-session-cookie"
The page could not be found
NOT_FOUND
bom1::h7mvg-1743703843749-4884836164a0

curl -X GET /api/
The page could not be found
NOT_FOUND
bom1::6d666-1743703058469-f05ee13be576

Can anyone help me identify why the Flask backend isn’t serving requests on Vercel and why the Next.js root page isn’t loading? I’d appreciate guidance on debugging the Vercel runtime logs or suggestions for fixing the configuration. Thank you!

I'm building my project from this template. When I deploy, I'm encountering persistent 404 NOT_FOUND errors for all Flask endpoints (e.g., /api/news-galore, /api/raw, /api/) and the root page (/) of my Next.js app fails to load on https://newsapp-parthgupta.vercel.app/. The deployment succeeds (READY state), but the backend doesn’t seem to be serving requests, and the frontend likely fails due to a dependent API call. I’ve tried updating vercel.json, adding pyproject.toml, and setting environment variables, but the issue persists.

Here is my directory -

nextjs-flask/
├── api/
│   ├── index.py
│   ├── requirements.txt
│   └── pyproject.toml
├── app/
│   ├── page.tsx
│   ├── components/
│   │   ├── FeedTray.tsx
│   │   ├── navbar.tsx
│   │   └── newsTile.tsx
│   └── routings/
│       ├── login/
│       │   └── page.tsx
│       ├── signup/
│       │   └── page.tsx
│       └── profile/
│           └── page.tsx
├── next.config.js
├── vercel.json
├── package.json
└── .vercelignore

Here are my endpoints file, api/index.py -

from flask import Flask, jsonify, request, make_response
from flask_cors import CORS
from dotenv import load_dotenv
import os
from news_lambda import news_app_lambda
from user_lambda import user_app_lambda
from mongoengine import connect
import boto3

load_dotenv()

app = Flask(__name__)
CORS(app, supports_credentials=True, origins=["http://localhost:3000", "https://newsapp-parthgupta.vercel.app"])

connect(host=os.getenv("MONGO_URI"))

@app.route('/', methods=['GET'])
def health_check():
    return jsonify({"status": "ok"}), 200

@app.route('/news-galore', methods=['GET'])
def news_galore():
    session = request.cookies.get('session')
    if not session:
        return jsonify({"error": "Unauthorized"}), 401
    lambda_client = boto3.client('lambda', region_name='us-east-1',
                                aws_access_key_id=os.getenv('AWS_ACCESS_KEY_ID'),
                                aws_secret_access_key=os.getenv('AWS_SECRET_ACCESS_KEY'))
    response = lambda_client.invoke(FunctionName='news-app-lambda',
                                   InvocationType='RequestResponse',
                                   Payload=bytes(json.dumps({"session": session}).encode()))
    return jsonify(json.loads(response['Payload'].read().decode('utf-8'))), 200

@app.route('/raw', methods=['GET'])
def hello_world():
    session = request.cookies.get('session')
    if not session:
        return jsonify({"error": "Unauthorized"}), 401
    lambda_client = boto3.client('lambda', region_name='us-east-1',
                                aws_access_key_id=os.getenv('AWS_ACCESS_KEY_ID'),
                                aws_secret_access_key=os.getenv('AWS_SECRET_ACCESS_KEY'))
    response = lambda_client.invoke(FunctionName='news-app-lambda',
                                   InvocationType='RequestResponse',
                                   Payload=bytes(json.dumps({"session": session}).encode()))
    return jsonify(json.loads(response['Payload'].read().decode('utf-8'))), 200

@app.route('/signup', methods=['POST'])
def signup():
    data = request.get_json()
    email = data.get('email')
    password = data.get('password')
    # Signup logic here
    return jsonify({"message": "Signup successful"}), 200

@app.route('/login', methods=['POST'])
def login():
    data = request.get_json()
    email = data.get('email')
    password = data.get('password')
    # Login logic here
    resp = make_response(jsonify({"message": "Login successful"}))
    resp.set_cookie('session', 'dummy_session_token', httponly=True)
    return resp, 200

@app.route('/logout', methods=['GET'])
def logout():
    resp = make_response(jsonify({"message": "Logout successful"}))
    resp.set_cookie('session', '', expires=0)
    return resp, 200

@app.route('/user', methods=['GET'])
def get_user():
    session = request.cookies.get('session')
    if not session:
        return jsonify({"error": "Unauthorized"}), 401
    # User logic here
    return jsonify({"user": "user_data"}), 200

@app.route('/preferences', methods=['POST'])
def update_preferences():
    session = request.cookies.get('session')
    if not session:
        return jsonify({"error": "Unauthorized"}), 401
    data = request.get_json()
    preferences = data.get('preferences')
    # Preferences logic here
    return jsonify({"message": "Preferences updated"}), 200

if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port=5000)

requirements.txt -

flask==2.3.3
flask-cors==4.0.0
requests==2.31.0
python-dotenv==1.0.0
boto3==1.28.57
werkzeug==3.0.1
mongoengine==0.27.0
pymongo==4.5.0

Here is pyproject.toml -

[tool.vercel]
runtime = "python3.9"

[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"

[project]
name = "news-app-flask"
version = "0.1.0"
dependencies = [
    "flask==2.3.3",
    "flask-cors==4.0.0",
    "requests==2.31.0",
    "python-dotenv==1.0.0",
    "boto3==1.28.57",
    "werkzeug==3.0.1",
    "mongoengine==0.27.0",
    "pymongo==4.5.0"
]

Here is next.config.js -

    /** @type {import('next').NextConfig} */
const nextConfig = {
    rewrites: async () => {
        return [
            {
                source: '/api/:path*',
                destination:
                    process.env.NODE_ENV === 'development'
                        ? 'http://127.0.0.1:5000/api/:path*'
                        : '/api/:path*',
            },
        ];
    },
};

module.exports = nextConfig;

app/page.tsx -

"use client";

import { useEffect, useState } from "react";
import FeedTray from "../components/FeedTray";

export default function Home() {
    const [isAuthenticated, setIsAuthenticated] = useState(false);

    useEffect(() => {
        fetch("/api/news-galore", { credentials: "include" })
            .then((response) => response.json())
            .then((data) => {
                if (data.error !== "Unauthorized") {
                    setIsAuthenticated(true);
                }
            })
            .catch((error) => console.error("Error fetching news:", error));
    }, []);

    return isAuthenticated ? <FeedTray /> : null;
}
...

here is vercel deployment log snippets -

[client-debug] 2025-04-03T18:25:45.297Z Deployment state changed to READY
[client-debug] 2025-04-03T18:25:45.297Z Yielding a 'ready' event
> [debug] [2025-04-03T18:25:45.297Z] Spinner invoked (Completing) with a 0ms delay
[client-debug] 2025-04-03T18:25:45.297Z Deployment alias assigned
❗️  Due to `builds` existing in your configuration file, the Build and Development Settings defined in your Project Settings will not apply. Learn More: https://vercel.link/unused-build-settings

curl tests -

curl -X GET https://newsapp-parthgupta.vercel.app/api/news-galore -b "session=your-session-cookie"
The page could not be found
NOT_FOUND
bom1::h7mvg-1743703843749-4884836164a0

curl -X GET https://newsapp-parthgupta.vercel.app/api/
The page could not be found
NOT_FOUND
bom1::6d666-1743703058469-f05ee13be576

Can anyone help me identify why the Flask backend isn’t serving requests on Vercel and why the Next.js root page isn’t loading? I’d appreciate guidance on debugging the Vercel runtime logs or suggestions for fixing the configuration. Thank you!

Share Improve this question edited Apr 3 at 20:07 Parth Gupta asked Mar 27 at 21:57 Parth GuptaParth Gupta 214 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

I couldn't find any clear solution so I am deploying backend and frontend separately.

本文标签: