iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 21
0
Mobile Development

老姐好像要用 Kotlin 寫專案,能撐30天嗎?系列 第 21

家家烤肉的第二十一天:攔截 Route 製作專屬處理

  • 分享至 

  • xImage
  •  

從窗戶飄入陣陣烤肉香,我趕緊揪住老姐,要不然老姐就跑出去了。

「今天放假一天也沒關係的啦。」老姐很不開心。

「再等我一下,快改好了。」我匆匆加上幾行程式碼,然後 run application 測試。

看到結果我放心的鬆開手中的布料。「好了,成功了!」

老姐停下腳步,驚訝的問:「什麼什麼?多房間聊天室架好了?」

「哪有那麼快啦。我是弄好之前說的 API 版本 authenticate 。」我邊說邊悄悄把右手的手機藏到背後打字,傳給烤肉店延後十分鐘到的訊息。「你看,原本的長這樣,需要手動複製很多程式碼。」

    get("/api/topics") {
        val session = call.sessions.get<LoginSession>()//需要複製的程式碼
        session?.let {//需要複製的程式碼
            val topics = transaction {
                Topic.all().with(Topic::author, Topic::tags).map {
                    ...
                }
            }
            call.respond(topics)
        } ?: call.respond(HttpStatusCode.Unauthorized)//需要複製的程式碼
    }

「現在只要把目標 API 移進 authenticationAPI<LoginSession> 區塊。」

    authenticationAPI<LoginSession> {
        get("/api/topics") {
            val topics = transaction {
                Topic.all().with(Topic::author, Topic::tags).map {
                    ...
                }
            }
            call.respond(topics)
        }
    }

「太神了!你怎麼做到的?」老姐瞪大眼睛。她本以為我只會獨立出一個 method 取代 session?.let 的部分。

「我研究了一下 authentication 對 Route 做的事。」要做就做最好的。

inline fun <reified T> Route.authenticationAPI(callback: Route.() -> Unit): Route {
    // With createChild, we create a child node for this received Route
    val routeAuthenticationAPI = this.createChild(object : RouteSelector(1.0) {
        override fun evaluate(context: RoutingResolveContext, segmentIndex: Int): RouteSelectorEvaluation =
            RouteSelectorEvaluation.Constant
    })

    // Intercepts calls from this route at the features step
    routeAuthenticationAPI.intercept(ApplicationCallPipeline.Features) {
        call.sessions.get<T>() ?: run {
            call.respond(HttpStatusCode.Unauthorized)
            finish()
            return@intercept
        }
    }

    // Configure this route with the block provided by the user
    callback(routeAuthenticationAPI)

    return routeAuthenticationAPI
}

我語帶驕傲的解釋:「關鍵是 createChild ,沒用它的話就會影響到全部的 route , finish() 表示提前結束,不用再叫原本的 route 做事。然後 session 我用的是 泛型 Generic Type ,因為說不定後面會是 multiple sessions 架構,如果真的是那樣我還可以把 HttpStatusCode 那邊改成參數傳入。」我的手指在鍵盤上蠢蠢欲動。

沒有 finish() 的白做工圖片記錄,一樣去資料庫拿資料,只是沒印在 response 。

https://ithelp.ithome.com.tw/upload/images/20201001/20129197NkWdhR6sY2.png
https://ithelp.ithome.com.tw/upload/images/20201001/20129197h0vswIYj3M.png

「等一下!還有更重要的事!」老姐一臉驚恐。「店裡預約要遲到了!」

好吧,不確定會重複利用的細部就先不模組化設計了。吃肉去!

本次鐵人賽的作品在放進更多內容後已經成書,書名是《老姐要用Kotlin寫專案:從 Server 到 Android APP 的開發生存日記》,歡迎購買唷。https://www.tenlong.com.tw/products/9789864348978


上一篇
節省開支的第二十天:Eager loading 原理——快取和 IN 運算子
下一篇
各自努力的第二十二天:聊天室範例拼接(上)
系列文
老姐好像要用 Kotlin 寫專案,能撐30天嗎?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言