Невозможно получить данные из Flask из React при развертывании на Heroku, но работает локально - PullRequest
0 голосов
/ 02 августа 2020

Я пытаюсь разместить веб-приложение, созданное с помощью React, и его REST api, созданный с помощью Python + Flask на Heroku. Если я обслуживаю его локально с помощью npm start, я могу успешно читать и использовать данные JSON из Flask. Однако, если я попытаюсь сделать то же самое на Heroku - даже с установленным прокси - я обнаружу, что JSON не может быть прочитано.

Я попытался изменить JSON, чтобы он читался как текст, а также добавление заголовков application/json, но безрезультатно. Несмотря на то, что приложение работает локально, оно по-прежнему не может считывать данные из своего внутреннего аналога. Вместо этого возникает следующая ошибка: (index):1 Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0. Если я попытаюсь распечатать ответ в виде текста с fetch('/api/multiply/10').then(res => res.text()).then(data => { console.log(data) }), я получу кучу HTML, которая не соответствует простому тексту, возвращенному на локальном сервере.

На локально работающий сервер я получаю ожидаемый { "result": 100 }, а с Heroku и той же командой я получаю значение по умолчанию HTML:

<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><title>React App</title><link href="/static/css/2.3c095960.chunk.css" rel="stylesheet"><link href="/static/css/main.f2d4b2b8.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(e){function r(r){for(var n,p,i=r[0],l=r[1],a=r[2],f=0,s=[];f<i.length;f++)p=i[f],Object.prototype.hasOwnProperty.call(o,p)&&o[p]&&s.push(o[p][0]),o[p]=0;for(n in l)Object.prototype.hasOwnProperty.call(l,n)&&(e[n]=l[n]);for(c&&c(r);s.length;)s.shift()();return u.push.apply(u,a||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,i=1;i<t.length;i++){var l=t[i];0!==o[l]&&(n=!1)}n&&(u.splice(r--,1),e=p(p.s=t[0]))}return e}var n={},o={1:0},u=[];function p(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,p),t.l=!0,t.exports}p.m=e,p.c=n,p.d=function(e,r,t){p.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},p.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},p.t=function(e,r){if(1&r&&(e=p(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(p.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)p.d(t,n,function(r){return e[r]}.bind(null,n));return t},p.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return p.d(r,"a",r),r},p.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},p.p="/";var i=this["webpackJsonpchinese-resource-app"]=this["webpackJsonpchinese-resource-app"]||[],l=i.push.bind(i);i.push=r,i=i.slice();for(var a=0;a<i.length;a++)r(i[a]);var c=l;t()}([])</script><script src="/static/js/2.e64d4889.chunk.js"></script><script src="/static/js/main.7180a907.chunk.js"></script></body></html>

Соответствующий контент из App.tsx:

import React, { useState, useEffect } from 'react';
...
...
function App() {
  const [result, setResult] = useState(0);
  useEffect(() => {
    fetch("/api/multiply/10", {
      headers : {
      'Content-Type': 'application/json',
      'Accept': 'application/json'
      }
    }).then(res => res.json()).then(data => {
      // setResult(data)
      console.log(data)
      console.log(data) // should show {result: 100}
    })
  }, []);

Бэкэнд:

from flask import Flask, request
from flask_restful import Resource, Api

app = Flask(__name__)
api = Api(app)

class ComplexExample(Resource):
    """
    Demonstrates a GET request with parameters.
    """

    def get(self, num):
        return {"result": num * 10}


api.add_resource(
    ComplexExample, "/api/multiply/<int:num>"
)

Соответствующие строки из package.json:

  "scripts": {
    "start": "npm-run-all --parallel scriptstart api",
    "scriptstart": "react-scripts start",
    "api": "cd api && flask run",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  ...
  "proxy": "http://localhost:5000"
}

Я что-то упустил или есть ли способ успешно разместить Flask REST api и интерфейс React на Heroku? В настоящее время веб-сайт размещается здесь: https://test-mandarin-web-app.herokuapp.com.

Вы можете просмотреть репозиторий и остальной код здесь: https://github.com/Destaq/chinese-resource-app/tree/268a747bf6f803e328d96caeb9b81719154b4ec0

1 Ответ

0 голосов
/ 02 августа 2020

Вы получаете 502 при доступе к API. У вас либо обратный прокси (nginx), либо серверная часть неправильно сконфигурированы, либо и то, и другое. Не могу сказать больше, не зная, как вы развертываете.

...