瞭解如何經過使用前端開發服務器中的代理配置來避免CORS。javascript
在過去的十年中,單頁應用程序已成爲構建Web應用程序的標準技術。現在,諸如Angular,Vue之類的框架以及諸如React之類的庫主導着前端開發,爲這些應用程序提供了基礎平臺。好消息是,它能夠從一個域中爲前臺和後臺API提供服務。但在某些狀況下,咱們會從不一樣的子域中爲前臺(如web.myapp.com)和後臺(如api.myapp.com)提供服務。有時,咱們只容許對開發環境的後端API進行跨域訪問。前端
跨域資源共享(CORS)是在Web瀏覽器中實現的一種機制,用於容許或拒絕來自其餘域的請求到Web應用程序。經過CORS,Web瀏覽器和Web服務器就標準協議達成一致,以瞭解是否容許訪問資源。所以請記住,從後端執行CORS並不意味着Bots或任何其餘機制都沒法訪問您的服務器資源。java
可是,咱們是否須要爲你的Web應用提供CORS?我想說的是,大多數狀況下,你不須要擔憂CORS,由於你的網絡應用是由一個域提供的。然而,可能會有一些特殊的特性,好比容許在主Web應用程序域以外嵌入頁面(例如,表單、視頻),你能夠考慮在後端啓用CORS。不過,你仍然能夠啓用限定範圍到該特定特性的CORS。web
除安全性外,CORS最明顯的問題是對Web應用程序性能的影響。當你的前端向不一樣的域或子域發送一個HTTP請求時,瀏覽器會發送一個額外的HTTP,稱爲preflight(預檢)請求,看服務器是否接受來自發件人域的消息。後端
所以,對於每一個由前端觸發的HTTP請求,瀏覽器須要發送兩個HTTP請求,從而增長了整體響應時間。在大多數狀況下,添加的延遲在Web應用程序中是可見的,而且會對用戶體驗產生負面影響。api
當涉及到單頁面應用程序時,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部署在不一樣的子域中。瀏覽器
可是咱們須要沿着這個方向走嗎?讓咱們看看在開發和生產環境中避免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啓用相同來源的訪問權限。根據個人經驗,它將節省大量時間,避免了不少陷阱。
來源:https://blog.bitsrc.io,翻譯:前端外文精選
本文首發於微信公衆號《前端外文精選》,關注即送大禮包,準能爲你節省很多錢!