2023年3月7日 星期二

AdonisJs第六天,全域取得context

 在AdonisJs設計中,原本只有Cntroller Method可以取得context(簡寫ctx),但在某些特殊情境下需要取得ctx,且無法透過controller傳遞參數怎麼辦呢?

小編在官網上尋找答案只找到可以使用以下方法,但在實際運行卻什麼也取不到,程式碼如下:

import HttpContext from '@ioc:Adonis/Core/HttpContext'
class SomeService {
public async someOperation() {
const ctx = HttpContext.get()
}
}

應該是缺少一點東西,小編把get改成getOrFail,讓他把錯誤印出來,錯誤訊息顯示

E_INVALID_ALS_ACCESS: HTTP context is not available. Set "useAsyncLocalStorage" to true inside "config/app.ts" file

所以應該是少了設定,只是這設定要加在哪裡,官方文件上只有文字描述要加設定,卻沒有告訴你怎麼做,加在哪。好在config/app.ts裡面設定也不多,一個一個嘗試後是加在

export const http: ServerConfig = {
    ...... // 中間忽略
    useAsyncLocalStorage: true,
}

以下看個使用情境

import { BaseModel, column, beforeSave } from "@ioc:Adonis/Lucid/Orm"
import Hash from "@ioc:Adonis/Core/Hash"
import HttpContext from "@ioc:Adonis/Core/HttpContext"
export default class User extends BaseModel {
  @column({ serializeAs: null })
public password: string

@beforeSave()
public static async beforeSave(user: User) {
    // 當路由名稱為approve時,實際命名方法如下
    // Route.post('xxx', 'XxxController.method').as('approve')
if (HttpContext.get()?.route?.name == "approve") {
return
}
if (user.$dirty.password) {
user.password = await Hash.make(user.password)
}
}
}

基本上在user password改變的前提下都需要經過加密,但就是有某些特殊場景不用,但又懶得把邏輯拆出來到service見一次做一次,只好用這個訪法去完成。

另外還有一個解法,是當判斷

user.password.startsWith("$argon2")

但這有一些問題,例如加密的方法如果改用不是argon lib加密,開頭就會變,或是他就是需要加密在加密。這些往往會變成bug,不過也是要看需求拉。以上就是這次簡短分享,也算做個筆記。

沒有留言:

張貼留言