本系列文已出版成書「NestJS 基礎必學實務指南:使用強大且易擴展的 Node.js 框架打造網頁應用程式」,感謝 iT 邦幫忙與博碩文化的協助。如果對 NestJS 有興趣、覺得這個系列文對你有幫助的話,歡迎前往購書,你的支持是我最大的寫作動力!
大部分的開發人員在面對前端後端是不同網域的時候,會碰上一個名叫 跨來源資源共享 (Cross-Origin Resource Sharing) 的問題,簡稱 CORS,那這個 CORS 究竟是什麼東西又為什麼會發生呢?這就讓我們來了解一下 CORS 的前因後果吧!
CORS 是一個控管跨網域請求資源的機制,這個機制可以有效將合法與非合法的跨域存取隔開來,讓合法的跨域存取能夠順利取得資源,而這套機制主要是受到 同源政策 的影響。
同源政策的概念很簡單,假設小華有現在很流行的 Switch,他的朋友小明很想玩,所以他可以直接拿來玩不經過小華同意嗎?當然是不行囉,肯定是要經過小華的同意才能夠借來玩,同理,假設 A 網域對 B 網域發出了資源請求,這時候 B 網域同意了 A 網域的存取,那麼這個跨網域的存取才會成功,這就產生出了所謂的 CORS 機制。
CORS 的處理方式會在不同的請求狀況下而有所不同,請求狀況主要分成 簡單請求 與 非簡單請求:
簡單請求的條件如下:
GET
、POST
、HEAD
其中一個。Accept
、 Accept-Language
、 Content-Language
、 Last-Event-ID
、 DPR
、 Save-Data
、 Viewport-Width
、Width
。Content-Type
的值僅接受:application/x-www-form-urlencoded
、 multipart/form-data
、 text/plain
。當該請求為簡單請求時,瀏覽器會判斷其是否為跨域存取並會在 Header 添加相關資訊,若該請求並不屬於合法範圍的話,這個跨域存取將會無效。
當該請求為非簡單請求時,會先向跨域的伺服器端發送 OPTION
的請求,該伺服器會返回許可規則的 Header,在收到規則後,瀏覽器會判斷這個非簡單請求是否符合許可規則,如果符合就會向跨域的伺服器端發送該請求來存取資源。
Nest 與 Express 一樣,預設是不允許跨域存取的,若要啟用的話,只需要在 main.ts
中做配置即可,調用 app
的 enableCors(options?: CorsOptions | CorsOptionsDelegate<any>)
這個方法,就可以順利啟用 CORS:
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.enableCors();
await app.listen(3000);
}
bootstrap();
Nest 的 CORS 功能其實也是將 Express 的 cors 套件進行打包,並直接內建在 Nest 中,所以 options
的配置與 cors
這個套件的配置項目是相同的。
還有另一種開啟 CORS 的方法,就是直接在 NestFactory
的 create
方法中帶入 cors
選項,以下方程式碼為例,直接帶入 true
的效果與 enableCors()
是相同的:
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule, { cors: true });
await app.listen(3000);
}
bootstrap();
CORS 的問題可以說是非常容易遇到,特別是在前後端分離的情況下。真正上線的時候,通常 不會 允許所有跨域存取都是許可的,都會針對特定網域設置白名單等,所以產品上線的時候千萬要記得配置 options
啊!