试图通过模块强制在apache中自定义输出

时间:2015-11-22 03:14:45

标签: c apache filter module segmentation-fault

我正在尝试创建一个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时都会执行此代码,并且在上面的代码中,我收到了分段错误。

1 个答案:

答案 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指针清空。由于您是从请求池中分配的,因此您可能不需要这样做。