0
votes

I'm working on an APP (React served by express: SSR) which has to connect with an API public and I getting the next message from chrome:

Access to XMLHttpRequest at 'https://api.musixmatch.com/ws/1.1/track.search?q_track=There%20will%20be%20blood&apikey=value' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

So I setup axios with next config/headers in my client:

const instance = axios.create({
  baseURL: urlServer,
});

const options = {
  headers: {
    "Access-Control-Allow-Origin": "*",
    "Content-Type": "application/json",
  },
  params: {
    apikey: "value",
  },
};

export const getUsers = () =>
  instance.get(`track.search?q_track=There will be blood`, options);

I have tried putting this on webpack, too:

devServer: {
    historyApiFallback: true,
    headers: {
      "Access-Control-Allow-Origin": "*",
      "Access-Control-Allow-Headers":
        "Origin, X-Requested-With, Content-Type, Accept",
    },
  },

Here is my server.js

import express from "express";
import cors from "cors";
import dotenv from "dotenv";
import webpack from "webpack";
import helmet from "helmet";
import React from "react";
import { renderToString } from "react-dom/server";
import { renderRoutes } from "react-router-config";
import { StaticRouter } from "react-router-dom";
import { Layout } from "components";
import serverRoutes from "../frontend/routes/serverRoutes";
import getManifest from "./getManifest";

dotenv.config();

const { ENV, PORT_DEV, PORT_PRO } = process.env;
const port = ENV === "development" ? PORT_DEV : PORT_PRO;

const app = express();
app.use(cors());

if (ENV === "development") {
  console.log("#########################################");
  console.log("Enviroment: ", "Working on develop");

  const webpackConfig = require("../../webpack.config");
  const webpackDevMiddleware = require("webpack-dev-middleware");
  const webpackHotMiddleware = require("webpack-hot-middleware");
  const compiler = webpack(webpackConfig);

  const webpackServerConfig = {
    port: port,
    hot: true,
  };

  app.use(webpackDevMiddleware(compiler, webpackServerConfig));
  app.use(webpackHotMiddleware(compiler));
}

if (ENV === "production") {
  app.use((request, response, next) => {
    if (!request.hashManifest) {
      request.hashManifest = getManifest();
    }
    next();
  });
  app.use(express.static(`${__dirname}/public`));
  app.use(helmet());
  app.use(helmet.permittedCrossDomainPolicies());
  app.disable("x-powered-by");
}

const setResponse = (html, manifest) => {
  const mainStyles = manifest ? manifest["main.css"] : "assets/main.css";
  const mainBuild = manifest ? manifest["main.js"] : "assets/main.js";
  const vendorBuild = manifest ? manifest["vendors.js"] : "assets/vendor.js";

  return `
      <!DOCTYPE html>
      <html lang="es">
        <head>
          <meta charset="utf-8" />
          <link href="${mainStyles}" rel="stylesheet" type="text/css">
          <title>React App</title>
        </head>
        <body>
          <div id="root">${html}</div>
          <script src="${mainBuild}" type="text/javascript"></script>
          <script src="${vendorBuild}" type="text/javascript"></script>
        </body>
      </html>
    `;
};

const renderApp = (request, response) => {
  const html = renderToString(
    <Layout>
      <StaticRouter location={request.url} context={{}}>
        {renderRoutes(serverRoutes)}
      </StaticRouter>
    </Layout>
  );

  response.send(setResponse(html, request.hashManifest));
};

app.get("*", renderApp);

app.listen(port, (error) => {
  if (error) {
    console.log("Error: ", "can not run the server.");
  } else {
    console.log(`Server running on port ${port} - ${ENV}`);
    console.log("#########################################");
  }
});

I tried to get data with postman and it works. But if I try from my APP, it didn't.

  • Have I to setup the request on express file (server.js)?
  • Am I missing something in the request from my client?
  • Can I do the request on client?

More information, about general headers. It gives me this pair of key value:

Referrer Policy: strict-origin-when-cross-origin

1
You shouldn't be making that request straight from the client app, then you'd have to share your token with your users. CORS is by-the-by, but note that you cannot fix it by adding headers in the client (they're response headers that need to be set by the server). You should write some kind of backend (Express or something else) to proxy that request, so you can keep the token private. - jonrsharpe
Thanks for the recommendation. I'll try it - Julián Peñaranda Acevedo
Hi, did you tried to install cors? expressjs.com/en/resources/middleware/cors.html - lissettdm
Yep, I'm using cors. Maybe could be a problem or a conflict between CORS and Helmet? - Julián Peñaranda Acevedo

1 Answers

0
votes

As suggested @lissettdm, I was using cors but without the right configuration.

I read carefully the documentation of http://expressjs.com/en/resources/middleware/cors.html and saw that we can set the origin or origins in wich we trust.

So I did it:

app.use(
  cors({
    origin: ["https://api.musixmatch.com"],
  })
);

This will add the domain to trus on and it will let us do request from client. In my case I dont want to hide the apikey because in the same request I have to send it, but as suggested @jonrsharpe we must not show that information.