我正在尝试创建一个apache过滤器,最终根据传入的状态代码创建自定义输出。
在使用f->r->status
的结果处理与请求相关的所有内容之后,我可以轻松地检索以下函数中的状态代码。
我希望能够在不循环现有数据的情况下进行更改,这是所有其他过滤器所做的事情。我想做的是抛弃现有数据并用我自己的数据替换它。
在下面的代码中,我正在尝试实现以下HTTP标头:
HTTP/1.1 777 Lucky
我正在努力实现这些数据:
Testing
相反,apache日志会报告分段错误。
有没有办法替换输出,还是我必须循环输入并将每个段空白并用我自己的数据替换一个段?
static apr_status_t OUTF(ap_filter_t *f,apr_bucket_brigade *inbb){
conn_rec* c=f->r->connection;
apr_brigade_cleanup(inbb);
apr_bucket_brigade* mybrigade=apr_brigade_create(f->r->pool,c->bucket_alloc);
int len=1000;
char* buf=apr_bucket_alloc(len,c->bucket_alloc);
strcpy(buf,"HTTP/1.1 777 Lucky\r\n\r\nTesting");
apr_bucket* mybucket=apr_bucket_heap_create(buf,len,apr_bucket_free,c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(mybrigade,mybucket);
return ap_pass_brigade(f->next,mybrigade);
}
P.S。:过滤器已被激活并注册,因此每次我请求URL时都会执行此代码,并且在上面的代码中,我收到了分段错误。
答案 0 :(得分:0)
您正在执行apr_bucket_alloc()
,然后将该函数的结果视为char *
并尝试将strcpy()
内容添加到其中。那是不对的。 apr_bucket_alloc()
不会创建char *
。这也不是创建存储桶的正确方法。
你想要的是apr_bucket_pool_create()
。 (它位于apr_buckets.h
,有足够的文档来确定如何调用它。)
如果我们假设您的字符串如此:
char *str = "HTTP/1.1 777 Lucky\r\n\r\nTesting";
然后你可以这样做:
apr_bucket *b = apr_bucket_pool_create(str, strlen(str)+1,
f->r->pool, f->r->connection->bucket_alloc);
现在你有了你的水桶,你可以APR_BRIGADE_INSERT_TAIL()
。
但是:你还有另外一个问题。无法保证您的过滤器功能仅针对请求调用一次。可以多次调用它,每次只需要请求的一大块输出。您需要保持状态,以便在同一请求中被叫第二次(或更多)时间。
为此目的提供了f->ctx
指针。你可以把任何你想要的东西放进去。
typedef struct {
int c;
// anything you want to preserve from one call to the next
} filter_ctx;
在过滤器功能中:
filter_ctx *ctx = f->ctx;
if (ctx == NULL) {
ctx = f->ctx = apr_palloc(f->r->pool, sizeof(filter_ctx));
ctx->c = 1;
} else {
ctx->c += 1;
}
现在你有一个计数器告诉你你有多少次被召唤。所以,你可以确保你只在第一次通话时做你的事情。 (显然你可以用自己喜欢的方式完成这个任务;使用计数器只是一个例子。)如果你想要安全,请检查你的传入存储桶中的EOS存储桶,并在看到它时将f->ctx
指针清空。由于您是从请求池中分配的,因此您可能不需要这样做。