You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

部署的天气预测App控制台持续报405 Method Not Allowed错误求助

天气预测App部署后报405 Method Not Allowed错误

我开发了一款基于OpenAI GPT-3.5-turbo的天气预测App,本地运行完全正常,但部署到Vercel、Netlify或Cloudflare平台后无法工作,控制台持续输出method (405) not allowed错误。

本地运行的HTML代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Weather Predictor</title>
    <style> 
    body {
            display: flex;
            align-items: center;
            justify-content: center;
            height: 100vh; /* Set the height of the body to 100% of the viewport height */
            margin-top: 150px; 
            margin-bottom: 150px;
            padding: 0; /* Remove default padding */
            flex-direction: column; /* Stack elements vertically */
            text-align: center; /* Center text horizontally */
            background-image: url('https://imgur.com/a/Z3uSG4q');
            background-color: #f0f0f0;
            background-size: cover; /* Cover the entire viewport */
            background-repeat: no-repeat; /* Do not repeat the image */
        }

        form {
            width: 400px; /* Set the width of the form */
            background-color: rgba(255, 255, 255, 0.8); /* Add a semi-transparent white background to the form */
            padding: 20px;
            border-radius: 10px; /* Add rounded corners */
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); /* Add a shadow effect */
        }

        input[type="submit"] {
            background-color: #4CAF50; /* Green background color */
            color: white; /* White text color */
            padding: 5px 10px; /* Padding for the button */
            font-size: 16px; /* Font size of the text */
            border: none; /* Remove the border */
            border-radius: 5px; /* Add rounded corners */
            cursor: pointer; /* Change cursor to pointer on hover */
        }

        /* Change styles on hover */
        input[type="submit"]:hover {
            background-color: #45a049; /* Darker green on hover */
        }

        /* Add any other CSS styles here */
    </style>
</head>
<body>
    <h1>Weather Predictor</h1>
    <form id="predictionForm" method="post" action="/">
        <label for="date">Date</label><br>
        <input type="text" id="date" name="date"><br><br>
        <input type="submit" value="Predict Match">
    </form><br>
    <div id="predictionResult"></div>
    <script>
        document.getElementById("predictionForm").addEventListener("submit", function(event) {
            event.preventDefault(); // Prevent default form submission

            var date = document.getElementById("date").value;

            var jsonData = {
                "date": date,
            };

            fetch('/', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify(jsonData)
            })
            .then(response => response.json())
            .then(data => {
                displayPrediction(data.prediction);
            })
            .catch(error => {
                console.error('Error:', error);
            });
        });

        function displayPrediction(prediction) {
            var predictionResultElement = document.getElementById("predictionResult");
            predictionResultElement.innerHTML = ""; // Clear previous content
            var predictionText = document.createTextNode("Prediction: " + prediction);
            predictionResultElement.appendChild(predictionText);
        }
    </script>


</body>
</html>

本地运行的Python代码

from http.server import BaseHTTPRequestHandler, HTTPServer
import json
from openai import OpenAI

# Initialize OpenAI client
client = OpenAI()

class RequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        if self.path == '/favicon.ico':
            self.send_response(404)
            self.end_headers()
            return

        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()

        with open('index.html', 'r') as file:
            html_content = file.read()

        self.wfile.write(html_content.encode('utf-8'))

    def do_POST(self):
        content_length = int(self.headers['Content-Length'])
        post_data = self.rfile.read(content_length)

        try:
            data = json.loads(post_data.decode('utf-8'))
            print("Received data:", data)

            date = data.get('date', '')

            if not date:
                prediction = "Please enter date."
            else:
                response = client.chat.completions.create(
                    model="gpt-3.5-turbo",
                    messages=[
                        {
                            "role": "system",
                            "content": "You will be provided with a date. You are to predict the weather in Lagos, Nigeria for that date. You should tell the maximum and minimum temperatures for that day and if it will rain or not. Don't talk too much, just be straight to the point and say the predicted weather"
                        },
                        {
                            "role": "user",
                            "content": f"{date}"
                        }
                    ],
                    temperature=0.1,
                    max_tokens=100,
                    top_p=1
                )
                prediction = response.choices[0].message.content

        except Exception as e:
            print("Error:", e)
            prediction = "Error occurred while generating prediction."

        # Ensure prediction is serializable
        if not isinstance(prediction, str):
            prediction = str(prediction)

        self.send_response(200)
        self.send_header('Content-type', 'application/json')
        self.end_headers()

        response_data = json.dumps({"prediction": prediction})
        self.wfile.write(response_data.encode('utf-8'))

def run(server_class=HTTPServer, handler_class=RequestHandler, port=8080):
    server_address = ('', port)
    httpd = server_class(server_address, handler_class)
    print('Starting server...')
    try:
        httpd.serve_forever()
    except KeyboardInterrupt:
        pass
    httpd.server_close()
    print('Stopping server...')

if __name__ == '__main__':
    run()

问题原因

Vercel、Netlify、Cloudflare这类平台本质是静态网站托管服务,默认只支持静态文件(HTML/CSS/JS)的部署,无法直接运行你本地使用的HTTPServer这类Python后端服务。当你发送POST请求到根路径/时,平台没有对应的后端处理逻辑,直接返回405 Method Not Allowed错误。

解决方法

需要使用这些平台提供的**无服务器函数(Serverless Functions)**来处理POST请求,将后端逻辑迁移到平台支持的函数服务中。下面以Vercel为例,给出改造步骤:

1. 调整项目结构

创建api目录,在其中新建predict.py文件(Vercel会自动识别api目录下的文件作为Serverless函数)。

2. 改造后端代码(使用Flask框架)

安装依赖:pip install flask openai,然后编写api/predict.py:

from flask import Flask, request, jsonify
from openai import OpenAI
import os

app = Flask(__name__)
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))

@app.route('/', methods=['POST'])
def predict_weather():
    try:
        data = request.get_json()
        date = data.get('date', '')
        
        if not date:
            return jsonify({"prediction": "Please enter date."})
        
        response = client.chat.completions.create(
            model="gpt-3.5-turbo",
            messages=[
                {
                    "role": "system",
                    "content": "You will be provided with a date. You are to predict the weather in Lagos, Nigeria for that date. You should tell the maximum and minimum temperatures for that day and if it will rain or not. Don't talk too much, just be straight to the point and say the predicted weather"
                },
                {
                    "role": "user",
                    "content": date
                }
            ],
            temperature=0.1,
            max_tokens=100,
            top_p=1
        )
        prediction = response.choices[0].message.content
        return jsonify({"prediction": prediction})
    
    except Exception as e:
        print(f"Error: {e}")
        return jsonify({"prediction": "Error occurred while generating prediction."})

if __name__ == '__main__':
    app.run()

3. 修改前端请求路径

将HTML中的fetch('/', { ... })改为fetch('/api/predict', { ... }),确保请求发送到Serverless函数的路径。

4. 配置环境变量

在平台的部署设置中添加OPENAI_API_KEY环境变量,填入你的OpenAI API密钥(不要硬编码在代码里)。

其他平台适配

  • Netlify:创建netlify/functions目录,将函数文件放入其中,命名为predict.py,并遵循Netlify Python函数规范(需安装netlify-lambda工具)。
  • Cloudflare:将后端逻辑改为Cloudflare Workers(支持JS/TS,或通过Python转译),或使用Cloudflare Pages Functions。

内容的提问来源于stack exchange,提问作者Wisdom Ona

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 05:50:57