Lỗi Gặp Phải
Khi bạn cố gắng lấy dữ liệu từ một API bên ngoài hoặc một backend chạy trên cổng khác với ứng dụng React của bạn, bạn sẽ thấy lỗi cụ thể này trong console trình duyệt:
Access to fetch at 'http://api.example.com' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Lỗi này ngăn ứng dụng của bạn nhận dữ liệu, thường dẫn đến request mạng thất bại dù server thực sự đã xử lý logic đúng.
Nguyên Nhân
CORS (Cross-Origin Resource Sharing) là cơ chế bảo mật được trình duyệt triển khai nhằm ngăn các website độc hại gửi request đến domain khác với domain đang phục vụ trang web. Trong phát triển web hiện đại, ứng dụng React của bạn thường chạy trên http://localhost:3000 trong khi API có thể nằm ở http://localhost:5000 hoặc http://api.example.com. Vì domain hoặc cổng khác nhau, trình duyệt sẽ chặn phản hồi trừ khi server cho phép một cách tường minh.
Các Bước Khắc Phục
Giải Pháp 1: Cấu Hình Phía Server (Cách Được Khuyến Nghị)
Cách mạnh mẽ nhất để giải quyết CORS là cấu hình server backend cho phép request từ origin của ứng dụng React. Bạn cần thêm header Access-Control-Allow-Origin vào phản hồi từ server.
Ví Dụ với Node.js / Express
Cài đặt package cors:
npm install cors
Sau đó, áp dụng nó như middleware trong server.js của bạn:
const express = require('express');
const cors = require('cors');
const app = express();
// Cho phép request từ dev server React của bạn
app.use(cors({
origin: 'http://localhost:3000'
}));
app.get('/api/data', (req, res) => {
res.json({ message: 'Success' });
});
app.listen(5000);
Ví Dụ với Python / FastAPI
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:3000"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
Giải Pháp 2: Dùng Development Proxy (Phía React)
Nếu bạn không có quyền truy cập vào code backend hoặc muốn giải quyết nhanh khi phát triển local, bạn có thể dùng proxy. Cách này khiến development server của React chuyển tiếp request đến API server, làm trình duyệt nghĩ rằng request xuất phát từ cùng một origin.
Với Create React App (CRA)
Mở package.json và thêm trường proxy ở cuối file:
{
"name": "my-react-app",
"version": "0.1.0",
"dependencies": { ... },
"proxy": "http://localhost:5000"
}
Sau khi thêm, hãy đổi các lời gọi fetch từ URL tuyệt đối sang đường dẫn tương đối:
// Đổi từ:
fetch('http://localhost:5000/api/users')
// Thành:
fetch('/api/users')
Lưu ý: Bạn phải khởi động lại development server React để thay đổi có hiệu lực.
Với Dự Án Vite
Trong vite.config.ts hoặc vite.config.js, cấu hình server proxy:
export default defineConfig({
server: {
proxy: {
'/api': {
target: 'http://localhost:5000',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
},
},
},
});
Giải Pháp 3: Thiết Lập Proxy Middleware Thủ Công
Nếu bạn cần kiểm soát nhiều hơn (ví dụ: proxy đến nhiều backend), hãy dùng http-proxy-middleware.
- Cài đặt package:
npm install http-proxy-middleware - Tạo file
src/setupProxy.js(Không cần import ở đâu cả, CRA tự động tìm file này).
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
'/api',
createProxyMiddleware({
target: 'http://localhost:5000',
changeOrigin: true,
})
);
};
Các Bước Kiểm Tra
- Mở ứng dụng React của bạn trong Chrome hoặc Firefox.
- Nhấn
F12để mở Developer Tools và chuyển sang tab Network. - Kích hoạt lời gọi API (ví dụ: tải lại trang hoặc nhấn một nút).
- Nhấp vào request bị lỗi.
- Xem mục Response Headers. Nếu cách sửa đã có hiệu lực, bạn sẽ thấy:
Access-Control-Allow-Origin: http://localhost:3000(hoặc*). - Kiểm tra Console; lỗi CORS màu đỏ sẽ không còn nữa.
Mẹo Từ Chuyên Gia
- Tránh Dùng
*Trên Production: Mặc dùapp.use(cors({ origin: '*' }))tiện cho việc test, nhưng nó không an toàn. Hãy luôn chỉ định đúng domain production của bạn. - Kiểm Tra Protocol:
http://localhost:3000vàhttps://localhost:3000được coi là hai origin khác nhau. Đảm bảo chúng khớp nhau. - Preflight Request: Với các request phức tạp (như request có header tùy chỉnh hoặc phương thức
PUT/DELETE), trình duyệt sẽ gửi requestOPTIONStrước. Đảm bảo server của bạn xử lý requestOPTIONSvà trả về đúng CORS header. - Cookie và Credentials: Nếu bạn cần gửi cookie hoặc Authorization header, bạn phải đặt
credentials: 'include'trong tùy chọn fetch vàallow_credentials=Truetrên server.

