DevHyperCoder
DevHyperCoder

Reputation: 943

Flask + React GET Request is failing but POST Request is successful

I am a bit of a beginner to React. I developed a Flask backend and now i want to pair it with React for frontend.

I am using fetch in React to make the GET Request. When i read the data, the text or the response when i call response.text() is the index.html file in the public directory of my app

Here is my react code:

componentDidMount() {
    fetch('/')
      .then(response => {
        console.log(response.text()) //Here is the text() i said before
        this.setState({ snippets: response.data })
      })
      .catch(error=>{
        console.log(error)
      })
  }

Here is the MRE of my flask app:

@app.route('/')
def index():
    return {'snippets':['blah','blaha']

My proxy in package.json

    "proxy": "http://127.0.0.1:5000/"

My flask backend is running at port 5000 and react at port 3000

One thing to note is that a POST request (from <form>) does get proxied to the backend server and i can retrieve the contents of the POST request in flask. Its the GET request using fetch that isn't working.

Directory structure:

-env
-getcode
  -templates
  -static
  -__init__.py
  -routes.py
-getcode-client
  -src
  -public
run.py

Here getcode is the directory of the flask app and getcode-client contains the React app created using create-react-app

NOTE: Also i tried to setup a manual proxy like this: https://create-react-app.dev/docs/proxying-api-requests-in-development/#configuring-the-proxy-manually

but now the react app is not shown. it completely shows my flask backend's json output.

Package.json:

{
    "name": "getcode-client",
    "version": "0.1.0",
    "private": true,
    "dependencies": {
        "@testing-library/jest-dom": "^4.2.4",
        "@testing-library/react": "^9.3.2",
        "@testing-library/user-event": "^7.1.2",
        "axios": "^0.19.2",
        "http-proxy-middleware": "^1.0.3",
        "react": "^16.13.1",
        "react-dom": "^16.13.1",
        "react-router-dom": "^5.1.2",
        "react-scripts": "3.4.1"
    },
    "scripts": {
        "start": "react-scripts start",
        "build": "react-scripts build",
        "test": "react-scripts test",
        "eject": "react-scripts eject"
    },
    "eslintConfig": {
        "extends": "react-app"
    },
    "browserslist": {
        "production": [
            ">0.2%",
            "not dead",
            "not op_mini all"
        ],
        "development": [
            "last 1 chrome version",
            "last 1 firefox version",
            "last 1 safari version"
        ]
    }
}

Upvotes: 2

Views: 4558

Answers (4)

Chih Sean Hsu
Chih Sean Hsu

Reputation: 433

Latest update: Sorry about I misunderstood about proxy in nodejs, and fetch() can support this kind of proxy.

After I do some trial and error, you just need to change you path '/' to '/something_else' and the proxy work well.

@app.route('/test', methods=['GET', 'POST'])
def index():
    return {'snippets':['blah','blaha']}
componentDidMount() {
    fetch('/test')
      .then(response => {
        console.log(response.text()) //Here is the text() i said before
        this.setState({ snippets: response.data })
      })
      .catch(error=>{
        console.log(error)
      })
  }

Wrong information:

This is not issue about python and flask.

You use fetch() in javascript, and this is native js function, so it is not related with proxy you set in package.json.

If you want to use fetch() to get other port, you have to give it the whole url http://localhost:5000/ or you will get the same port of you react app.

fetch('http://localhost:5000/')
      .then(response => {
        console.log(response.text()) //Here is the text() i said before
        this.setState({ snippets: response.data })
      })
      .catch(error => {
        console.log(error)
      });

There are some packages you can use like fetch-with-proxy or node-https-proxy-agent, fetch-with-proxy can get HTTP_PROXY env var to set proxy, and you can use the other create proxy agent.

But I recommend that to use other package to send request like axios.

import axios from 'axios';
const axios_ = axios.create({
  baseURL: 'http://localhost:5000',
  headers: { 'Content-Type': 'application/json' },
})

class App extends React.Component  {
  componentDidMount() {
    axios_.get('/')
      .then(response => {
        console.log(response.text()) //Here is the text() i said before
        this.setState({ snippets: response.data })
      })
      .catch(error => {
        console.log(error)
      });
  }
...}

Actually, the proxy you mean is not the proxy we usually talk about, what you want to do is just to point to another port to get the response.

Proxy is about a tunnel or something between your client to server.

Further more, you also can search for reverse proxy that will be the question you want to know too.

Upvotes: 2

random_number
random_number

Reputation: 1

I am also relatively new to react. Recently I wrote a flask API and was testing it with a react frontend. There are two things that i did differently to get things working.

  1. My componentDidMount would look something like this using the docs

componentDidMount() {
  fetch('/').then(response => {
    return response.text();
  }).then(response => {
    this.setState({ snippets: response.data })
  }).catch(error=>{
    console.log(error)
  });
}
  1. I use the flask_cors package to prevent CORS related issues. Implementation would be something like this
from flask_cors import cross_origin


@cross_origin(origin="*")
@app.route('/')
def index():
   return {'snippets':['blah','blaha']

I haven't made any changes to my package.json to get the connection between the React frontend and the flask api backend. Hope this helps and good luck with your troubleshooting.

Upvotes: 0

Damian Busz
Damian Busz

Reputation: 1848

Since you are using CRA I would suggest to use their proxy setting.

To tell the development server to proxy any unknown requests to your API server in development, add a proxy field to your package.json, for example:

"proxy": "http://localhost:4000",

In your case this will be on port 5000.

Here is more on the topic.

However, on production I would suggest to use nginx or apache to avoid issues in the future.

@Edit This is how package.json should look in your case

{
"name": "getcode-client",
"version": "0.1.0",
"private": true,
"dependencies": {
    "@testing-library/jest-dom": "^4.2.4",
    "@testing-library/react": "^9.3.2",
    "@testing-library/user-event": "^7.1.2",
    "axios": "^0.19.2",
    "http-proxy-middleware": "^1.0.3",
    "react": "^16.13.1",
    "react-dom": "^16.13.1",
    "react-router-dom": "^5.1.2",
    "react-scripts": "3.4.1"
},
"scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
},
"proxy": "http://localhost:5000",
"eslintConfig": {
    "extends": "react-app"
},
"browserslist": {
    "production": [
        ">0.2%",
        "not dead",
        "not op_mini all"
    ],
    "development": [
        "last 1 chrome version",
        "last 1 firefox version",
        "last 1 safari version"
    ]
}  }

Upvotes: -1

Dex
Dex

Reputation: 122

I am not sure, but I think that the problem is that your using both React and Flask on localhost, and not specifying the port in the fetch requests, try this:

componentDidMount() {
    fetch('/:5000')
      .then(response => {
        console.log(response.text()) //Here is the text() i said before
        this.setState({ snippets: response.data })
      })
      .catch(error=>{
        console.log(error)
      })
  }

Or if that doesn't help, maybe change the proxy settings as:

"proxy": "127.0.0.1:5000"

Upvotes: 0

Related Questions