Home > Blockchain >  Host React and api on the same server, but got cors errors
Host React and api on the same server, but got cors errors

Time:09-22

I'm building a simple web app that displays news from the NewsAPI.
First, I built an API server using express.js. The API server works on "http://localhost:4001".
Second, I built a react web page using the react development server. The react server works on "http://localhost:3000".
The first and second builds were successful. The react server could serve web pages to the browser. The API server could get news data from the NewsAPI according to requests from the browser and send the data to the browser. The browser could display news articles with thumbnails properly.
Third, I build the react server project using npm run build command to make a build folder and copy the folder to the API server project folder.
The API project structure is below.

.
├── build              <--This folder is built using 'npm run build'
├── api                <--This folder contains the api router code
├── functions          <--This folder contains extra functions for newsApp.ts
├── newsApp.ts         <--This code is main server code.
├── package-lock.json
├── package.json
├── tsconfig.json
├── types.ts

The newsApp.ts is the API server code.
Furthermore, I changed the newsApp.ts so that the API server can serve the react web page and work as an API server.
The change is below.

  1. Add the helmet options. Before the third act, the Helmet had no options.
app.use(Helmet({
    contentSecurityPolicy: {
        directives: {
            "img-src": ["'self'", "data:", "https:", "http:"],
        }
    }
}));
  1. Changed to return index.html inside the build folder when '/' is accessed.
app.get("/", async (req: express.Request, res: express.Response) => {
    res.sendFile(path.join(path.resolve(), "build", "index.html"));
});
  1. Changed to cors origin option from http://localhost:3000 to *.
const options: cors.CorsOptions = {
    credentials: true,
    origin: "*",
}

app.use(cors(options));

The entire newsApp.ts code is below.

import 'dotenv/config';
import express from "express";
import cors from "cors";
import * as http from "http";
import path from "path";
import Helmet from "helmet";
import bodyParser from "body-parser";
import nocache from "nocache";
import {apiRouter} from './api/apiRouter.js' <-- This is the api server code, is not posted.

const app: express.Express = express();

const options: cors.CorsOptions = {
    credentials: true,
    origin: "*",
}

app.use(cors(options));

app.use(express.json());
app.use(express.urlencoded({extended: true}));

app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());

app.use(nocache());
app.use(Helmet({
    contentSecurityPolicy: {
        directives: {
            "img-src": ["'self'", "data:", "https:", "http:"],
        }
    }
}));

app.use('/api', apiRouter);

app.use(express.static(path.join(path.resolve(), "build")));

app.get("/", async (req: express.Request, res: express.Response) => {
    res.sendFile(path.join(path.resolve(), "build", "index.html"));
});

let httpServer: http.Server = http.createServer(app);
httpServer.listen(4001);

However, the browser could display news articles but could not display its thumbnail.
The error code is below.

assets.media-platform.com/gizmodo/dist/images/2022/09/20/220920vespera-w960.jpg:1          GET https://assets.media-platform.com/gizmodo/dist/images/2022/09/20/220920vespera-w960.jpg net::ERR_FAILED 200
Image (async)
(anonymous) @ chakra-ui-image.esm.js:78
(anonymous) @ chakra-ui-image.esm.js:114
rs @ react-dom.production.min.js:244
xs @ react-dom.production.min.js:261
bs @ react-dom.production.min.js:260
ys @ react-dom.production.min.js:259
(anonymous) @ react-dom.production.min.js:283
wu @ react-dom.production.min.js:281
ou @ react-dom.production.min.js:270
S @ scheduler.production.min.js:13
A @ scheduler.production.min.js:14
localhost/:1 Access to image at 'https://storage.mantan-web.jp/images/2022/09/22/20220922dog00m200007000c/001_size6.jpg' from origin 'http://localhost:4001' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

The react code that displays the thumbnail is using Chakra-UI Image component. This is simple like below.

<Image crossOrigin={"anonymous"} maxH={300} src={props.urlToImage} fallbackSrc={placeHolder}/>

The props.urlToImage is a news source URL that is got from the NewsAPI, and this might be the cause of the errors. The errors are output by the number of thumbnails.
I tried adding the code below to newsApp.ts, but this did not work.

app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  next();
});

I can not find any solution to the problem.
Does anyone know what it is?

React: v18.2.0
chakra-ui: v2.2.4
express.js: v4.18.1

CodePudding user response:

As far as I know origin: '*' doesn't allow you to use credentials.

Check https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors/CORSNotSupportingCredentials

CodePudding user response:

You need to set proxy in package.json

"proxy": "http://localhost:4001",

like this ...

refer this link to resolve this issue : https://blog.bitsrc.io/react-devserver-proxy-ed4d228956c2#:~:text=Proxy Setup with Create-React-App&text=All you have to do,API server in development mode.

  • Related