mod_aclr

Alexey Polyakov alexey.polyakov at gmail.com
Fri Dec 23 23:44:14 MSK 2005


Супер!
Еще бы теперь научить nginx кешировать соответствия uri-filename, в
случае возврата x-accel-redirect, чтобы каждый раз не лазить на
бекэнд.

On 12/23/05, Dmitriy MiksIr <miksir at maker.ru> wrote:
> В таком случае к тестированию предлагаю модуль =)
> Идея модуля такова - но становится обработчиком */* запросов. Апач
> вызывает этот хендлер только если не было никаких других обработок его,
> т.е. имеем то, что нам надо - выдачу голого файла.
> В этом случае модуль выдает X-Accel-Redirect без тела самого файла
> (устанавливая Content-Length: 0)
>
> Переданный X-Accel-Redirect состоит из двух частей - строки, принятой от
> вронтенда в заголовке X-Accel-Internal и собственно URI.
> Таким образом конфиг nginx выгладит приблизительно так:
>
>      server {
>          listen       81;
>          server_name  www;
>
>          location / {
>              proxy_pass          http://127.0.0.1:80;
>              proxy_set_header    X-Real-IP  $remote_addr;
>              proxy_set_header    X-Accel-Internal /internal_843t;
>              proxy_set_header    Host $http_host;
>              proxy_redirect_errors on;
>          }
>
>          location /internal_843t/ {
>              root                /path/to/htdocs/;
>              rewrite             ^/internal_843t/(.*)$ /$1 break;
>              index               index.html index.htm;
>              internal;
>          }
>      }
>
> Модуль, собственно, умеет 2 директивы
>
>     AccelRedirectSet [On|Off]
>       Включение модуля
>     AccelRedirectSize number[k|M]
>       Установка минимального размера запрашиваемого файла, начиная с
> которого будут выдаваться редиректы
>     Контенты обоих директив: server config, virtual host, directory
>
> Установка в апач, конечно же
> /usr/local/apache/bin/apxs -c mod_aclr.c
> /usr/local/apache/bin/apxs -i mod_aclr.so
> И руками добавить
> LoadModule aclr_module        libexec/mod_aclr.so
> AddModule mod_aclr.c
>
> Буду признателен за любые замечания, как по алгоритму, так и по коду.
>
>
> /* -------------------------------------------------------------------------- *\
>  * mod_aclr.c                                                                 *
>  * Dmitriy MiksIr <miksir at maker.ru>                                           *
>  *                                                                            *
>  * Description FIX IT                                                         *
>  *                                                                            *
>  * This program is free software; you can redistribute it and/or              *
>  * modify it under the terms of the GNU General Public License                *
>  * as published by the Free Software Foundation; either version 2             *
>  * of the License, or (at your option) any later version.                     *
>  *                                                                            *
>  * This program is distributed in the hope that it will be useful,            *
>  * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
>  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
>  * GNU General Public License for more details.                               *
>  *                                                                            *
>  * You should have received a copy of the GNU General Public License          *
>  * along with this program; if not, write to the Free Software                *
>  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.*
> \* -------------------------------------------------------------------------- */
>
> /*
>   $Id: mod_aclr.c,v 1.1 2005/12/23 14:05:06 cvs Exp $
> */
>
> #include "httpd.h"
> #include "http_config.h"
> #include "http_request.h"
> #include "http_protocol.h"
> #include "http_core.h"
> #include "http_main.h"
> #include "http_log.h"
>
> module aclr_module;
>
> #define ACLR_VERSION "0.01"
>
> #define ACLR_ENABLED 1
> #define ACLR_DISABLED 0
> #define UNSET -1
>
> typedef struct {
>   int state;
>   long long fsize;
> } aclr_dir_config;
>
> /* ----------------------------------------- */
>
> long long parse_bytes(const char *arg) {
>   long long ret;
>   int arglen = strlen(arg);
>   char last_char = arg[arglen - 1];
>   int i;
>   char arg1[256];
>
>   if (arglen >= 256) return(-1);
>
>   if(last_char == 'K' || last_char == 'k'
>     || last_char == 'M' || last_char == 'm') {
>        arglen --;
>   }
>
>   snprintf(arg1,sizeof(arg1),"%s",arg);
>
>   for (i=0;i<arglen;i++) {
>     if(!isdigit(arg1[i])) return(-1);
>   }
>
>   if(last_char == 'K' || last_char == 'k')
>     return(atoll(arg1) * 1024);
>
>   if(last_char == 'M' || last_char == 'm')
>     return(atoll(arg1) * 1048576);
>
>   return(atoll(arg1));
> }
>
> /* ----------------------------------------- */
>
> static int aclr_handler(request_rec *r)
> {
>   long long     filesize;
>   int           rc;
>   const char    *idhead;
>   char          iredirect[1024];
>   aclr_dir_config *cfg = (aclr_dir_config *)ap_get_module_config(r->per_dir_config, &aclr_module);
>
>   if(cfg->state != ACLR_ENABLED)
>     return(DECLINED);
>
>   if (idhead = ap_table_get(r->headers_in, "X-Accel-Internal")) {
>      if (strlen(idhead)+strlen(r->uri) >= 1024)
>          return(DECLINED);
>      snprintf(iredirect,sizeof(iredirect),"%s%s",idhead,r->uri);
>   } else {
>      return(DECLINED);
>   }
>
>   ap_table_set(r->headers_out, "X-ACLR-Version", ACLR_VERSION);
>
>   if ((rc = ap_discard_request_body(r)) != OK) {
>     return rc;
>   }
>
>   if (r->method_number != M_GET)
>     return(DECLINED);
>
>   if (r->finfo.st_mode == 0 || (r->path_info && *r->path_info))
>     return(DECLINED);
>
>   filesize = r->finfo.st_size;
>   if (cfg->fsize != UNSET && filesize < cfg->fsize)
>     return(DECLINED);
>
>   ap_table_set(r->headers_out, "X-Accel-Redirect", iredirect);
>
>   ap_update_mtime(r, r->finfo.st_mtime);
>   if (rc = ap_set_content_length(r, 0))
>      return rc;
>   ap_send_http_header(r);
>
>   return OK;
> }
>
> /* ------------------------------------------ */
>
> static void *aclr_create_dir_config(pool *p, char *path) {
>   aclr_dir_config *cfg = (aclr_dir_config *)ap_palloc(p, sizeof(aclr_dir_config));
>   cfg->state   = UNSET;
>   cfg->fsize   = UNSET;
>   return( (void *)cfg );
> }
>
> /* ------------------------------------------ */
>
> static const char *aclr_cmd_state(cmd_parms *parms, void *mconfig, int flag) {
>   aclr_dir_config *cfg = (aclr_dir_config *)mconfig;
>   cfg->state = (flag ? ACLR_ENABLED : ACLR_DISABLED);
>   return(NULL);
> }
>
> static const char *aclr_cmd_size(cmd_parms *parms, void *mconfig, const char *arg) {
>   aclr_dir_config *cfg = (aclr_dir_config *)mconfig;
>   long long bytes = parse_bytes(arg);
>
>   if (bytes >= 0) {
>      cfg->fsize = bytes;
>   } else {
>      cfg->fsize = UNSET;
>      ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, parms->server,  "Argument %s of AccelRedirectSize is not number", arg);
>   }
>
>   return(NULL);
> }
>
> static const command_rec aclr_cmds[] = {
>   { "AccelRedirectSet", aclr_cmd_state, NULL, ACCESS_CONF | RSRC_CONF, FLAG,
>     "turn X-Accel-Redirect support On or Off (default Off)" },
>   { "AccelRedirectSize", aclr_cmd_size, NULL, ACCESS_CONF | RSRC_CONF, TAKE1,
>     "minimum size of file for redirect in bytes" },
>   { NULL }
> };
>
> /* ------------------------------------------- */
>
> static const handler_rec aclr_handlers[] = {
>   { "*/*",          aclr_handler },
>   { NULL }
> };
>
> module MODULE_VAR_EXPORT aclr_module = {
>   STANDARD_MODULE_STUFF,
>   NULL,                       /* module initializer                  */
>   aclr_create_dir_config,     /* create per-dir    config structures */
>   NULL,                       /* merge  per-dir    config structures */
>   NULL,                       /* create per-server config structures */
>   NULL,                       /* merge  per-server config structures */
>   aclr_cmds,                  /* table of config file commands       */
>   aclr_handlers,              /* [#8] MIME-typed-dispatched handlers */
>   NULL,                       /* [#1] URI to filename translation    */
>   NULL,                       /* [#4] validate user id from request  */
>   NULL,                       /* [#5] check if the user is ok _here_ */
>   NULL,                       /* [#3] check access by host address   */
>   NULL,                       /* [#6] determine MIME type            */
>   NULL,                       /* [#7] pre-run fixups                 */
>   NULL,                       /* [#9] log a transaction              */
>   NULL,                       /* [#2] header parser                  */
>   NULL,                       /* child_init                          */
>   NULL,                       /* child_exit                          */
>   NULL                        /* [#0] post read-request              */
> };
>
>
>


--
Alexey Polyakov


More information about the nginx-ru mailing list