One way to understand how TiddlyWeb operates is to examine what happens in the system when a {{{GET}}} request for a single tiddler is made. Since the primary role of TiddlyWeb is to make tiddlers available, this touches on the main features. As an overview this touches on, rather than describes, the main concepts. For more depth, follow the links.
In a default instance a tiddler may be requested via two URIs:
- by bag via /bags/{bag_name}/tiddlers/{tiddler_title}
- by recipe via /recipes/{recipe_name}/tiddlers/{tiddler_title}
To keep things (relatively) simple this description will address the bag-based request. This is appropriate because the canonical URI for a tiddler is the one which address the tiddler in its bag. For a description of how things are handled when addressing the recipe see recipe cascade.
TiddlyWeb is architected as a stack of WSGI applications wrapping the core tiddlyweb application. This stack is hosted by (or mounted on) a web server. See Architecture Overview for more information.
Assuming a bag name of {{{cars}}} and a tiddler title of {{{buick}}} a {{{GET}}} request proceeds as follows.
The web server receives the request, creates an initial WSGI environment and hands off to the first application in the stack.
{{{Environator}}} logs initial request information to the debugging log (if enabled).
{{{Configurator}}} adds the current tiddlyweb configuration to the WSGI {{{environ}}}.
{{{Query}}} parses and processes any query string parameters and any {{{POSTed}}} form parameters into {{{tiddlyweb.query}}} in the environment. Any parameters which are filters are parsed as such, and added to {{{tiddlyweb.filters}}}.
{{{StoreSet}}} establishes and initializes a connection to the store defines in configuration.
{{{UserExtract}}} runs the credentials extraction process. If an authentic user is found their information is added to {{{tiddlyweb.usersign}}}. If no user is found, the user is set to {{{GUEST}}}.
{{{Header}}} manipulates a {{{HEAD}}} request into a {{{GET}}} but truncates the output. For this {{{GET}}} request, nothing happens at this layer.
{{{Negotiate}}} determines what representation of the requested resource is desired. This happens in one of two ways: By processing the {{{Accept}}} header or by evaluating an extension provided at the end of the URI. The determine type is put into {{{tiddlyweb.type}}} for later reference.
The selector app examines the URI and determines which handler (defined in urls.map) maps to this request URI and method. In this case the mapping is {{{GET tiddlyweb.web.handler.tiddler:get}}}. That is, the {{{get}}} method in the module {{{tiddlyweb.web.handler.tiddler}}}.
That method looks at the name of the bag and the title and uses that to create tiddler and bag objects.
The bag is loaded from the store (established in {{{tiddlyweb.store}}}). If the bag does not exist an HTTP {{{404}}} is sent as a response.
The current user (in {{{tiddlyweb.usersign}}}) is checked against the ''read'' constraint of the bag's policy. If the user does not pass, a {{{PermissionsError}}} is raised, to be handled by the {{{PermissionsExceptor}}} (described below).
If the current user can read from the bag, the tiddler is loaded from the store. If the tiddler does not exist a {{{404}}} is sent.
The headers of the request are checked for cache-validation headers ({{{If-None-Match}}} or {{{If-Modified-Since}}}) and compared with tiddler data. If the cache is valid a {{{304}}} is sent as a response, with no body.
If there are no validation headers, or they are invalid, the tiddler is serialized to generate the output content.
Headers are set, a status of {{{200}}} is set, and the content returned to the rest of the stack.
The {{{PermissionsExceptor}}} checks for policy violations earlier in the processing and turns them into appropriate responses. If the {{{cars}}} bag's policy required a user for access, the current request will be redirected to the challenger system.
The {{{HTTPExceptor}}} checks for HTTP exceptions raised earlier in the code and turns them into appropriate responses. If the {{{cars}}} bag or {{{buick}}} tiddler don't exists, a 404 exception would have been raised. It is here that it is turned into a well formed response sent to the user agent.
{{{EncodeUTF8}}} run to translate unicode content into {{{UTF-8}}} encoded byte strings. Internally TiddlyWeb keeps all textual content as unicode, transforming to/from {{{UTF-8}}} at the boundaries.
{{{TransformProtect}}} adds a {{{Cache-Control: no-transform}}} header to protect against broken caches which transform content (such as minifying JavaScript).
{{{SimpleLog}}} logs the request to a log file (if configured).
The web server sends the headers and body to the user agent.
!! See Also: