让我们与Vite谈论CORS和前端
#node #php #vite #cors

我经常发现自己开发了带有反应或提前的网站。
最近,预告片已成为我的最爱,因为它更快,更轻。

有时我不需要使用真正的服务器,例如,当我教课程,进行演示或没有互联网工作时。当我需要模拟服务器的请求时,即使是本地的也是有帮助的。

为了测试我的前端,我创建了一个简单的PHP文件,该文件读取通过帖子发送的数据并返回一个类似于真实服务器提供的json对象。

(在文章的末尾,有一个php服务器的nod​​e.js版本。)

php -S 127.0.0.1 -t server.php
<?php

$json = file_get_contents('php://input');
$data = json_decode($json, true);

if (!isset($data['username']) || !isset($data['password'])) {
    http_response_code(400);
    echo json_encode([
        'status' => 'error',
        'message' => 'Username or password not provided'
    ]);
    exit;
}

if ($data['username'] === 'nicolas' && $data['password'] === 'Correct-h0rse-Battery-staple') {
    echo json_encode([
        'status' => 'success',
        'token' => 'fake_token'
    ]);
} else {
    http_response_code(401);
    echo json_encode([
        'status' => 'error',
        'message' => 'Invalid username or password'
    ]);
}

我喜欢使用PHP,因为它没有依赖关系,这非常适合演示。但是此代码不起作用。错误是:

Response body is not available to scripts (Reason: CORS Failed)

阅读标题后,您可能已经猜到了错误来自CORS。但是什么是CORS?

CORS代表交叉原始资源共享。这是一种安全机制,可让您控制谁可以访问服务器的资源。

那么,我只需要添加到我的PHP代码中的所有HTTP标题,对吗?

<?php

header('Content-Type: application/json');
header('Access-Control-Allow-Origin: http://localhost:5173');
header('Access-Control-Allow-Methods: POST');
header('Access-Control-Allow-Headers: Content-Type');

我的代码仍然不起作用!我的请求没有到达服务器。但是为什么?

检查后,Axios在我提出的发布请求之前向请求发送。第一个请求被称为“前飞行请求”。这是一个选项请求;它仅向服务器询问允许的请求类型。知道这一点,让我们修改标题并添加一个小的台词:

// headers
header('Access-Control-Allow-Methods: POST, OPTIONS');

if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(200);
    exit;
}
// fake login

现在可以工作了!通常,浏览器试图执行“相同的原点”策略,该策略限制了在一个原点运行的JavaScript代码如何访问另一个来源的资源。 (起源可以是域,协议或端口。)

最后,我们的PHP代码看起来像这样:

<?php

header('Content-Type: application/json');
header('Access-Control-Allow-Origin: http://localhost:5173'); // CORS
header('Access-Control-Allow-Methods: POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');

if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(200);
    exit;
}

$json = file_get_contents('php://input');
$data = json_decode($json, true);

if (!isset($data['username']) || !isset($data['password'])) {
  http_response_code(400);
  echo json_encode([
    'status' => 'error',
    'message' => 'Username or password not provided'
  ]);
  exit;
}

if ($data['username'] === 'nicolas' && $data['password'] === 'Correct-h0rse-Battery-staple') {
  echo json_encode([
    'status' => 'success',
    'token' => 'fake_token'
  ]);
} else {
  http_response_code(401);
  echo json_encode([
    'status' => 'error',
    'message' => 'Invalid username or password'
  ]);
}

如果您的系统上没有PHP解释器,请使用express:
中的Node.js中的同一程序的一个版本

pnpm init && pnpm add express body-parser cors
const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");

const app = express();
const port = process.env.PORT || 3000;

app.use(bodyParser.json());
app.use(cors());

app.post("/login", (req, res) => {
  const { username, password } = req.body;

  if (!username || !password) {
    res
      .status(400)
      .json({ status: "error", message: "Username or password not provided" });
    return;
  }

  if (username === "nicolas" && password === "Correct-h0rse-Battery-staple") {
    res.json({ status: "success", token: "fake_token" });
  } else {
    res
      .status(401)
      .json({ status: "error", message: "Invalid username or password" });
  }
});

app.listen(port, () => {
  console.log(`Node.js server running at http://localhost:${port}`);
});

封面学分: