在微服務的架構中,常見會選擇前後端分離,但是有些情況還是需要把 ReactJS 或是其他種的 JS SPA 與 Quarkus 放在一起,做一個微單體的設計與服務,這時會有些眉角要注意,本篇會示範何把 Quarkus後端與 React 前端頁面包在一起。
Quarkus 的服務,當 request url 有在 /src/main/resource/META-INF/resources
相對位置的 html file, 就可以 access.所以我們可以把 React compiler 好的 index.html 與file 放到此處。 只是 React 預設的執行環境是 NodeJS,一些 route 的行為是不需要實體的 html file,React Route 有分兩種,詳細你要去哪裡:React Router 這個說明的不錯滿好的
Type | Sample URL | Quarkus Effort |
---|---|---|
browserHistory | http://localhost:3000/users/2 | 程式多一點 |
hashHistory | http://localhost:3000/#/users/2 | 少 |
因為 /#/users/2
是指到 index.html 與 Quarkus 行為一致,不需改 code
因為 /users/2
會是 Quarkus 接到,找了一圈發現沒有 /user/2
這個網址。也沒有相對的 api, 就會出 404 ERROR。 所以這些都找不到時,我們得導去 index.html。所以作一個客製化 IndexResource 。當找不到時,就會自已輸出 index.html 的內容,當然這樣是暴力了點,但有用,而且前端新增 route 也不用動作。
@Path("/")
class IndexResource {
companion object {
private const val INDEX_RESOURCE = "/META-INF/resources/index.html"
}
@GET
@Path("/{fileName:.+}")
suspend fun responseIndexContent(@PathParam("fileName") fileName: String): Response = IndexResource::class
.java.getResourceAsStream(INDEX_RESOURCE).let {
Response
.ok(it)
.cacheControl(CacheControl.valueOf("max-age=900"))
.type(MediaType.TEXT_HTML_TYPE)
.build()
}
}
或是前端能列舉所有的 route ,可以在 Quarkus 這邊列舉,作到更仔細的管理。
@GET
@Path("/user/{fileName:.+}")
suspend fun responseIndexContent(@PathParam("fileName") fileName: String): Response = IndexResource::class
.java.getResourceAsStream(INDEX_RESOURCE).let {
Response
.ok(it)
.cacheControl(CacheControl.valueOf("max-age=900"))
.type(MediaType.TEXT_HTML_TYPE)
.build()
}
@GET
@Path("/task/{fileName:.+}")
suspend fun responseTaskContent(@PathParam("fileName") fileName: String): Response = responseIndexContent(fileName)
主要是要把 React project 在 compile 後,要 cp 一份到 src/main/META-INF/resources/
因為我們在開發時,還是會前後端分離, Quarkus 要 enable CORS
quarkus.http.cors=true
quarkus.http.cors.origins=http://localhost:3000
quarkus.http.cors.headers=accept, origin, authorization, content-type, x-requested-with
quarkus.http.cors.methods=GET,POST,DELETE,OPTIONS
在 React 這邊,要設定 env.development
REACT_APP_API_URL=http://localhost:8080/api/v1
就可以利用 http://localhost:3000 來測前後端
在權限上,/* 表示所有頁面都會認證,有新的 rule 可以往後看,在 quarkus 設定時,可以利用 quarkus.http.auth.permission.[policyName].paths 達到多組權限的操作設定。例如以下我們要鎖 /*
,但是開放 health, 就如下操作。
quarkus.http.auth.permission.authenticated.paths=/*
quarkus.http.auth.permission.authenticated.policy=authenticated
quarkus.http.auth.permission.health.paths=/q/health/*
quarkus.http.auth.permission.health.policy=permit
%test.quarkus.oidc.application-type=service