将带有 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;
    

ma​​in.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 时出现问题

使用 fetch 发送带有数据对象的 get 请求

JSON“POST”到烧瓶视图不起作用

使用 Fetch API 将数据发送到 PHP 服务器(首选 POST 方法和 JSON)

带有请求的烧瓶损坏的管道

烧瓶返回图像对象