Nodejs + 自定义 CORS

nodejs + 自定义 cors

cors(跨源资源共享) 是一种允许一个域上的 web 应用程序访问另一个域上的资源的机制。当开发前端和后端分离并通过 api 进行通信的应用程序时,这一点至关重要。

这里有一篇文章解释了在 node.js 和 express 中不使用外部库的 cors 实现:

"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:定义 cors 请求允许的 http 方法(例如 get、post、put 等)。

导出来源:指定允许访问的来源列表。在此示例中,允许使用 http://localhost:3000。

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;

导出 simplerequestheaders:定义跨域请求中客户端允许的请求标头。

导出 simpleresponseheaders:定义从服务器到客户端允许的响应标头。

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);    }};

函数 checkoriginmatch:检查请求来源是否与允许的来源列表匹配。如果匹配,则允许请求。

exports.create = function (options) {    options = options || {};    options.origins = options.origins || origin;    options.methods = options.methods || simplemethods;

来源和方法选项的初始化,如果未提供,则使用来自 origin 和 simplemethods 的默认值。

设置请求和响应标头

 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;    }

设置允许的请求(requestheaders)和响应(responseheaders)标头。将任何给定的请求或响应标头转换为小写。

附加中间件配置

 options.maxage = options.maxage || null;    options.supportscredentials = options.supportscredentials || false;    if (options.hasownproperty("endpreflightrequests") === false) {        options.endpreflightrequests = true;    }

maxage:指定 cors 预检的最大缓存期限。 supportcredentials:确定服务器是否支持跨域请求中的凭据(cookie 或令牌)。 endpreflightrequests:决定服务器是否应终止预检请求(选项)或继续执行下一个中间件。

 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();                        }                    };

函数 endpreflight:如果 endpreflightrequests 设置为 true,则结束预检(options)请求。来源检查:使用 checkoriginmatch 来验证请求来源是否与允许的来源匹配。

处理预检请求(选项)

 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();                                }                            }                        }                    }

请求方法和标头匹配:检查请求方法和标头是否与允许的匹配。 cors 响应标头:设置 cors 标头,例如 access-control-allow-origin、access-control-allow-credentials、access-control-allow-methods 等

在响应中公开标头
} 其他 {
if (options.supportscredentials) {
res.setheader(“access-control-allow-origin”, req.headers.origin);
res.setheader(“access-control-allow-credentials”, “true”);
} 其他 {
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:如果 simpleresponseheaders 中未包含自定义标头,则设置客户端可访问的响应标头。

这就是如何在 node.js 中实现自定义 cors,而无需使用任何库。完整的脚本可以参考这个例子

以上就是Nodejs + 自定义 CORS的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1497477.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月19日 19:33:28
下一篇 2025年12月19日 19:33:44

相关推荐

  • JavaScript包管理与发布

    发布JavaScript包最靠谱方式是通过npm,需先注册账号并安装Node.js。初始化项目用npm init生成package.json,确保包名唯一,配置name、version、main、module、files等字段。代码放在src目录,编译后输出到dist,入口文件导出功能函数。添加测试…

    2025年12月21日
    000
  • 浏览器跨域安全策略:为何无法程序化点击PayPal iframe中的按钮

    本文深入探讨了尝试通过javascript程序化点击嵌入在跨域iframe中的paypal按钮时遇到的securityerror。核心原因是浏览器实施的同源策略,它严格限制了不同源文档间的交互,以防止恶意脚本攻击。因此,直接通过父页面脚本访问和操作跨域iframe内部元素是不可能的,开发者应遵循sd…

    2025年12月21日
    000
  • 深入理解跨域安全:为何无法直接操作PayPal iframe按钮

    本文深入探讨了在Web开发中尝试直接操作跨域iframe(如PayPal支付按钮)时遇到的SecurityError。我们将解释浏览器同源策略的核心原理,阐明为何直接通过JavaScript访问和点击此类iframe中的元素是不可行的,并提供使用官方SDK进行安全、规范集成的正确方法,以避免常见的安…

    2025年12月21日
    000
  • React中构建可复用手风琴组件:高效展示动态内容的策略

    本文探讨了在react应用中,如何避免硬编码,通过组件化和属性(props)传递,高效地构建和复用手风琴(accordion)组件以展示多样化内容。通过将可变部分抽象为组件属性,开发者可以大幅减少代码量,提高代码的可维护性和可扩展性,从而实现同一风格手风琴下不同内容的灵活渲染。 在现代Web应用开发…

    2025年12月21日
    000
  • 基于活动类名实现内容动态切换:一个可扩展的jQuery方法

    本教程详细介绍了如何利用%ignore_a_1%和css,根据导航元素(如轮播图滑块)的活动状态,动态切换显示对应的页面内容。文章摒弃了繁琐的`if-else`条件判断,提出了一种更具通用性和可扩展性的解决方案,通过统一的命名约定和事件委托机制,实现内容区域的平滑过渡显示,适用于多状态内容管理场景。…

    2025年12月21日
    000
  • NodeJS 中 String.search() 返回 0 的问题解析与解决方案

    本文旨在解决 NodeJS 中使用 `String.search()` 方法进行正则匹配时,返回值为 0 的问题。我们将深入探讨 `String.search()` 的特性,并提供使用 `String.match()` 方法以及断言来实现正确提取所需数据的解决方案。此外,我们还会推荐使用 jsdom…

    2025年12月21日
    000
  • AWS Amplify Next.js 应用中 S3 凭证错误的解决方案

    在 AWS Amplify 托管的 Next.js 应用中,当尝试上传文件到 S3 时,即使环境变量已正确配置,也可能遭遇 `CredentialsError: Missing credentials in config` 错误。此问题通常源于 Amplify 应用关联的 IAM 角色权限不足,而非…

    2025年12月21日
    000
  • 优化HTML表单文件上传与URL重定向:异步操作的正确处理

    本文探讨了在html表单提交过程中,当需要异步动态设置表单 `action` 属性时,如何避免因 `e.preventdefault()` 和异步操作时序问题导致的提交失败或重定向失效。我们将深入分析常见错误模式,并提供一种将异步 `action` 更新与显式表单提交结合的解决方案,确保文件上传和页…

    2025年12月21日
    000
  • 深入探讨:检测原生密码输入框可见状态的挑战与解决方案

    本文旨在探讨如何检测html密码输入框的原生“显示密码”图标(如::-ms-reveal)的激活状态,并根据此状态触发css样式或javascript动画。我们将详细解析当前css :has()选择器与伪元素结合使用的局限性,解释为何无法直接通过原生机制检测密码可见性。最后,文章将提供一个健壮且跨浏…

    2025年12月21日
    000
  • Angular Formly 自定义组件验证消息未在失焦时显示问题的解决方案

    在 angular 应用中,当我们需要将自定义组件集成到响应式表单或 formly 表单中时,通常会实现 `controlvalueaccessor` 接口。这个接口允许自定义组件充当表单控件,与 angular 的表单系统进行双向数据绑定和状态同步。然而,一个常见的挑战是,在自定义组件中,表单验证…

    2025年12月21日
    000
  • JavaScript异步表单提交:解决动态Action与重定向失效问题

    本文深入探讨了在html表单提交过程中,当涉及异步操作动态设置 `action` 属性时,可能遇到的重定向和数据提交失效问题。核心在于理解 `e.preventdefault()` 的作用及异步函数在事件处理中的时序。教程提供了通过集中式 `onsubmit` 处理、先阻止默认行为、再异步更新 `a…

    2025年12月21日
    000
  • 实现平滑过渡的响应式导航菜单

    本教程将指导您如何使用简洁的css过渡和javascript事件监听,创建一个具有平滑滑入滑出动画效果的导航菜单。通过切换css类,我们可以优雅地控制导航菜单的可见性和动画,避免复杂的第三方库,同时强调html最佳实践,如id的唯一性。 构建可切换导航菜单:CSS过渡与JavaScript实践 在现…

    2025年12月21日
    000
  • 使用jQuery和CSS动态管理同类名元素样式:实现点击选中效果

    本教程详细阐述如何利用jquery和css为一组具有相同类名的元素实现点击选中效果。文章介绍了两种方法:一是通过css的`:focus`伪类处理可聚焦元素,二是通过jquery动态添加/移除css类,以实现更灵活和通用的选中状态样式切换,并提供了完整的代码示例和实践建议。 理解需求:动态样式切换 在…

    2025年12月21日
    000
  • 在React中利用Promise实现HTML Dialog的异步交互

    本文详细介绍了如何在React应用中,通过结合HTML的“元素和JavaScript的Promise机制,实现一个类似`window.confirm()`的异步模态对话框。我们将探讨如何利用全局状态管理来控制对话框的显示与隐藏,并捕获用户交互结果,从而实现流程的暂停与恢复。 实现异步模态对话框的需…

    2025年12月21日
    000
  • 解决Windows上@tensorflow/tfjs-node安装失败的常见问题

    在Windows环境下安装@tensorflow/tfjs-node时,用户常遇到预编译二进制文件404错误及node-gyp编译失败问题。本文旨在提供一份详尽的教程,指导用户正确配置开发环境,特别是强调Python和Visual Studio C++桌面开发工作负载的重要性,以确保tfjs-nod…

    2025年12月21日
    000
  • JavaScript动态创建元素与事件监听:菜单开关实战教程

    在javascript中动态创建dom元素并为其绑定事件是常见的开发需求,但若处理不当,可能导致事件监听失效。本文将深入探讨这一常见问题,并提供一套行之有效的解决方案,重点在于确保事件监听器在元素被创建并添加到dom后才进行绑定,同时兼顾代码的健壮性和用户体验,以实现如动态菜单开关等功能。 理解动态…

    2025年12月20日
    000
  • JavaScript动态创建元素事件监听:实现可开关菜单的正确姿势

    本文旨在解决javascript中动态创建dom元素(如菜单)后,无法正确为其绑定关闭事件的问题。核心在于理解事件监听器必须在元素被创建并添加到dom后才能有效绑定。文章将提供详细的解决方案,包括示例代码和最佳实践,确保动态ui组件的交互功能正常运行。 引言:动态UI与事件监听的挑战 在现代Web开…

    2025年12月20日
    000
  • Chrome扩展开发:解决图片资源加载失败的完整指南

    本文详细阐述了chrome扩展程序中图片资源加载失败的常见原因及解决方案。核心在于理解`manifest.json`中的`web_accessible_resources`配置,并掌握在内容脚本或动态生成元素中通过`chrome.runtime.geturl()`函数正确引用扩展内部图片资源的最佳实…

    2025年12月20日
    000
  • JavaScript无障碍访问性实现

    JavaScript若合理使用可提升无障碍体验,关键在于动态内容更新时采用aria-live属性、管理键盘焦点与语义化交互元素。 JavaScript在现代网页开发中扮演着重要角色,但若使用不当,可能破坏无障碍访问性(Accessibility, 简称a11y)。合理使用JavaScript可以增强…

    2025年12月20日
    000
  • Chrome 扩展程序中图片资源加载指南

    本文深入探讨Chrome扩展程序中图片资源加载不显示的问题,重点解析`manifest.json`中的`web_accessible_resources`配置、`chrome.runtime.getURL()`函数的使用,以及在JavaScript中设置`backgroundImage`时常犯的语法…

    2025年12月20日
    000

发表回复

登录后才能评论
关注微信