CORS (Cross-Origin Resource Sharing) est un mécanisme qui permet à une application Web sur un domaine d'accéder aux ressources d'un autre domaine. Ceci est crucial lors du développement d'une application où le frontend et le backend sont séparés et communiquent via une API.
Voici un article expliquant l'implémentation de CORS dans Node.js et Express sans utiliser de bibliothèques externes :
"use strict"; /*jshint node:true */ var simpleMethods, simpleRequestHeaders, simpleResponseHeaders, toLowerCase, checkOriginMatch, origin; Object.defineProperty(exports, "simpleMethods", { get: function () { return [ "GET", "HEAD", "POST", "PUT", "DELETE" ]; } }); simpleMethods = exports.simpleMethods; Object.defineProperty(exports, "origin", { get: function () { return ["http://localhost:3000"]; } }); origin = exports.origin;
Export simpleMethods : définit les méthodes HTTP autorisées pour les requêtes CORS (par exemple, GET, POST, PUT, etc.).
Export origin : Spécifie la liste des origines autorisées pour l'accès. Dans cet exemple, http://localhost:3000 est autorisé.
Object.defineProperty(exports, "simpleRequestHeaders", { get: function () { return ["accept", "accept-language", "content-language", "content-type", "authorization", "token"]; } }); simpleRequestHeaders = exports.simpleRequestHeaders; Object.defineProperty(exports, "simpleResponseHeaders", { get: function () { return ["cache-control", "content-language", "content-type", "expires", "last-modified", "pragma"]; } }); simpleResponseHeaders = exports.simpleResponseHeaders;
Export simpleRequestHeaders : définit les en-têtes de requête autorisés des clients dans les requêtes inter-domaines.
Export simpleResponseHeaders : Définit les en-têtes de réponse autorisés du serveur vers le client.
checkOriginMatch = function (originHeader, origins, callback) { if (typeof origins === "function") { origins(originHeader, function (err, allow) { callback(err, allow); }); } else if (origins.length > 0) { callback(null, origins.some(function (origin) { return origin === originHeader; })); } else { callback(null, true); } };
Fonction checkOriginMatch : Vérifie si l'origine de la requête correspond à une liste d'origines autorisées. En cas de correspondance, la demande est autorisée.
exports.create = function (options) { options = options || {}; options.origins = options.origins || origin; options.methods = options.methods || simpleMethods;
Initialisation des options d'origines et de méthodes, avec les valeurs par défaut de origin et simpleMethods si aucune n'est fournie.
Définition des en-têtes de demande et de réponse
if (options.hasOwnProperty("requestHeaders") === true) { options.requestHeaders = toLowerCase(options.requestHeaders); } else { options.requestHeaders = simpleRequestHeaders; } if (options.hasOwnProperty("responseHeaders") === true) { options.responseHeaders = toLowerCase(options.responseHeaders); } else { options.responseHeaders = simpleResponseHeaders; }
Définit les en-têtes de requête (requestHeaders) et de réponse (responseHeaders) autorisés. Convertit tout en-tête de demande ou de réponse donné en minuscules.
Configuration middleware supplémentaire
options.maxAge = options.maxAge || null; options.supportsCredentials = options.supportsCredentials || false; if (options.hasOwnProperty("endPreflightRequests") === false) { options.endPreflightRequests = true; }
maxAge : Spécifie l'âge maximum du cache pour le contrôle en amont CORS. supportsCredentials : détermine si le serveur prend en charge les informations d'identification (cookies ou jetons) dans les requêtes inter-domaines. endPreflightRequests : décide si le serveur doit mettre fin aux requêtes de contrôle en amont (OPTIONS) ou passer au middleware suivant.
return function (req, res, next) { if (!req.headers.hasOwnProperty("origin")) { next(); } else { checkOriginMatch(req.headers.origin, options.origins, function (err, originMatches) { if (err !== null) { next(err); } else { var endPreflight = function () { if (options.endPreflightRequests === true) { res.writeHead(204); res.end(); } else { next(); } };
Fonction endPreflight : termine les requêtes de contrôle en amont (OPTIONS) si endPreflightRequests est défini sur true. Vérification de l'origine : utilise checkOriginMatch pour vérifier si l'origine de la demande correspond à une origine autorisée.
Gestion des demandes de contrôle en amont (OPTIONS)
if (req.method === "OPTIONS") { if (!req.headers.hasOwnProperty("access-control-request-method")) { endPreflight(); } else { requestMethod = req.headers["access-control-request-method"]; if (req.headers.hasOwnProperty("access-control-request-headers")) { requestHeaders = toLowerCase(req.headers["access-control-request-headers"].split(/,\s*/)); } else { requestHeaders = []; } methodMatches = options.methods.indexOf(requestMethod) !== -1; if (!methodMatches) { endPreflight(); } else { headersMatch = requestHeaders.every(function (requestHeader) { return options.requestHeaders.includes(requestHeader); }); if (!headersMatch) { endPreflight(); } else { if (options.supportsCredentials) { res.setHeader("Access-Control-Allow-Origin", req.headers.origin); res.setHeader("Access-Control-Allow-Credentials", "true"); } else { res.setHeader("Access-Control-Allow-Origin", "*"); } if (options.maxAge !== null) { res.setHeader("Access-Control-Max-Age", options.maxAge); } res.setHeader("Access-Control-Allow-Methods", options.methods.join(",")); res.setHeader("Access-Control-Allow-Headers", options.requestHeaders.join(",")); endPreflight(); } } } }
Méthode de requête et correspondance des en-têtes : Vérifie si la méthode de requête et les en-têtes correspondent à ceux autorisés. En-têtes de réponse CORS : définit les en-têtes CORS tels que Access-Control-Allow-Origin, Access-Control-Allow-Credentials, Access-Control-Allow-Methods, etc.
Exposing Headers in the Response
} else {
if (options.supportsCredentials) {
res.setHeader("Access-Control-Allow-Origin", req.headers.origin);
res.setHeader("Access-Control-Allow-Credentials", "true");
} else {
res.setHeader("Access-Control-Allow-Origin", "*");
}
exposedHeaders = options.responseHeaders.filter(function (header) { return !simpleResponseHeaders.includes(header); }); if (exposedHeaders.length > 0) { res.setHeader("Access-Control-Expose-Headers", exposedHeaders.join(",")); } next(); } } }); } };
} else { if (options.supportsCredentials) { res.setHeader("Access-Control-Allow-Origin", req.headers.origin); res.setHeader("Access-Control-Allow-Credentials", "true"); } else { res.setHeader("Access-Control-Allow-Origin", "*"); } exposedHeaders = options.responseHeaders.filter(function (header) { return !simpleResponseHeaders.includes(header); }); if (exposedHeaders.length > 0) { res.setHeader("Access-Control-Expose-Headers", exposedHeaders.join(",")); } next(); } } }); } };
Access-Control-Expose-Headers: Sets response headers that are accessible to the client if there are custom headers not included in simpleResponseHeaders.
This is how you can implement custom CORS in Node.js without using any library. For the complete script, you can refer to this example.
Atas ialah kandungan terperinci CORS Tersuai Nodejs. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!