FCF 2.0 development in progress...
> > >
[News] [Packages API] [Downloads] [Donate to the project] [Contacts]

Context

To save session data, the FCF framework provides execution context functionality. This functionality provides access to session data both on the NODEJS server side and on the browser side. The execution context is an instance of the fcf.Context class, which has the following predefined fields:
  • boolean debug = false - Debug flag. Used to load original (debug versions) JS modules with fcf.require() and fcf.module() functions

  • string language = fcf.getConfiguration().defaultLanguage - The language used by the user.

  • fcf.RouteInfo route - An object with information about the current URL route

  • object session - An object with information about the user, used to determine access rights.

    • object groups = {} - User groups. The key and value is the name of the group. When an object is created, the value is always equal to the default value.

    • object roles = {} - User roles. The key and value is the name of the role. When an object is created, the value is always equal to the default value.

    • string user = "" - Username. When an object is created, the value is always equal to the default value.

If necessary, the list of fields can be expanded

On the server side, the execution context is available from the moment it is set (calling the fcf.setContext() function) and in all subsequent calls. The execution context object is accessed via the fcf.getContext() function

function printValue() { console.log(fcf.getContext().value); } let context = new fcf.Context(); context.value = 1; fcf.setContext(context); await new Promise((a_resolve)=>{ a_resolve(); }); printValue();

Output:

1

The execution context data when sending a browser request to the server is passed through a cookie or through the HTTP header in the "fcf-context" parameter, in the case of using the fcf.load() function.

To create an execution context based on the database received from the browser when using the Express server, it is enough to pass the request object to the constructor fcf.Context()

let libExpress = require("express"); let server = libExpress(); server.get("/index1", (a_req, a_res) => { fcf.setContext( new fcf.Context(a_req) ); console.log("URL:", fcf.getContext().route.url); console.log("Context data:", fcf.getContext().data); a_res.send(""); }); let listener; await fcf.actions() .then((a_res, a_act)=>{ listener = server.listen(8697, ()=>{ a_act.complete(); }); }) .then(async ()=>{ fcf.getContext().data = "value"; await fcf.load("http://127.0.0.1:8697/index1?data=1", {external: true}); }) .finally(()=>{ if (listener){ listener.close(); } });

Output:

URL: /index1?data=1 Context data: value

If another HTTP server is used, then it is necessary to pass an object to the fcf.Context() constructor, which should contain the following fields:

  • string url - Request URL

  • object postArgs - Object containing request arguments passed as POST data

  • string|object context - Execution context data sent by the client.

    If the property is set to a string, then the field must contain data in JSON format encoded in base64.

    The field can also be set by an object, in which case the property must contain an object with the data of the passed context from the client.

Example:

let libExpress = require("express"); let server = libExpress(); server.use(libExpress.json()); server.get("/index1", (a_req, a_res) => { fcf.setContext( new fcf.Context({ url: a_req.originalUrl, postArgs: a_req.body, context: a_req.headers["fcf-context"], }) ); console.log("URL:", fcf.getContext().route.url); console.log("Context data:", fcf.getContext().data); a_res.send(""); }); let listener; await fcf.actions() .then((a_res, a_act)=>{ listener = server.listen(8697, ()=>{ a_act.complete(); }); }) .then(async ()=>{ fcf.getContext().data = "value"; await fcf.load("http://127.0.0.1:8697/index1?data=1", {external: true}); }) .finally(()=>{ if (listener){ listener.close(); } });

Output:

URL: /index1?data=1 Context data: value

In addition to the execution context, the framework uses a state object that stores internal system data and the execution context. Similar to the execution context, once the state is set (calling the fcf.setState() function), it is passed to all subsequent function calls.

The function fcf.getState() is used to get the state object

On the browser side, only one global state and execution context object is always used.

On the server side, the state object and execution context are automatically preserved when using asynchronous calls and timers.

But if a function call is made, the result of which is supplied via a callback, which is initialized in a separate execution task not created by the caller, then a loss of context will occur. To restore the context, it is enough to re-set the initial state using the fcf.setState() function

Example:

let state = fcf.getState(); somethingFunction((a_error, a_result)=>{ fcf.setState(state); });

or wrap the call in an fcf.Actions object or use the asynchronous util.promisify() call from the util library.

Example:

fcf.actions() .then((a_res, a_act)=>{ somethingFunction((a_error, a_result)=>{ if (a_error){ a_act.error(a_error); } else { a_act.complete(a_result); } }); }) .then(()=>{ // The original execution context is already available here });

The fcf.saveContext() function is used to save the context in cookies. Which, when called on the server side, must accept an Express server response object. On the browser side, the function is called without parameters.

Server side example:

let libExpress = require("express"); let server = libExpress(); server.get("/index1", (a_req, a_res) => { fcf.saveContext(a_res); a_res.send(""); }); ...

If the Express server is not used to process the response on the server side, then to save the context in cookies, you need to save the data in the "fcf-context" cookie parameter in JSON format, which in turn must be encoded in base64 format