This project demonstrates using the setup generated by create-react-app
alongside a Node Express API server.
Original blog post that explains the fundamentals of this repository.
Have trouble when using this repo with version 12 of Node. Back to 9.5. See .nvmrc
file.
Run first:
nvm use
Véase branch: 10-crguezl-master-cors-01
Si en Client-js
cambiamos el fetch
para solicitar al server en 3001:
* eslint-disable no-undef */
function search(query, cb) {
return fetch(`http://localhost:3001/api/food?q=${query}`, {
accept: "application/json"
})
.then(checkStatus)
.then(parseJSON)
.then(cb);
}
Obtenemos una respuesta:
Access to fetch at 'http://localhost:3001/api/food?q=r' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
localhost/:1 Uncaught (in promise) TypeError: Failed to fetch
If you want to avoid the blocking, the server that hosts the resource needs to have CORS enabled.
What you can do on the client side (and probably what you are thinking of) is set the mode of fetch
to CORS
(although this is the default setting I believe):
fetch(request, {mode: 'cors'});
However this still requires the server to enable CORS as well, and allow your domain to request the resource.
In Express we can use the module cors
$ npm install cors
If inside the app we use this middleware:
var express = require('express')
var cors = require('cors')
var app = express()
app.use(cors())
app.get('/products/:id', function (req, res, next) {
res.json({msg: 'This is CORS-enabled for all origins!'})
})
app.listen(80, function () {
console.log('CORS-enabled web server listening on port 80')
})
To enable CORS for a Single Route we do:
var express = require('express')
var cors = require('cors')
var app = express()
app.get('/products/:id', cors(), function (req, res, next) {
res.json({msg: 'This is CORS-enabled for a Single Route'})
})
app.listen(80, function () {
console.log('CORS-enabled web server listening on port 80')
})
We can configure CORS:
var express = require('express')
var cors = require('cors')
var app = express()
var corsOptions = {
origin: 'http://example.com',
optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204
}
app.get('/products/:id', cors(corsOptions), function (req, res, next) {
res.json({msg: 'This is CORS-enabled for only example.com.'})
})
app.listen(80, function () {
console.log('CORS-enabled web server listening on port 80')
})
The origin
option used in this example configures the Access-Control-Allow-Origin CORS header.
Possible values:
Boolean
- setorigin
totrue
to reflect the request origin, as defined byreq.header('Origin')
, or set it tofalse
to disable CORS.String
- setorigin
to a specific origin. For example if you set it to"http://example.com"
only requests from “http://example.com” will be allowed.RegExp
- setorigin
to a regular expression pattern which will be used to test the request origin. If it’s a match, the request origin will be reflected. For example the pattern/example\.com$/
will reflect any request that is coming from an origin ending with “example.com”.Array
- setorigin
to an array of valid origins. Each origin can be aString
or aRegExp
. For example["http://example1.com", /\.example2\.com$/]
will accept any request from “http://example1.com” or from a subdomain of “example2.com”.Function
- setorigin
to a function implementing some custom logic. The function takes the request origin as the first parameter and a callback (which expects the signatureerr [object], allow [bool]
) as the second.
- Using CORS in Express by Alexis Hevia
- fetch
- cors is a node.js package for providing a Connect/Express middleware that can be used to enable CORS with various options.
We have a detailed blog post that explains this repository.
Check out the Rails version if that's your preferred API server platform.
git clone https://github.com/fullstackreact/food-lookup-demo.git
cd food-lookup-demo
npm i
cd client
npm i
cd ..
npm start
create-react-app
configures a Webpack development server to run on localhost:3000
. This development server will bundle all static assets located under client/src/
. All requests to localhost:3000
will serve client/index.html
which will include Webpack's bundle.js
.
To prevent any issues with CORS, the user's browser will communicate exclusively with the Webpack development server.
Inside Client.js
, we use Fetch to make a request to the API:
// Inside Client.js
return fetch(`/api/food?q=${query}`, {
// ...
})
This request is made to localhost:3000
, the Webpack dev server. Webpack will infer that this request is actually intended for our API server. We specify in package.json
that we would like Webpack to proxy API requests to localhost:3001
:
// Inside client/package.json
"proxy": "http://localhost:3001/",
This handy features is provided for us by create-react-app
.
Therefore, the user's browser makes a request to Webpack at localhost:3000
which then proxies the request to our API server at localhost:3001
:
This setup provides two advantages:
- If the user's browser tried to request
localhost:3001
directly, we'd run into issues with CORS. - The API URL in development matches that in production. You don't have to do something like this:
// Example API base URL determination in Client.js
const apiBaseUrl = process.env.NODE_ENV === 'development' ? 'localhost:3001' : '/'
This setup uses concurrently for process management. Executing npm start
instructs concurrently
to boot both the Webpack dev server and the API server.
The app is ready to be deployed to Heroku.
In production, Heroku will use Procfile
which boots just the server:
web: npm run server
Inside server.js
, we tell Node/Express we'd like it to serve static assets in production:
if (process.env.NODE_ENV === 'production') {
app.use(express.static('client/build'));
}
You just need to have Webpack produce a static bundle of the React app (below).
We assume basic knowledge of Heroku.
0. Setup your Heroku account and Heroku CLI
For installing the CLI tool, see this article.
1. Build the React app
Running npm run build
creates the static bundle which we can then use any HTTP server to serve:
cd client/
npm run build
2. Commit the client/build
folder to source control
From the root of the project:
git add client/build
git commit -m 'Adding `build` to source control'
3. Create the Heroku app
heroku apps:create food-lookup-demo
4. Push to Heroku
git push heroku master
Heroku will give you a link at which to view your live app.