代码之家  ›  专栏  ›  技术社区  ›  AJ.

Apache模块:每个请求的输出都在不断增长

  •  1
  • AJ.  · 技术社区  · 15 年前

    我有一个基于Apache模块API的项目的想法。因此,我编写了第一个Apache模块来学习API——只是简单的主机名查找:

    URL:  http://localhost/hostname/stackoverflow.com
    Response data:
    Host: stackoverflow.com
    Address: 69.59.196.211
    Address type: AF_INET
    

    当请求在处理程序路径后不包含主机名时,我只希望响应数据说:

    “在请求中找不到主机名。”

    除了一件事外,所有这些都可以工作:错误响应会不断附加到产生错误结果的后续请求上。主机名查找结果(提供主机名时)不会出现这种情况。问题示例:

    Request 1:  http://192.168.1.3/hostname
    Response data:
    Hostname not found in request.
    
    Request 2:  http://192.168.1.3/hostname
    Response data:
    Hostname not found in request.
    Hostname not found in request.
    
    Request 3:  http://192.168.1.3/hostname
    Response data:
    Hostname not found in request.
    Hostname not found in request.
    Hostname not found in request.
    

    我确信我在错误情况下对输出缓冲区做了一些错误——有人能指出问题所在吗?代码如下:

    #include <sys/types.h>
    #include <netdb.h>
    #include <stdio.h>
    #include <stdarg.h>
    
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    
    #include "httpd.h"
    #include "http_log.h"
    #include "http_config.h"
    
    
    static void log_info(request_rec *r, const char *fmt, ...){
        char log_msg[100];
        memset(log_msg,100,0x00);
        va_list args;
        va_start(args,fmt);
        vsprintf(log_msg,fmt,args);
        va_end(args);
        ap_log_error(APLOG_MARK,APLOG_INFO,APR_SUCCESS,r->server,log_msg,NULL);
    }
    static void log_err(request_rec *r, const char *fmt, ...){
        char log_msg[100];
        memset(log_msg,100,0x00);
        va_list args;
        va_start(args,fmt);
        vsprintf(log_msg,fmt,args);
        va_end(args);
        ap_log_error(APLOG_MARK,APLOG_ERR,APR_SUCCESS,r->server,log_msg,NULL);
    }
    
    int count_chrinstr(const char *haystack, const char needle){
        int n=0;
        char *next;
        while( (next=strchr(haystack,needle)) != NULL ){
            haystack=next+1;
            n++;
        }
    
        return n;
    }
    void parse_uri(char *uri, char *pieces[]){
        int i=0;
        char *next_tok=strtok(uri,"/");
        while( next_tok != NULL ){
            pieces[i]=next_tok;
            i++;
            next_tok=strtok(NULL,"/");
        }
    }
    
    void lookup_hostname(request_rec *r, char *output){
        int num_parts=count_chrinstr(r->uri,'/');
        log_info(r,"Number of parts: %d",num_parts);
        if(num_parts<2){
            log_err(r,"Hostname not found in request, exiting.",NULL);
            strcat(output,"Hostname not found in request.<br>\n");
            return;
        }
    
        char *pieces[num_parts];
        parse_uri(r->uri,pieces);
        char *host_entered=pieces[1];
    
        struct hostent *h=gethostbyname(host_entered);
    
        //host
        output += sprintf(output,"Host: %s<br>\n", h->h_name);
    
        //aliases
        int i=0;
        while(h->h_aliases[i] != NULL){
            output += sprintf(output,"Alias: %s<br>\n",h->h_aliases[i]);
            i++;
        }
    
        //addresses
        i=0;
        while(h->h_addr_list[i] != NULL){
            char *net_addr=inet_ntoa( *(struct in_addr*)(h->h_addr_list[i]));
            output += sprintf(output,"Address: %s<br>\n",net_addr);
            i++;
        }
        log_info(r,"Added addresses to output.",NULL);
    
        //address type
        if(h->h_addrtype != NULL){
            switch(h->h_addrtype){
                case 2:
                    strcat(output,"Address type: AF_INET<br>\n");
                    break;
                case 10:
                    strcat(output,"Address type: AF_INET6<br>\n");
                    break;
                default:
                    strcat(output,"Address type: Unknown<br>\n");
                    break;
            }
        }
    
    }
    
    static int hostname_handler(request_rec *r) {
      if (!r->handler || strcasecmp(r->handler, "hostname") != 0) {
        return DECLINED;
      }
    
      if (r->method_number != M_GET) {
        return HTTP_METHOD_NOT_ALLOWED;
      }
    
      char result[10000];
      memset(result,10000,0x00);
    
      log_info(r,"Starting hostname lookup.",NULL);
      lookup_hostname(r,result);
      ap_set_content_type(r, "text/html");
      ap_rputs(result, r);
      ap_finalize_request_protocol(r);
    
      return OK;
    }
    
    
    static void hostname_hooks(apr_pool_t *pool) {
      ap_hook_handler(hostname_handler, NULL, NULL, APR_HOOK_MIDDLE);
    }
    
    module AP_MODULE_DECLARE_DATA hostname_module = {
      STANDARD20_MODULE_STUFF,
      NULL,
      NULL,
      NULL,
      NULL,
      NULL,
      hostname_hooks
    };
    

    事先谢谢,

    AJ

    1 回复  |  直到 15 年前
        1
  •  3
  •   caf    15 年前

    你有参数来 memset 走错了路:

    memset(result,10000,0x00);
    

    该行使用的是零计数,这意味着它什么也不做。不使用memset,只需执行以下操作:

    char result[10000] = { 0 };
    

    这会将整个数组初始化为零(C中的对象永远不会部分初始化)。

    或者,您可以将第一个字符设置为零,因为这也会使 strcat 做正确的事:

    char result[10000];
    result[0] = '\0';
    

    (另外,应该将缓冲区大小传递给 lookup_hostname 并使用 strncat / snprintf 而不是 字符串连接函数 / sprintf )

    推荐文章