📄 mod_example.c
字号:
const char *sofar; char *addon; char *where; apr_pool_t *p; const char *trace_copy; /* * Make sure our pools and tables are set up - we need 'em. */ setup_module_cells(); /* * Now, if we're in request-context, we use the request pool. */ if (r != NULL) { p = r->pool; if ((trace_copy = apr_table_get(r->notes, TRACE_NOTE)) == NULL) { trace_copy = ""; } } else { /* * We're not in request context, so the trace gets attached to our * module-wide pool. We do the create/destroy every time we're called * in non-request context; this avoids leaking memory in some of * the subsequent calls that allocate memory only once (such as the * key formation below). * * Make a new sub-pool and copy any existing trace to it. Point the * trace cell at the copied value. */ apr_pool_create(&p, x_pool); if (trace != NULL) { trace = apr_pstrdup(p, trace); } /* * Now, if we have a sub-pool from before, nuke it and replace with * the one we just allocated. */ if (x_subpool != NULL) { apr_pool_destroy(x_subpool); } x_subpool = p; trace_copy = trace; } /* * If we weren't passed a configuration record, we can't figure out to * what location this call applies. This only happens for co-routines * that don't operate in a particular directory or server context. If we * got a valid record, extract the location (directory or server) to which * it applies. */ where = (mconfig != NULL) ? mconfig->loc : "nowhere"; where = (where != NULL) ? where : ""; /* * Now, if we're not in request context, see if we've been called with * this particular combination before. The apr_table_t is allocated in the * module's private pool, which doesn't get destroyed. */ if (r == NULL) { char *key; key = apr_pstrcat(p, note, ":", where, NULL); if (apr_table_get(static_calls_made, key) != NULL) { /* * Been here, done this. */ return; } else { /* * First time for this combination of routine and environment - * log it so we don't do it again. */ apr_table_set(static_calls_made, key, "been here"); } } addon = apr_pstrcat(p, " <li>\n" " <dl>\n" " <dt><samp>", note, "</samp></dt>\n" " <dd><samp>[", where, "]</samp></dd>\n" " </dl>\n" " </li>\n", NULL); sofar = (trace_copy == NULL) ? "" : trace_copy; trace_copy = apr_pstrcat(p, sofar, addon, NULL); if (r != NULL) { apr_table_set(r->notes, TRACE_NOTE, trace_copy); } else { trace = trace_copy; } /* * You *could* change the following if you wanted to see the calling * sequence reported in the server's error_log, but beware - almost all of * these co-routines are called for every single request, and the impact * on the size (and readability) of the error_log is considerable. */#define EXAMPLE_LOG_EACH 0 if (EXAMPLE_LOG_EACH && (s != NULL)) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_example: %s", note); }}/*--------------------------------------------------------------------------*//* We prototyped the various syntax for command handlers (routines that *//* are called when the configuration parser detects a directive declared *//* by our module) earlier. Now we actually declare a "real" routine that *//* will be invoked by the parser when our "real" directive is *//* encountered. *//* *//* If a command handler encounters a problem processing the directive, it *//* signals this fact by returning a non-NULL pointer to a string *//* describing the problem. *//* *//* The magic return value DECLINE_CMD is used to deal with directives *//* that might be declared by multiple modules. If the command handler *//* returns NULL, the directive was processed; if it returns DECLINE_CMD, *//* the next module (if any) that declares the directive is given a chance *//* at it. If it returns any other value, it's treated as the text of an *//* error message. *//*--------------------------------------------------------------------------*//* * Command handler for the NO_ARGS "Example" directive. All we do is mark the * call in the trace log, and flag the applicability of the directive to the * current location in that location's configuration record. */static const char *cmd_example(cmd_parms *cmd, void *mconfig){ x_cfg *cfg = (x_cfg *) mconfig; /* * "Example Wuz Here" */ cfg->local = 1; trace_add(cmd->server, NULL, cfg, "cmd_example()"); return NULL;}/*--------------------------------------------------------------------------*//* *//* Now we declare our content handlers, which are invoked when the server *//* encounters a document which our module is supposed to have a chance to *//* see. (See mod_mime's SetHandler and AddHandler directives, and the *//* mod_info and mod_status examples, for more details.) *//* *//* Since content handlers are dumping data directly into the connection *//* (using the r*() routines, such as rputs() and rprintf()) without *//* intervention by other parts of the server, they need to make *//* sure any accumulated HTTP headers are sent first. This is done by *//* calling send_http_header(). Otherwise, no header will be sent at all, *//* and the output sent to the client will actually be HTTP-uncompliant. *//*--------------------------------------------------------------------------*//* * Sample content handler. All this does is display the call list that has * been built up so far. * * The return value instructs the caller concerning what happened and what to * do next: * OK ("we did our thing") * DECLINED ("this isn't something with which we want to get involved") * HTTP_mumble ("an error status should be reported") */static int x_handler(request_rec *r){ x_cfg *dcfg; if (strcmp(r->handler, "example-handler")) { return DECLINED; } dcfg = our_dconfig(r); trace_add(r->server, r, dcfg, "x_handler()"); /* * We're about to start sending content, so we need to force the HTTP * headers to be sent at this point. Otherwise, no headers will be sent * at all. We can set any we like first, of course. **NOTE** Here's * where you set the "Content-type" header, and you do so by putting it in * r->content_type, *not* r->headers_out("Content-type"). If you don't * set it, it will be filled in with the server's default type (typically * "text/plain"). You *must* also ensure that r->content_type is lower * case. * * We also need to start a timer so the server can know if the connexion * is broken. */ ap_set_content_type(r, "text/html"); /* * If we're only supposed to send header information (HEAD request), we're * already there. */ if (r->header_only) { return OK; } /* * Now send our actual output. Since we tagged this as being * "text/html", we need to embed any HTML. */ ap_rputs(DOCTYPE_HTML_3_2, r); ap_rputs("<HTML>\n", r); ap_rputs(" <HEAD>\n", r); ap_rputs(" <TITLE>mod_example Module Content-Handler Output\n", r); ap_rputs(" </TITLE>\n", r); ap_rputs(" </HEAD>\n", r); ap_rputs(" <BODY>\n", r); ap_rputs(" <H1><SAMP>mod_example</SAMP> Module Content-Handler Output\n", r); ap_rputs(" </H1>\n", r); ap_rputs(" <P>\n", r); ap_rprintf(r, " Apache HTTP Server version: \"%s\"\n", ap_get_server_version()); ap_rputs(" <BR>\n", r); ap_rprintf(r, " Server built: \"%s\"\n", ap_get_server_built()); ap_rputs(" </P>\n", r);; ap_rputs(" <P>\n", r); ap_rputs(" The format for the callback trace is:\n", r); ap_rputs(" </P>\n", r); ap_rputs(" <DL>\n", r); ap_rputs(" <DT><EM>n</EM>.<SAMP><routine-name>", r); ap_rputs("(<routine-data>)</SAMP>\n", r); ap_rputs(" </DT>\n", r); ap_rputs(" <DD><SAMP>[<applies-to>]</SAMP>\n", r); ap_rputs(" </DD>\n", r); ap_rputs(" </DL>\n", r); ap_rputs(" <P>\n", r); ap_rputs(" The <SAMP><routine-data></SAMP> is supplied by\n", r); ap_rputs(" the routine when it requests the trace,\n", r); ap_rputs(" and the <SAMP><applies-to></SAMP> is extracted\n", r); ap_rputs(" from the configuration record at the time of the trace.\n", r); ap_rputs(" <STRONG>SVR()</STRONG> indicates a server environment\n", r); ap_rputs(" (blank means the main or default server, otherwise it's\n", r); ap_rputs(" the name of the VirtualHost); <STRONG>DIR()</STRONG>\n", r); ap_rputs(" indicates a location in the URL or filesystem\n", r); ap_rputs(" namespace.\n", r); ap_rputs(" </P>\n", r); ap_rprintf(r, " <H2>Static callbacks so far:</H2>\n <OL>\n%s </OL>\n", trace); ap_rputs(" <H2>Request-specific callbacks so far:</H2>\n", r); ap_rprintf(r, " <OL>\n%s </OL>\n", apr_table_get(r->notes, TRACE_NOTE)); ap_rputs(" <H2>Environment for <EM>this</EM> call:</H2>\n", r); ap_rputs(" <UL>\n", r); ap_rprintf(r, " <LI>Applies-to: <SAMP>%s</SAMP>\n </LI>\n", dcfg->loc); ap_rprintf(r, " <LI>\"Example\" directive declared here: %s\n </LI>\n", (dcfg->local ? "YES" : "NO")); ap_rprintf(r, " <LI>\"Example\" inherited: %s\n </LI>\n", (dcfg->congenital ? "YES" : "NO")); ap_rputs(" </UL>\n", r); ap_rputs(" </BODY>\n", r); ap_rputs("</HTML>\n", r); /* * We're all done, so cancel the timeout we set. Since this is probably * the end of the request we *could* assume this would be done during * post-processing - but it's possible that another handler might be * called and inherit our outstanding timer. Not good; to each its own. */ /* * We did what we wanted to do, so tell the rest of the server we * succeeded. */ return OK;}/*--------------------------------------------------------------------------*//* *//* Now let's declare routines for each of the callback phase in order. *//* (That's the order in which they're listed in the callback list, *not *//* the order in which the server calls them! See the command_rec *//* declaration near the bottom of this file.) Note that these may be *//* called for situations that don't relate primarily to our function - in *//* other words, the fixup handler shouldn't assume that the request has *//* to do with "example" stuff. *//* *//* With the exception of the content handler, all of our routines will be *//* called for each request, unless an earlier handler from another module *//* aborted the sequence. *//* *//* Handlers that are declared as "int" can return the following: *//* *//* OK Handler accepted the request and did its thing with it. *//* DECLINED Handler took no action. *//* HTTP_mumble Handler looked at request and found it wanting. *//* *//* What the server does after calling a module handler depends upon the *//* handler's return value. In all cases, if the handler returns *//* DECLINED, the server will continue to the next module with an handler *//* for the current phase. However, if the handler return a non-OK, *//* non-DECLINED status, the server aborts the request right there. If *//* the handler returns OK, the server's next action is phase-specific; *//* see the individual handler comments below for details. *//* *//*--------------------------------------------------------------------------*//* * This function is called during server initialisation. Any information * that needs to be recorded must be in static cells, since there's no * configuration record. * * There is no return value. *//* * This function is called when an heavy-weight process (such as a child) is * being run down or destroyed. As with the child initialisation function, * any information that needs to be recorded must be in static cells, since * there's no configuration record. * * There is no return value. *//* * This function is called during server initialisation when an heavy-weight * process (such as a child) is being initialised. As with the * module initialisation function, any information that needs to be recorded * must be in static cells, since there's no configuration record. * * There is no return value. *//* * This function gets called to create a per-directory configuration * record. This will be called for the "default" server environment, and for * each directory for which the parser finds any of our directives applicable. * If a directory doesn't have any of our directives involved (i.e., they * aren't in the .htaccess file, or a <Location>, <Directory>, or related * block), this routine will *not* be called - the configuration for the * closest ancestor is used. * * The return value is a pointer to the created module-specific * structure. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -