Docs ResponseHandling » History » Revision 7
Revision 6 (kjikaqawej, 2011-01-05 22:38) → Revision 7/8 (kjikaqawej, 2011-01-05 22:48)
h2. Response handling in response.c -- this may help to understand how the config works too. (I removed the @con->@ prefix from the code so it is easier to read; so @mode@ is @con->mode@ in the source) The conditional checks are activated at specific points as you will see; so modules which do something in their uri_clean handler will probably never trigger if you wrap them in a @$PHYSICAL["existing-path"]@ conditional. In every @handle(foo)@ call the module handlers are called in the order the modules have been loaded. But this does not mean that by inserting a module before another will make it always handling the request before the other, as not every module implements every handler. One example for this is mod_rewrite/mod_redirect: rewrite handles uri_raw, redirect uri_clean - so rewrite will always act before redirect (for now - I suggest you load mod_rewrite before mod_redirect so you are on the safe side if this changes). The request handling is restarted if a handler returns @HANDLER_COMEBACK@ (mod_rewrite, mod_proxy_core, mod_magnet). *TODO*: At which point should @config_cond_cache_reset(srv, con)@ be executed? *TODO*: What about @HANDLER_WAIT_FOR_FD@? If a request handler does not return @HANDLER_GO_ON@ , request handling stops (remaining module handlers are not called!) and the return value from the handler is returned. @mode@ indicates which module wants to generate the content; @mode @_mode == DIRECT@ DIRECT_@ ends in mod_staticfile (the default value); modules should set it to their own id if they handle the request: @con->mode = p->id@ . If @mode _mode != DIRECT@ DIRECT_ you have to generate error messages yourself, so if you want lighty to send an error (or trigger the error-handler) @mode@ must be @DIRECT@; just set @http_status@ to an error status and return @HANDLER_FINISHED@. If you want to know if another module already handled the request, do something like this: <pre> if (con->mode != DIRECT || con->http_status != 0) return HANDLER_GO_ON; </pre> So, let's start (this is basically the simplified code from @response.c@): <pre> handle_request() { if (mode == DIRECT and (http_status != 0 or http_status != 200)) return HANDLER_FINISHED if (mode == DIRECT and empty(physical.path)) { // We need a physical path, i.e. a filename activate_conditionals($SERVER["socket"], $HTTP["scheme"], $HTTP["host"], $HTTP["remote-ip"], $HTTP["referer"], $HTTP["user-agent"], $HTTP["cookie"], $HTTP["request-method"]) split(request.uri -> uri.path_raw '?' uri.query) handle(uri_raw) urldecode_and_simplify(uri.raw -> uri.path); // "sanitising" activate_conditionals($HTTP["url"], $HTTP["query-string"]) handle(uri_clean) response to the query 'OPTIONS *' set default physical.doc_root (server.document-root from the last matching conditional) set default physical.rel_path = uri.path [lighty-1.5] filename_unix2local(physical.rel_path) handle(docroot) lowercase physical.rel_path on case insensitive platforms physical.path = physical.docroot + physical.rel_path [lighty-1.5] remove trailing DIR_SEPERATOR from physical.path handle(phyiscal) activate_conditionals($PHYSICAL["path"]) } if (mode == DIRECT) { // Now we should have a physical.path if (exists(phyiscal.path)) { if (is_symlink(phyiscal.path) and not conf.follow_symlinks) return FORBIDDEN() // 403 if (is_dir(phyiscal.path) and uri.path does not end with a '/') return redirect_to_dir(); // append '/' } else if (some physical.path component was not a directory) { // errno = ENOTDIR split phyiscal.path into (a existing filename) physical.path and request.path_info } [lighty-1.5] activate_conditionals($PHYSICAL["existing-path"]) [lighty-1.4] handle(subrequest_start) [lighty-1.5] handle(start_backend) [lighty-1.4] if (mode == DIRECT and http_status == 0) { // no one wanted to send content if (request.http_method == 'OPTIONS') OK() // 200 else FORBIDDEN() // 403; } } [lighty-1.4] handle(subrequest); [lighty-1.5] if (mode == DIRECT) { // no one wanted to send content FORBIDDEN() // 403 } } </pre>