WebNodes are Nodes that can be used to create HTTP based guis for games / applications, using a [WebNode] tree for routing. They only work when they are a child of a [WebServer].
Their main purpose is to route [WebServerRequest]s, and then to send responses when the proper node was found (or to send errors if it wasn't). The handle_request_main() method is responsible for routing. It can be overridden if the default behaviour needs to be customized. Processing a request and sending a response should take place in the _handle_request() method. This will get called when a request's handler node is found.
As mentioned in [WebServerRequest]'s documentation, this framework uses a stack like url routing model, where the http path is split along forward slashes, and then these get handled going deeper into the given [WebServer]'s [WebNode] hierarchy, effectively using the node structure as a pseudo filesystem. The HTTP uri can be set using the [code]uri_segment[/code] property. Of course [WebNode]s can override this behaviour. For an example look at [WebRoot], or [BrowsableFolderServeWebPage].
When the [WebServer] receives an HTTP request, it creates a [WebServerRequest] from it, and then passes this request to the root [WebNode]'s handle_request_main() method. Note that [WebRoot] types will handle request a bit differently than normal [WebNodes], as they will not try handle the request by themselves, if they are matched, instead they try to pass it to a child node which has it's uri segment set to "/", if they can't they send a 404.
It will contain convenience methods for working with [Database]s if the database module was enabled when the engine was compiled (default).
For a concrete example Let's say we have the following WebNode structure:
So [WebRoot] will look at the current segment of the request, which is going to be "school". It has a WebNode child with "school" set as it's uri segment, so it will call push_path() on the request, and then call the selected WebNode's handle_request_main() method. The school WebNode will now look at the request, and notice that the current segment is "programming", so it will try to route the request to it's children. If it can't it will send an error. In this example it can, so it will call push_path() on the request, and pass it to the matching WebNode's handle_request_main(). The "programming" WebNode will now look at the Request, and notice that now the current uri segment is "/", and thus will call it's own _handle_request_main(), which will render and send back the contents that it's supposed to.
Since the routing was successful, if the selected WebNode (if it's set up that way), will also try to render the HTML menu using WebNode's render_menu() helper method.
This method is where you should render your error pages. If an error happens during processing a request, by default you should call send_error() in the given [WebServerRequest], that in turn will call this method on your root [WebNode].
This method is called when a WebNode was selected by handle_request_main() to handle a [WebServerRequest]. This is where you should implement your HTML rendering, error handling, and even POST request processing logic for a [WebNode].
This is where routing happens. If you need to implement custom routing logic, that's when you should override this method. you can look at [WebRoot], or [BrowsableFolderServeWebPage] for as simpler examples.
The [WebServer] passes [WebServerRequest]s to it's root [WebNode]'s handle_request_main().
Migrations are used for updating / creating the database table structure / data initially (or after an update for example). Only this method needs to be called, it will properly call the other migration related methods using the supplied parameters.
If you want to trigger an app-wide migration, call the [DatabaseManager] singleton's migrate method. It will notify all [WebNode]s.
You can use override this for a default render of the page. It is for convenience, by default it's not used. For example [UserWebPage]s use these in their _handle_request() methods to simplify drawing logic a lot.
Call this method on a [WebNode] to make it actually render a menu into the given [WebServerRequest]. This is where you implement your HTML menu rendering logic.
Call this method on a [WebNode] to render a menu into the given [WebServerRequest]. When your [WebNode] wants to render a menu, call this method. The default implementaion will call render_main_menu() on the [WebServer]'s root [WebNode], so that's where you should create your site wide menu rendering logic.
If you want more control over menu rendering for some of your [WebNode]s, like they need to render a custom menu, that's when you override this method.
Rendering a preview can be requested using this method. Implement your preview drawing logic here. THink like on a Blog when listing entries you want to render a small preview of each article.
Request a write lock, in order to be able to change your active [WebNode] tree (children). Actually change the tree in _notification, when you receive NOTIFICATION_WEB_NODE_WRITE_LOCKED.
Note that HTTP servers are highly asynchronous, and due to how the system works adding and even removing [WebNode]s from the tree is not that big of a deal, however deallocating [WebNode]s while they are processing requests will crash your app sooner or later. Just to be safe I recommended that you lock your [WebNode] tree branch before touching it.
Do not forget to make your nodes refresh their internal handler map when you change the tree using other helper methods like build_handler_map().
This allows you to set different database connections to different branches of the [WebNode] tree. If a [Database] instance is set to a [WebNode] it's children will automatically also use that particular Database instance.
The HTTP uri segment of this node used when routing a [WebServerRequest]. For example if we take this url: "http://127.0.0.1/atest/btest/ctest", "atest" is uri_segment 1, "btest" is uri_segment 2, "atest" is uri_segment 3.
This allows you to set different permission sets to different branches of the [WebNode] tree. They could allow a user with certain traits to edit the contents of a certain branch. If a [WebPermission] instance is set to a [WebNode] it's children will automatically also use that particular Database instance.