Apache 模块:每个请求的输出不断增长
我有一个基于 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
I have an idea for a project based on the Apache module API. So, I am writing my first Apache module to learn the API- just a simple hostname lookup:
URL: http://localhost/hostname/stackoverflow.com
Response data:
Host: stackoverflow.com
Address: 69.59.196.211
Address type: AF_INET
When the request does not include a hostname after the handler path, I just want the Response data to say:
"Hostname not found in request."
All of this is working, except one thing: the error response keeps getting appended to on subsequent requests that produce the error result. This does not happen with the hostname lookup result (when the hostname is provided). Example of the issue:
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.
I'm sure I've done something wrong with my output buffer in the error case - anyone able to point out the problem? Here is the code:
#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
};
Thanks in advance,
-aj
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您以错误的方式使用了
memset
参数:该行使用的计数为零,这意味着它什么也不做。您可以这样做,而不是使用 memset:
这会将整个数组初始化为零(C 中的对象永远不会部分初始化)。
或者,您可以仅将第一个字符设置为零,因为这也会使
strcat
做正确的事情:(此外,您应该将缓冲区大小传递给
lookup_hostname
并使用strncat
/snprintf
而不是strcat
/sprintf
)。You have the parameters to
memset
around the wrong way:That line uses a count of zero, which means it does nothing. Instead of using memset, you could just do this:
This will initialise the entire array to zero (objects in C are never partially initialised).
Alternatively, you could set just the first character to zero, since that will also make
strcat
do the right thing:(Also, you should be passing the buffer size to
lookup_hostname
and usingstrncat
/snprintf
instead ofstrcat
/sprintf
).