httpd-modules-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Michael Spiegle <m...@nauticaltech.com>
Subject Re: How do you handle multiple custom config containers?
Date Wed, 11 Feb 2009 06:46:03 GMT
Michael Spiegle wrote:
> Hi All,
> I'm writing a module called mod_gfx which will perform on-the-fly image 
> resizing via libgd.  I wanted to make the module as configurable as 
> possible so others can take advantage of it as well.  I'm currently 
> running into a rough spot with custom containers, but first I'd like to 
> make mention of how the module works.

I don't think it is correct, but I have found a solution for now.  Since 
  I can only seem to execute directives inside a container via 
ap_walk_config(), and it requires a section_vector to be working, I'm 
(ab)using ap_set_config_vectors() to send a tag to the per-dir config 
allocator so it knows what type of config to allocate.  I have no idea 
how bad this is, but it appears to be working.  Here's the relevant code:

static const char*
gfx_config_profile(cmd_parms* cmd, void* p, const char* arg) {
     const char* endp = ap_strrchr_c(arg, '>');
     const char* args;
     char* profile_name;
     ap_conf_vector_t* gfx_conf;

     ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "Entering 
gfx_config_profile callback");

     //create a new profile for each <GfxProfile> encountered
     gfx_conf = ap_create_per_dir_config(cmd->pool);

     const char* err = ap_check_cmd_context(cmd, NOT_IN_LIMIT | 
NOT_IN_DIRECTORY);

     if (err != NULL)
         return err;

     //get the profile name (argument to <GfxProfile>)
     //do some checks for good measure
     args = apr_pstrndup(cmd->pool, arg, endp - arg);
     if (!args[0])
         return apr_psprintf(cmd->pool, "%s %s", cmd->cmd->name, "> 
directive requires profile name");

     if (endp == NULL)
         return apr_psprintf(cmd->pool, "%s %s", cmd->cmd->name, "> 
directive missing closing '>'");

     profile_name = ap_getword_conf(cmd->pool, &args);
     if (!profile_name)
         return apr_psprintf(cmd->pool, "%s %s", cmd->cmd->name, "> 
error reading profile name");

     //i abusing this by sending <GfxProfile> so the container creator 
knows what type to give me back
     gfx_profile_config_t* profile = ap_set_config_vectors(cmd->server, 
gfx_conf, "<GfxProfile>", &gfx_module, cmd->pool);

     //setup profile
     profile->name = apr_pstrdup(cmd->pool, profile_name);

     //not sure yet - i hope it iterates over the gfx parms in the 
<GfxProfile>
     err = ap_walk_config(cmd->directive->first_child, cmd, gfx_conf);
     if (err != NULL)
         return err;

     //add profile to server profiles hashmap
     gfx_server_config_t* sconf = 
ap_get_module_config(cmd->server->module_config, &gfx_module);
     apr_hash_set(sconf->profiles, profile->name, APR_HASH_KEY_STRING, 
profile);

     return NULL;
}

static const char*
gfx_config_origin(cmd_parms* cmd, void* p, const char* arg) {
     const char* endp = ap_strrchr_c(arg, '>');
     const char* args;
     char* origin_name;
     ap_conf_vector_t* gfx_conf;

     ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "Entering 
gfx_config_origin callback");

     //create a new origin for each <GfxOrigin> encountered
     gfx_conf = ap_create_per_dir_config(cmd->pool);

     const char* err = ap_check_cmd_context(cmd, NOT_IN_LIMIT | 
NOT_IN_DIRECTORY);

     if (err != NULL)
         return err;

     //get the origin name (argument to <GfxOrigin>)
     //do some checks for good measure
     args = apr_pstrndup(cmd->pool, arg, endp - arg);
     if (!args[0])
         return apr_psprintf(cmd->pool, "%s %s", cmd->cmd->name, "> 
directive requires origin name");

     if (endp == NULL)
         return apr_psprintf(cmd->pool, "%s %s", cmd->cmd->name, "> 
directive missing closing '>'");

     origin_name = ap_getword_conf(cmd->pool, &args);
     if (!origin_name)
         return apr_psprintf(cmd->pool, "%s %s", cmd->cmd->name, "> 
error reading origin name");

     //i think this associates the generic config type with my origin config
     gfx_origin_config_t* origin = ap_set_config_vectors(cmd->server, 
gfx_conf, "<GfxOrigin>", &gfx_module, cmd->pool);

     //setup origin
     origin->name = apr_pstrdup(cmd->pool, origin_name);

     //not sure yet - i hope it iterates over the gfx parms in the 
<GfxOrigin>
     err = ap_walk_config(cmd->directive->first_child, cmd, gfx_conf);
     if (err != NULL)
         return err;

     //add origin to server origins
     gfx_server_config_t* sconf = 
ap_get_module_config(cmd->server->module_config, &gfx_module);
     apr_hash_set(sconf->origins, origin->name, APR_HASH_KEY_STRING, 
origin);

     return NULL;
}


static void*
gfx_create_server_config(apr_pool_t* pool, server_rec* server) {
     gfx_server_config_t* sconf;
     sconf = (gfx_server_config_t*)apr_pcalloc(pool, 
sizeof(gfx_server_config_t));

     sconf->profiles = apr_hash_make(pool);
     sconf->origins = apr_hash_make(pool);

     ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "Created server config");

     return (void*)sconf;
}

static void*
gfx_create_container_config(apr_pool_t* pool, char* arg) {
     //I'm not really sure why apache calls this function at startup
     //I don't think I need it, so I'm just going to ignore it...
     if (arg == NULL)
         return (void*)NULL;

     //Create a GfxProfile struct on-command and pass it back to the caller
     if (strcmp(arg, "<GfxProfile>") == 0) {
         gfx_profile_config_t* profile;
         profile = (gfx_profile_config_t*)apr_pcalloc(pool, 
sizeof(gfx_profile_config_t));
         profile->name = NULL;
         profile->output_format = IMAGE_TYPE_SRC;
         profile->actions = apr_array_make(pool, 8, sizeof(const char*));
         profile->rsx = 0;
         profile->rsy = 0;
         profile->qual = 0;
         ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "Created 
<GfxProfile> container");
         return profile;
     }

     //Create a GfxOrigin struct on-command and pass it back to the caller
     if (strcmp(arg, "<GfxOrigin>") == 0) {
         gfx_origin_config_t* origin;
         origin = (gfx_origin_config_t*)apr_pcalloc(pool, 
sizeof(gfx_origin_config_t));
         origin->name = NULL;
         origin->hosts = apr_array_make(pool, 16, sizeof(const char*));
         ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "Created 
<GfxOrigin> container");
         return origin;
     }

     //default case.  shouldn't ever happen
     ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "Error creating 
container (%s)", arg);
     return (void*)NULL;
}


static const
command_rec gfx_cmds[] = {
     AP_INIT_RAW_ARGS("<GfxProfile", gfx_config_profile, NULL, RSRC_CONF,
                          "Container to create profiles"),
     AP_INIT_NO_ARGS("</GfxProfile>", NULL, NULL, RSRC_CONF, "Place 
Holder"),
     AP_INIT_RAW_ARGS("<GfxOrigin", gfx_config_origin, NULL, RSRC_CONF,
                      "Container to create origin hosts"),
     AP_INIT_NO_ARGS("</GfxOrigin>", NULL, NULL, RSRC_CONF, "Place Holder"),
     AP_INIT_ITERATE("GfxActions", gfx_profile_actions, NULL, RSRC_CONF,
                     "Defines a list of actions to perform on the image"),
     AP_INIT_TAKE1("GfxRsX", gfx_profile_rsx, NULL, RSRC_CONF,
                   "Specifies a maximum width to resize to"),
     AP_INIT_TAKE1("GfxRsY", gfx_profile_rsy, NULL, RSRC_CONF,
                   "Specifies a maximum height to resize to"),
     AP_INIT_TAKE1("GfxQual", gfx_profile_qual, NULL, RSRC_CONF,
                   "Specifies the quality (if supported by output format)"),
     AP_INIT_TAKE1("GfxOutputFormat", gfx_profile_outputformat, NULL, 
RSRC_CONF,
                   "Specifies the ouput format"),
     AP_INIT_TAKE2("GfxOriginMatch", gfx_config_originmatch, NULL, 
RSRC_CONF,
                   "A regex to declare origins"),
     AP_INIT_TAKE1("GfxOriginHost", gfx_config_originhost, NULL, RSRC_CONF,
                   "Define a host to origin content from"),
     { NULL }
};

module AP_MODULE_DECLARE_DATA gfx_module = {
     STANDARD20_MODULE_STUFF,
     gfx_create_container_config, //do I really need this?
     NULL,                        //i'm too lazy to implement merging
     gfx_create_server_config,    //create server config
     NULL,                        //i'm too lazy to implement merging
     gfx_cmds,                    //command table
     gfx_register_hooks           //hooks
};

Mime
View raw message