13

I'm using pretty small create-react-app running on port 3000 setup to proxy requests to backend server running on port 8080. If I put in the browser address bar http://localhost:3000/api/me I get back the index.html page but if I use fetch API to get /api/me it try to call to by backend.

The problem is that I have to authenticate with the backend which will set a cookie but since I can't access the login page on http://localhost:3000/login I can't get the cookie.

On a different project which I've eject from create-react-app I have small file to run webpack-dev-server wih the configuration

  proxy: {
    "*": "http://localhost:9191"
  }

which does proxy requests even when put into the browser address bar.

Is it possible to create such setup in create-react-app?

4 Answers 4

19

Closer look into create-react-app code reveal that this is by design:

For single page apps, we generally want to fallback to /index.html. However we also want to respect proxy for API calls. So if proxy is specified, we need to decide which fallback to use. We use a heuristic: if request accepts text/html, we pick /index.html. Modern browsers include text/html into accept header when navigating. However API calls like fetch() won’t generally accept text/html. If this heuristic doesn’t work well for you, don’t use proxy.

Running GET of http://localhost:3000/api/me inside REST Console extension return the correct result.

Further reading about Fetch API and cookies reveal that I have to include the parameter credentials:true to send cookies:

fetch('/api/me', {
  credentials: 'include'
})
Sign up to request clarification or add additional context in comments.

1 Comment

This was helpful in that it convinced me to try using the advanced proxy, which worked. I was trying to proxy a path that returns a text file with express. github.com/facebook/create-react-app/blob/master/packages/…
1

Yes it is possible:

  "proxy": {
    "/api": {
      "target": "<url>",
      "ws": true
    }
  },

See https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/template/README.md#configuring-the-proxy-manually

1 Comment

0

I have my own react app and I tried adding proxy to the package.json, but it is nit working.

The simple create-react-app works just fine bu tit does not have any webpack configured.

Here is my webpack:

const path = require('path')

const HtmlWebpackPlugin = require('html-webpack-plugin');
const HtmlWebpackPluginConfig = new HtmlWebpackPlugin({
  template: './src/index.html',
  filename: 'index.html',
  inject: 'body'
})

module.exports = {
    entry: './src/index.js',
    output: {
        path: path.resolve('./dist'),
        filename: 'index_bundle.js'
    },
    module: {
        loaders:[
            { 
                test: /\.js$/, 
                loader: 'babel-loader', 
                exclude: /node_modules/ 
            },
            { 
                test: /\.jsx$/, 
                loader: 'babel-loader', 
                exclude: /node_modules/ 
            },
            { 
                test: /\.css$/, 
                loader: "style-loader!css-loader?modules" 
            },
            { 
                test: /\.png$/, 
                loader: "url-loader?limit=100000" 
            },
            { 
                test: /\.jpg$/, 
                loader: "file-loader" 
            },
            {
                test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/, 
                loader: 'url-loader?limit=10000&mimetype=application/font-woff'
            },
            {
                test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, 
                loader: 'url-loader?limit=10000&mimetype=application/octet-stream'
            },
            {     
                test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, 
                loader: 'file-loader'
            },
            {
                test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, 
                loader: 'url-loader?limit=10000&mimetype=image/svg+xml'
            }
        ]
    },
    resolve: {
        extensions: ['.js', '.jsx' ,'.json'],
        modules: [path.join(__dirname, 'src'), 'node_modules']
    },
    plugins: [HtmlWebpackPluginConfig]
}

My package.json:

{
  "name": "A2ZPressMaterial",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "scripts": {
    "start": "webpack-dev-server --history-api-fallback",
    "webpack-watch": "webpack -w",
    "express-server": "node ./server",
    "dev": "concurrently --kill-others \"npm run webpack-watch\" \"npm run express-server\"",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "proxy": "http://localhost:3001",
  "dependencies": {
    "classnames": "^2.2.5",
    "css-loader": "^0.28.7",
    "file-loader": "^0.11.2",
    "html-webpack-plugin": "^2.30.1",
    "http-proxy-middleware": "^0.17.4",
    "material-ui": "^0.19.2",
    "path": "^0.12.7",
    "react": "^15.6.1",
    "react-dom": "^15.6.1",
    "react-lazyload": "^2.2.7",
    "react-redux": "^5.0.6",
    "react-router-dom": "^4.2.2",
    "redux": "^3.7.2",
    "redux-thunk": "^2.2.0",
    "style-loader": "^0.18.2",
    "url-loader": "^0.5.9",
    "webpack": "^3.5.6",
    "webpack-dev-server": "^2.8.1"
  },
  "devDependencies": {
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.2",
    "babel-plugin-transform-class-properties": "^6.24.1",
    "babel-plugin-transform-runtime": "^6.23.0",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "babel-preset-stage-0": "^6.24.1",
    "concurrently": "^3.5.0"
  }
}

I get 404 on my ajax/fetch calls

Comments

0

Yes it is possible. You will need to use http-proxy-middleware and configure proxy manually.

First install http-proxy-middleware in your react app

npm install http-proxy-middleware --save

Then create src/setupProxy.js file with below configuration

/* eslint-disable @typescript-eslint/no-var-requires */
/* eslint-disable no-undef */
const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = function(app) {
  app.use(
    '/api',
    createProxyMiddleware({
      target: 'http://localhost:9191',
      secure: false,
      changeOrigin: true,
    })
  );
};

Now simply start the application and you will see that non AJAX calls (document etc) are also being proxied correctly.

Note: Remove the proxy configuration from package.json file before configuring it manually with http-proxy-middleware otherwise the proxy won't work correctly if defined at both the places

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.