Skip to content

Commit

Permalink
feat(runtime): support interceptor function #341 (#579)
Browse files Browse the repository at this point in the history
  • Loading branch information
maslow authored Dec 24, 2022
1 parent 3f6927c commit 17f7606
Showing 1 changed file with 76 additions and 0 deletions.
76 changes: 76 additions & 0 deletions runtimes/nodejs/src/handler/invoke-func.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,24 @@ import { handleDebugFunction } from './debug-func'
import { parseToken } from '../support/token'

const DEFAULT_FUNCTION_NAME = '__default__'
const INTERCEPTOR_FUNCTION_NAME = '__interceptor__'

/**
* Handler of invoking cloud function
*/
export async function handleInvokeFunction(req: IRequest, res: Response) {
// intercept the request, skip websocket request
if (false === req.method.startsWith('WebSocket')) {
const passed = await invokeInterceptor(req, res)
if (passed === false) return
}

// debug mode
if (req.get('x-laf-debug-token')) {
return await handleDebugFunction(req, res)
}

// trigger mode
let isTrigger = false
if (parseToken(req.get('x-laf-trigger-token'))) {
isTrigger = true
Expand Down Expand Up @@ -93,3 +102,70 @@ export async function handleInvokeFunction(req: IRequest, res: Response) {
return res.status(500).send('Internal Server Error')
}
}

async function invokeInterceptor(req: IRequest, res: Response) {
const requestId = req.requestId
const func_name = INTERCEPTOR_FUNCTION_NAME

// load function data from db
let funcData = await CloudFunction.getFunctionByName(func_name)
// pass if no interceptor
if (!funcData) {
return true
}

const func = new CloudFunction(funcData)

try {
// execute the func
const ctx: FunctionContext = {
query: req.query,
files: req.files as any,
body: req.body,
headers: req.headers,
method: req.method,
auth: req['auth'],
user: req.user,
requestId,
request: req,
response: res,
__function_name: func.name,
}
const result = await func.invoke(ctx)

// return false to reject request if interceptor got error
if (result.error) {
logger.error(
requestId,
`invoke function ${func_name} invoke error: `,
result,
)

res.status(400).send({
error: `invoke ${func_name} function got error, please check the function logs`,
requestId,
})

return false
}

// if response has been ended, return false to stop the request
if (res.writableEnded) {
return false
}

// reject request if interceptor return false
if (false === result.data) {
res.status(403).send({ error: 'Forbidden', requestId })
return false
}

// pass the request
return result.data
} catch (error) {
logger.error(requestId, `failed to invoke ${func_name}`, error)
return res
.status(500)
.send(`Internal Server Error - got error in ${func_name}`)
}
}

0 comments on commit 17f7606

Please sign in to comment.