简体   繁体   English

CORS with SSR with express、react 和 Axios

[英]CORS with SSR with express, react and Axios

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:我正在开发一个必须与公共 API 连接的 APP(由 express 提供的 React:SSR),并且我从 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.从源“http://localhost:3000”访问“https://api.musixmatch.com/ws/1.1/track.search?q_track=There%20will%20be%20blood&apikey=value”的 XMLHttpRequest 已被阻止CORS 策略:对预检请求的响应未通过访问控制检查:请求的资源上不存在“Access-Control-Allow-Origin”标头。

So I setup axios with next config/headers in my client:因此,我在客户端中使用下一个配置/标头设置 axios:

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:我也试过把它放在 webpack 上:

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

Here is my server.js这是我的 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.但是如果我从我的 APP 尝试,它没有。

  • Have I to setup the request on express file (server.js)?我必须在快递文件 (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推荐人政策:strict-origin-when-cross-origin

As suggested @lissettdm, I was using cors but without the right configuration.正如@lissettdm 所建议的,我使用的是 cors,但没有正确的配置。

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.我仔细阅读了http://expressjs.com/en/resources/middleware/cors.html的文档,发现我们可以设置我们信任的起源或起源。

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.在我的情况下,我不想隐藏 apikey,因为在同一请求中我必须发送它,但正如建议的@jonrsharpe,我们不能显示该信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM