Description
When deploying ltijs in Firebase Cloud Functions, the deep linking flow generates URLs that are missing the Cloud Function's base path prefix, resulting in 404 errors.
Environment
ltijs version: 5.9.7
ltijs-firestore version: 2.2.0
Deployment: Firebase Cloud Functions (Node.js 22)
Framework: Express (via ltijs)
The Problem
In Firebase Cloud Functions, all routes are automatically prefixed with the function name. For example, if the function is named ltiFunction, all routes become:
/ltiFunction/login
/ltiFunction/deeplink
/ltiFunction/launch
However, when ltijs generates URLs during the deep linking flow (specifically after lti.DeepLinking.createDeepLinkingMessage()), it creates URLs without this prefix:
https://domain.com/deeplink?ltik=... ❌
Instead of: https://domain.com/ltiFunction/deeplink?ltik=... ✓
This causes the LMS to redirect users to a non-existent route, resulting in 404 errors.
Configuration
await lti.setup(
encryptionKey,
{ plugin: firestoreAdapter },
{
appRoute: "/launch",
loginRoute: "/login",
keysetRoute: "/keys",
deeplinkingRoute: "/deeplink",
cookies: {
secure: true,
sameSite: "None"
},
sessionTimeout: 3600,
serverless: true,
https: false,
devMode: false
}
);
await lti.deploy({ serverless: true });
The Cloud Function is deployed as:
javascriptexport const ltiFunction = onRequest(httpsOpts, async (req, res) => {
await initOnce();
return lti.app(req, res);
});
Expected Behavior
ltijs should generate URLs that include the base path where the Express app is mounted. When deployed as a Cloud Function named ltiFunction, the generated URLs should be:
https://domain.com/ltiFunction/deeplink?ltik=...
https://domain.com/ltiFunction/launch
Actual Behavior
ltijs generates URLs without the function name prefix:
https://domain.com/deeplink?ltik=...
https://domain.com/launch
Attempted Workarounds
Setting Express mountpath: Tried setting lti.app.mountpath = '/ltiFunction' but ltijs doesn't seem to use this property when building URLs.
URL rewriting: Currently using regex to fix URLs in the generated HTML:
const fixedForm = form.replace(
/https:\/\/([^\/]+)\/deeplink/g,
'https://$1/ltiFunction/deeplink'
);
This works but is not an ideal solution.
Separate redirect function: Tried creating a separate Cloud Function to redirect /deeplink → /ltiFunction/deeplink, but this loses session state.
Question
Is there a proper way to configure ltijs to be aware of the base path when deployed in a serverless environment where routes are prefixed? For example:
A configuration option to set the base URL or path prefix?
A way to tell ltijs about the Express app's mount point?
Any other recommended approach for Cloud Functions deployment?
Additional Context
This issue is specific to serverless platforms that automatically prefix routes:
Firebase Cloud Functions (function name prefix)
AWS Lambda with API Gateway (stage prefix)
Azure Functions (function app prefix)
A configuration option to set a base path would make ltijs more compatible with these serverless environments.
Description
When deploying ltijs in Firebase Cloud Functions, the deep linking flow generates URLs that are missing the Cloud Function's base path prefix, resulting in 404 errors.
Environment
ltijs version: 5.9.7
ltijs-firestore version: 2.2.0
Deployment: Firebase Cloud Functions (Node.js 22)
Framework: Express (via ltijs)
The Problem
In Firebase Cloud Functions, all routes are automatically prefixed with the function name. For example, if the function is named ltiFunction, all routes become:
/ltiFunction/login
/ltiFunction/deeplink
/ltiFunction/launch
However, when ltijs generates URLs during the deep linking flow (specifically after lti.DeepLinking.createDeepLinkingMessage()), it creates URLs without this prefix:
https://domain.com/deeplink?ltik=... ❌
Instead of: https://domain.com/ltiFunction/deeplink?ltik=... ✓
This causes the LMS to redirect users to a non-existent route, resulting in 404 errors.
Configuration
Expected Behavior
ltijs should generate URLs that include the base path where the Express app is mounted. When deployed as a Cloud Function named ltiFunction, the generated URLs should be:
https://domain.com/ltiFunction/deeplink?ltik=...
https://domain.com/ltiFunction/launch
Actual Behavior
ltijs generates URLs without the function name prefix:
https://domain.com/deeplink?ltik=...
https://domain.com/launch
Attempted Workarounds
Setting Express mountpath: Tried setting lti.app.mountpath = '/ltiFunction' but ltijs doesn't seem to use this property when building URLs.
URL rewriting: Currently using regex to fix URLs in the generated HTML:
This works but is not an ideal solution.
Separate redirect function: Tried creating a separate Cloud Function to redirect /deeplink → /ltiFunction/deeplink, but this loses session state.
Question
Is there a proper way to configure ltijs to be aware of the base path when deployed in a serverless environment where routes are prefixed? For example:
A configuration option to set the base URL or path prefix?
A way to tell ltijs about the Express app's mount point?
Any other recommended approach for Cloud Functions deployment?
Additional Context
This issue is specific to serverless platforms that automatically prefix routes:
Firebase Cloud Functions (function name prefix)
AWS Lambda with API Gateway (stage prefix)
Azure Functions (function app prefix)
A configuration option to set a base path would make ltijs more compatible with these serverless environments.