📄 mod_example.c
字号:
/* * Now, if we're not in request context, see if we've been called with * this particular combination before. The table is allocated in the * module's private pool, which doesn't get destroyed. */ if (r == NULL) { char *key; key = ap_pstrcat(p, note, ":", where, NULL); if (ap_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. */ ap_table_set(static_calls_made, key, "been here"); } } addon = ap_pstrcat(p, " <LI>\n", " <DL>\n", " <DT><SAMP>", note, "</SAMP>\n", " </DT>\n", " <DD><SAMP>[", where, "]</SAMP>\n", " </DD>\n", " </DL>\n", " </LI>\n", NULL); sofar = (trace_copy == NULL) ? "" : trace_copy; trace_copy = ap_pstrcat(p, sofar, addon, NULL); if (r != NULL) { ap_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, 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){ excfg *cfg = (excfg *) 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 connexion *//* (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 example_handler(request_rec *r){ excfg *dcfg; dcfg = our_dconfig(r); trace_add(r->server, r, dcfg, "example_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. */ r->content_type = "text/html"; ap_soft_timeout("send example call trace", r); ap_send_http_header(r); /* * If we're only supposed to send header information (HEAD request), we're * already there. */ if (r->header_only) { ap_kill_timeout(r); 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 PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n", 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", ap_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. */ ap_kill_timeout(r); /* * 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. *//* * All our module-initialiser does is add its trace to the log. */static void example_init(server_rec *s, pool *p){ char *note; char *sname = s->server_hostname; /* * Set up any module cells that ought to be initialised. */ setup_module_cells(); /* * The arbitrary text we add to our trace entry indicates for which server * we're being called. */ sname = (sname != NULL) ? sname : ""; note = ap_pstrcat(p, "example_init(", sname, ")", NULL); trace_add(s, NULL, NULL, note);}/* * 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. *//* * All our process-initialiser does is add its trace to the log. */static void example_child_init(server_rec *s, pool *p){ char *note; char *sname = s->server_hostname; /* * Set up any module cells that ought to be initialised. */ setup_module_cells(); /* * The arbitrary text we add to our trace entry indicates for which server * we're being called. */ sname = (sname != NULL) ? sname : ""; note = ap_pstrcat(p, "example_child_init(", sname, ")", NULL); trace_add(s, NULL, NULL, note);}/* * 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. *//* * All our process-death routine does is add its trace to the log. */static void example_child_exit(server_rec *s, pool *p){ char *note; char *sname = s->server_hostname; /* * The arbitrary text we add to our trace entry indicates for which server * we're being called. */ sname = (sname != NULL) ? sname : ""; note = ap_pstrcat(p, "example_child_exit(", sname, ")", NULL); trace_add(s, NULL, NULL, note);}/* * This function gets called to create up 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. */static void *example_create_dir_config(pool *p, char *dirspec){ excfg *cfg; char *dname = dirspec; /* * Allocate the space for our record from the pool supplied. */ cfg = (excfg *) ap_pcalloc(p, sizeof(excfg)); /* * Now fill in the defaults. If there are any `parent' configuration * records, they'll get merged as part of a separate callback. */ cfg->local = 0; cfg->congenital = 0; cfg->cmode = CONFIG_MODE_DIRECTORY; /* * Finally, add our trace to the callback list. */ dname = (dname != NULL) ? dname : ""; cfg->loc = ap_pstrcat(p, "DIR(", dname, ")", NULL); trace_add(NULL, NULL, cfg, "example_create_dir_config()"); return (void *) cfg;}/* * This function gets called to merge two per-directory configuration * records. This is typically done to cope with things like .htaccess files * or <Location> directives for directories that are beneath one for which a * configuration record was already created. The routine has the * responsibility of creating a new record and merging the contents of the * other two into it appropriately. If the module doesn't declare a merge * routine, the record for the closest ancestor location (that has one) is * used exclusively. * * The routine MUST NOT modify any of its arguments! * * The return value is a pointer to the created module-specific structure * containing the merged values. */static void *example_merge_dir_config(pool *p, void *parent_conf, void *newloc_conf){ excfg *merged_config = (excfg *) ap_pcalloc(p, sizeof(excfg)); excfg *pconf = (excfg *) parent_conf; excfg *nconf = (excfg *) newloc_conf;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -