node-fetch与requests请求差异排查:JS报错Python正常问题
问题排查:Node.js node-fetch POST请求500错误 vs Python requests正常
问题背景
两段逻辑看似一致的POST请求代码,Python版使用requests库可正常获取响应,但Node.js版使用node-fetch时返回500内部服务器错误,需定位差异及报错原因。
相关代码
Node.js 代码(报错版本)
import fetch from 'node-fetch'; const url = "http://host3.dreamhack.games:15592/img_viewer" const imageUrl = "/static/dream.png" const data = { "url": imageUrl } const res = await fetch(url, { method: "POST", body: JSON.stringify(data) }) const text = await res.text() console.log(text) // 返回内容: // <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> // <title>500 Internal Server Error</title> // <h1>Internal Server Error</h1> // <p>The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.</p>
Python 代码(正常版本)
import requests url = "http://host3.dreamhack.games:15592/img_viewer" imageUrl = "/static/dream.png" data = { "url": imageUrl } response = requests.post(url, data=data) print(response.text)
后端 Flask 服务代码
@app.route("/img_viewer", methods=["GET", "POST"]) def img_viewer(): if request.method == "GET": return render_template("img_viewer.html") elif request.method == "POST": url = request.form.get("url", "") urlp = urlparse(url) if url[0] == "/": url = "http://localhost:8000" + url elif ("localhost" in urlp.netloc) or ("127.0.0.1" in urlp.netloc): data = open("error.png", "rb").read() img = base64.b64encode(data).decode("utf8") return render_template("img_viewer.html", img=img) try: data = requests.get(url, timeout=3).content img = base64.b64encode(data).decode("utf8") except: data = open("error.png", "rb").read() img = base64.b64encode(data).decode("utf8") return render_template("img_viewer.html", img=img)
差异分析
核心差异在于请求数据格式与Content-Type头:
- Python
requests.post(url, data=data):默认将数据编码为application/x-www-form-urlencoded格式的表单数据,自动设置对应Content-Type头,后端request.form.get("url")可以正确提取参数。 - Node.js
fetch用JSON.stringify(data)作为body:默认Content-Type为text/plain,后端request.form无法解析JSON格式的数据,因此url = request.form.get("url", "")得到的是空字符串。
报错原因
后端代码中,当url为空字符串时,执行if url[0] == "/"会抛出TypeError(空字符串没有索引0),而后端的except块仅捕获requests.get相关的异常,未处理此类型错误,最终触发Flask的500内部服务器错误。
修复方案
将Node.js请求改为发送application/x-www-form-urlencoded格式的表单数据,有两种实现方式:
方式1:使用URLSearchParams构造表单数据
import fetch from 'node-fetch'; import { URLSearchParams } from 'url'; const url = "http://host3.dreamhack.games:15592/img_viewer" const imageUrl = "/static/dream.png" const params = new URLSearchParams(); params.append('url', imageUrl); const res = await fetch(url, { method: "POST", body: params }) const text = await res.text() console.log(text)
方式2:手动编码表单数据并设置Content-Type
import fetch from 'node-fetch'; const url = "http://host3.dreamhack.games:15592/img_viewer" const imageUrl = "/static/dream.png" const data = `url=${encodeURIComponent(imageUrl)}`; const res = await fetch(url, { method: "POST", body: data, headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }) const text = await res.text() console.log(text)
内容的提问来源于stack exchange,提问作者lubiksss
相关产品推荐
相关产品推荐

