了解如何经过使用前端开发服务器中的代理配置来避免CORS。javascript
在过去的十年中,单页应用程序已成为构建Web应用程序的标准技术。现在,诸如Angular,Vue之类的框架以及诸如React之类的库主导着前端开发,为这些应用程序提供了基础平台。好消息是,它能够从一个域中为前台和后台API提供服务。但在某些状况下,咱们会从不一样的子域中为前台(如web.myapp.com)和后台(如api.myapp.com)提供服务。有时,咱们只容许对开发环境的后端API进行跨域访问。html
跨域资源共享(CORS)是在Web浏览器中实现的一种机制,用于容许或拒绝来自其余域的请求到Web应用程序。经过CORS,Web浏览器和Web服务器就标准协议达成一致,以了解是否容许访问资源。所以请记住,从后端执行CORS并不意味着Bots或任何其余机制都没法访问您的服务器资源。前端
可是,咱们是否须要为你的Web应用提供CORS?我想说的是,大多数状况下,你不须要担忧CORS,由于你的网络应用是由一个域提供的。然而,可能会有一些特殊的特性,好比容许在主Web应用程序域以外嵌入页面(例如,表单、视频),你能够考虑在后端启用CORS。不过,你仍然能够启用限定范围到该特定特性的CORS。java
除安全性外,CORS最明显的问题是对Web应用程序性能的影响。当你的前端向不一样的域或子域发送一个HTTP请求时,浏览器会发送一个额外的HTTP,称为preflight(预检)请求,看服务器是否接受来自发件人域的消息。nginx
所以,对于每一个由前端触发的HTTP请求,浏览器须要发送两个HTTP请求,从而增长了整体响应时间。在大多数状况下,添加的延迟在Web应用程序中是可见的,而且会对用户体验产生负面影响。web
当涉及到单页面应用程序时,CORS的使用就显得更为明显。Web浏览器,若是web应用只使用HTTP头(Accept、Accept-Language、DPR、Downlink、Save-Data、Viewport-Width、Width、Content-Language、Content-Type(除了值application/x-www-form-urlencoded、multipart/form-data、text/plan
))和HTTP方法(GET、HEAD、POST
)来进行后端API调用,那么Web浏览器就不会考虑预检请求。在你的单页面应用程序中,你可能须要这些HTTP头和HTTP方法之外的内容。后端
在这些应用中,咱们在前端定义后端API的URL做为服务器操做的变量。此外,咱们甚至可能会在后端API中授予CORS来进行开发,由于前台和后端API的开发服务器可能在两个不一样的端口上运行。开发环境可能还会影响生产环境中的设置,你可能会在其中将前端API和后端API部署在不一样的子域中。api
可是咱们须要沿着这个方向走吗?让咱们看看在开发和生产环境中避免CORS的方法。跨域
今天,咱们选择用于前端开发的大多数开发服务器都使用NodeJS。这些Node服务器中的大多数都支持代理配置。此外,Angular,React和Vue附带了Webpack开发服务器,该服务器内置了对代理配置的支持。浏览器
那么这个代理配置究竟是作什么的呢?
假设你的前端应用程序在 http://localhost:4200
中运行,然后端API在 http://localhost:3000/api/ <resource>
中运行。咱们的前台须要存储后端API的URL和端口,以便在本地运行应用程序。为了支持这一点,你还须要在你的后端API中启用CORS,容许从运行在 http://locahost:4200
的前端服务器上访问。
经过在前端开发服务器中使用代理配置,咱们能够避免上述全部麻烦。使用代理时,只需在前端应用程序中存储相对路径(/api
)。在本地运行应用程序时,你的前端将尝试使用相同的域和端口(http://localhost:4200 /api/<resource>
)访问后端API,浏览器无需担忧CORS。
在此阶段,代理会尽力而为。在代理配置内部,你能够定义将在前端开发服务器上针对路径 /api
的全部请求转发到 http://localhost:3000
。
因为开发服务器是与后端API通讯的中间人,所以能够安全地避免CORS。下面的示例显示了如何在Webpack开发服务器中添加代理配置。
module.exports = {
//...
devServer: {
proxy: {
'/api': 'http://localhost:3000'
}
}
};
复制代码
在生产环境中,除非你的前端和后端API在同一Web服务器中运行,不然你须要在它们的前面设置网关或代理以从单个域提供服务。在某些状况下,若是负载均衡器可以基于HTTP路径路由到不一样的端点,那么它就足够了。
与dev Server代理相似,网关,代理或负载均衡器根据咱们提供的配置来进行路由,并与请求中接收到的HTTP路径匹配。下面的列表包含了一些经常使用的网关、代理和负载均衡器,支持基于URL路径的路由,供你们参考。
此外,经过只容许同源访问来增强CORS的后端API是很是重要的。
整体而言,我但愿你了解CORS的性能含义以及在单页应用程序中避免使用它的好处。除了性能以外,安全性是现代浏览器中创建CORS的最终缘由,所以,相当重要的是要了解CORS在安全性方面的工做原理。可是,你应该可以找到有关CORS和安全性的足够或更多的内容,这不是本文的重点。我在这里的重点是避免在单页应用程序中首先使用CORS。
既然我已经触及到了使用代理来避免CORS,你可能会想知道,当前端和后端API在不一样的服务上运行时,设置一个代理有多难?然而,设置代理比你想象的要简单。例如,为Angular、React或Vue设置一个开发服务器代理,只需在Webpack配置文件中添加几行内容来代理你的请求到后端API,从而避免CORS。这一样适用于生产环境,由于实现基于URL路径的路由有很好的方法。
可是,你必须为后端API创建适当的路径转换,以免每次添加新端点时都须要更新代理配置。例如,若是你使用一个基础路径(例如,\api\
),那么写一个简单的规则,将全部具备该基础路径的请求路由到后端API,并将其余HTTP路径的请求回落到前端资产就比较容易。
最后,我想再次强调一下,若是你不须要使用CORS,请在开发和生产环境中仅对后端API启用相同来源的访问权限。根据个人经验,它将节省大量时间,避免了不少陷阱。
来源:blog.bitsrc.io,做者:Ashan Fernando,翻译:前端外文精选