Merged in fix/service-token-error-handling (pull request #673)
fix: improve error handling Approved-by: Christel Westerberg Approved-by: Arvid Norlin
This commit is contained in:
@@ -50,8 +50,6 @@ export function serverClient() {
|
||||
redirect(redirectUrl)
|
||||
}
|
||||
}
|
||||
|
||||
throw internalServerError()
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ const fetchServiceTokenFailCounter = meter.createCounter(
|
||||
|
||||
async function fetchServiceToken(scopes: string[]) {
|
||||
fetchServiceTokenCounter.add(1)
|
||||
|
||||
const response = await fetch(`${env.CURITY_ISSUER_USER}/oauth/v2/token`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
@@ -36,52 +37,67 @@ async function fetchServiceToken(scopes: string[]) {
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
fetchServiceTokenFailCounter.add(1, {
|
||||
error_type: "http_error",
|
||||
error: JSON.stringify({
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
}),
|
||||
})
|
||||
throw new Error("Failed to obtain service token")
|
||||
}
|
||||
|
||||
return response.json()
|
||||
}
|
||||
|
||||
export async function getServiceToken(): Promise<ServiceTokenResponse> {
|
||||
try {
|
||||
const scopes = ["profile", "hotel", "booking"]
|
||||
const tag = generateServiceTokenTag(scopes)
|
||||
const getCachedJwt = unstable_cache(
|
||||
async (scopes) => {
|
||||
const jwt = await fetchServiceToken(scopes)
|
||||
|
||||
const expiresAt = Date.now() + jwt.expires_in * 1000
|
||||
return { expiresAt, jwt }
|
||||
},
|
||||
[tag],
|
||||
{ tags: [tag] }
|
||||
)
|
||||
|
||||
const cachedJwt = await getCachedJwt(scopes)
|
||||
if (cachedJwt.expiresAt < Date.now()) {
|
||||
console.log(
|
||||
"trpc.context.serviceToken: Service token expired, revalidating tag"
|
||||
)
|
||||
revalidateTag(tag)
|
||||
|
||||
console.log(
|
||||
"trpc.context.serviceToken: Fetching new temporary service token."
|
||||
)
|
||||
fetchTempServiceTokenCounter.add(1)
|
||||
const newToken = await fetchServiceToken(scopes)
|
||||
return newToken
|
||||
const text = await response.text()
|
||||
const error = {
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
text,
|
||||
}
|
||||
|
||||
return cachedJwt.jwt
|
||||
} catch (error) {
|
||||
console.error("Error fetching service token:", error)
|
||||
throw error
|
||||
fetchServiceTokenFailCounter.add(1, {
|
||||
error_type: "http_error",
|
||||
error: JSON.stringify(error),
|
||||
})
|
||||
|
||||
console.error(
|
||||
"fetchServiceToken error",
|
||||
JSON.stringify({
|
||||
query: {
|
||||
grant_type: "client_credentials",
|
||||
client_id: env.CURITY_CLIENT_ID_SERVICE,
|
||||
scope: scopes.join(" "),
|
||||
},
|
||||
error,
|
||||
})
|
||||
)
|
||||
|
||||
throw new Error(
|
||||
`[fetchServiceToken] Failed to obtain service token: ${JSON.stringify(error)}`
|
||||
)
|
||||
}
|
||||
|
||||
return response.json() as Promise<ServiceTokenResponse>
|
||||
}
|
||||
|
||||
export async function getServiceToken() {
|
||||
const scopes = ["profile", "hotel", "booking"]
|
||||
const tag = generateServiceTokenTag(scopes)
|
||||
const getCachedJwt = unstable_cache(
|
||||
async (scopes) => {
|
||||
const jwt = await fetchServiceToken(scopes)
|
||||
|
||||
const expiresAt = Date.now() + jwt.expires_in * 1000
|
||||
return { expiresAt, jwt }
|
||||
},
|
||||
[tag],
|
||||
{ tags: [tag] }
|
||||
)
|
||||
|
||||
const cachedJwt = await getCachedJwt(scopes)
|
||||
if (cachedJwt.expiresAt < Date.now()) {
|
||||
console.log(
|
||||
"trpc.context.serviceToken: Service token expired, revalidating tag"
|
||||
)
|
||||
|
||||
revalidateTag(tag)
|
||||
|
||||
console.log(
|
||||
"trpc.context.serviceToken: Fetching new temporary service token."
|
||||
)
|
||||
fetchTempServiceTokenCounter.add(1)
|
||||
const newToken = await fetchServiceToken(scopes)
|
||||
return newToken
|
||||
}
|
||||
|
||||
return cachedJwt.jwt
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ export const safeProtectedProcedure = t.procedure.use(async function (opts) {
|
||||
export const serviceProcedure = t.procedure.use(async (opts) => {
|
||||
const { access_token } = await getServiceToken()
|
||||
if (!access_token) {
|
||||
throw internalServerError(`Failed to obtain service token`)
|
||||
throw internalServerError(`[serviceProcedure] No service token`)
|
||||
}
|
||||
return opts.next({
|
||||
ctx: {
|
||||
@@ -144,7 +144,9 @@ export const serviceServerActionProcedure = serverActionProcedure.use(
|
||||
async (opts) => {
|
||||
const { access_token } = await getServiceToken()
|
||||
if (!access_token) {
|
||||
throw internalServerError("Failed to obtain service token")
|
||||
throw internalServerError(
|
||||
"[serviceServerActionProcedure]: No service token"
|
||||
)
|
||||
}
|
||||
return opts.next({
|
||||
ctx: {
|
||||
|
||||
Reference in New Issue
Block a user