将带有 fetch 的 POST 发送到烧瓶时的端口问题
Posted
技术标签:
【中文标题】将带有 fetch 的 POST 发送到烧瓶时的端口问题【英文标题】:port issue when sending POST with fetch to flask 【发布时间】:2021-02-19 22:22:17 【问题描述】:我的情况的小背景:
我的 VPS 上有一个具有公共 IP 的应用程序。 VPS 基于 centOS7,我想通过 fetch 从我的 javascript 客户端向服务器发送 POST 查询。从服务器端,我使用烧瓶接收 POST 数据。
服务器端httpd.conf:
<Directory "/var/www/html/wet-pogotowie.pl">
<IfModule mod_headers.c>
AllowOverride All
Require all granted
Header add Access-Control-Allow-Origin "https://wet-pogotowie.pl"
Allow from all
</IfModule>
</Directory>
烧瓶代码:
from flask import Flask, request, jsonify
import json
app = Flask(__name__)
@app.route("/api", methods=['GET', 'POST'])
def json():
content = request.json
return content
context = ('/var/.certs/cert.crt', '/var/.certs/priv.key')
if __name__ == '__main__':
app.run(host = 'wet-pogotowie.pl', port = 443, ssl_context = context, debug = True)
JS 的 fetch:
time = setInterval(function()
var zzz = "xyz": "123";
const data = JSON.stringify(zzz);
const options =
method: 'POST',
body: data,
mode: 'cors',
headers:
'content-type': 'application/json',
'Access-Control-Allow-Origin': 'https://wet-pogotowie.pl',
'Access-Control-Request-Method': 'GET, POST, DELETE, PUT, OPTIONS',
'Access-Control-Allow-Credentials': 'true',
crossorigin: true,
,
;
fetch('https://wet-pogotowie.pl/api', options) // TU DZILA, NIE DZIALA Z PORTEM
.then(response => response)
.then(data =>
// if everting is ok should log the object message: "Long lang sent to express" from server
console.log(data)
);
, 9000);
问题是: 我无法在烧瓶中设置端口 443,因为它当然被占用了,但是当我尝试在 fetch 中设置其他端口时 - 'SAME ORIGIN POLICY' - 出现 CORS 错误。
我的问题: 我需要改变的地方和内容?我是否需要更改代码或服务器端的某些内容?
其他信息: 当 fetch 设置为默认 80 端口时 - POST 有效,浏览器中的控制台登录显示它,但收到 404 错误。
更新:
我已将服务器从 apache 更改为 nginx,这是nginx.conf
文件的一部分:
http
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
server
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
server_name www.wet-pogotowie.pl;
root /var/www/html/www.wet-pogotowie.pl;
# process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0;
ssl_certificate "/var/.certs/cert.crt";
ssl_certificate_key "/var/.certs/priv.key";
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 10m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
#
# # Load configuration files for the default server block.
# include /etc/nginx/default.d/*.conf;
location /api
if ($request_method = 'OPTIONS')
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
#
# Custom headers and headers various browsers *should* be OK with but aren't
#
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
#
# Tell client that this pre-flight info is valid for 20 days
#
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
if ($request_method = 'POST')
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
if ($request_method = 'GET')
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
proxy_pass https://www.wet-pogotowie.pl:3000;
main.js:
time=setInterval(function()
const data = "patrz wredny"
const options =
method: 'get',
mode: 'no-cors',
headers:
'content-type': 'application/json',
'Access-Control-Allow-Origin': 'wet-pogotowie.pl',
'Access-Control-Request-Method': 'GET, POST, DELETE, PUT, OPTIONS',
'Access-Control-Allow-Credentials': 'true',
'Access-Control-Allow-Headers': 'wet-pogotowie.pl',
,
fetch('https://wet-pogotowie.pl:3000/api',options)
.then(response => response)
.then(data =>
// if everting is ok should log the object message: "Long lang sent to express" from server
console.log(data)
);
,9000);
Flask 代码是相同的 - 只有 diff 端口设置为 3000 并启用 SSL_CONTEXT。 我的观点是 - 如何从 JS 的前端向 python 的烧瓶发送或接收 GET/POST?
【问题讨论】:
【参考方案1】:我认为这里有一些令人困惑的事情。
通常,您的应用程序不会直接侦听端口 80 或端口 443,尽管这当然是可能的。在共享托管环境中,这肯定不太可能。相反,您配置 nginx(或者我认为那是您那里的 Apache 配置?伙计,我没有意识到人们仍然使用它)来反向代理到您的 python / node / ruby 应用程序。您的应用会在任何您喜欢的环回端口上侦听,例如 8080 或 9000 等。您不想自己进行 SSL 终止或静态文件托管,让 nginx(或其他)为您完成。
您是否需要跨源的东西也不清楚。网站调用的是同域的api吗?
对端口 80 的 fetch 调用“有效”,因为 nginx/apache 尝试提供该 URI,但您得到 404,因为(我猜)您没有将流量正确路由到后端 python 代码。
也许发布更多关于哪个托管、哪个 httpd 以及您在开发中使用的内容。
【讨论】:
以上是关于将带有 fetch 的 POST 发送到烧瓶时的端口问题的主要内容,如果未能解决你的问题,请参考以下文章
从画布正确获取信息并通过带有 node-fetch 的 webhook 将信息发送到 discord 时出现问题