简体   繁体   English

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

[英]Trying to force custom output in apache via module

I'm trying to create an apache filter that eventually creates a custom output based on the incoming status code. 我正在尝试创建一个Apache过滤器,该过滤器最终根据传入的状态码创建自定义输出。

I can easily retrieve the status code in the below function after everything in relation to the request is processed using the result from f->r->status . 使用f->r->status的结果处理与请求相关的所有内容后,可以轻松地在下面的函数中检索状态代码。

I want to be able to do it without looping through existing data to change it which is what all other filters do. 我希望能够做到这一点而无需循环访问现有数据来更改它,这是所有其他过滤器所做的。 What I want to do is ditch the existing data and replace it with my own. 我想要做的是抛弃现有数据,并用我自己的数据替换。

In the code below, I'm trying to achieve the following HTTP header: 在下面的代码中,我正在尝试实现以下HTTP标头:

HTTP/1.1 777 Lucky

And I'm trying to achieve this data: 我正在尝试获得以下数据:

Testing

Instead, the apache log reports a segmentation fault. 而是,apache日志报告分段错误。

Is there a way to replace the output or will I have to loop through the input and blank each segment out and replace one segment with my own data? 有没有一种方法可以替换输出,还是我必须遍历输入并清空每个段,然后用自己的数据替换一个段?

    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);
    }

PS: The filter has been activated and registered so this code does get executed every time I request a URL and somewhere in the above code, I receive a segmentation fault. PS:筛选器已激活并注册,因此每次我请求URL时,此代码确实会执行,并且在上述代码中的某处,我收到分段错误。

You're doing apr_bucket_alloc() and then treating the result of that function as a char * and trying to strcpy() something into it. 您正在做apr_bucket_alloc() ,然后将该函数的结果视为char *然后尝试将strcpy()放入其中。 That's not right. 那是不对的。 apr_bucket_alloc() doesn't create a char * . apr_bucket_alloc()不创建char * It's also not the right way to create a bucket. 这也不是创建存储桶的正确方法。

What you want is apr_bucket_pool_create() . 您想要的是apr_bucket_pool_create() (It's in apr_buckets.h , with enough documentation to figure out how to call it.) (它位于apr_buckets.h ,具有足够的文档来找出如何调用它。)

If we assume you have your string like so: 如果我们假设您有这样的字符串:

char *str = "HTTP/1.1 777 Lucky\r\n\r\nTesting";

Then you can do this: 然后,您可以执行以下操作:

apr_bucket *b = apr_bucket_pool_create(str, strlen(str)+1,
    f->r->pool, f->r->connection->bucket_alloc);

Now you have your bucket and you can APR_BRIGADE_INSERT_TAIL() . 现在您有了存储桶,可以使用APR_BRIGADE_INSERT_TAIL()

But: you have another problem. 但是:您还有另一个问题。 There is no guarantee that your filter function will be called only once for a request. 不能保证您的过滤器函数对于一个请求仅被调用一次。 It may be called several times, each time with just a chunk of the output from the request. 可能会多次调用它,每次都只是请求中的一部分输出。 You need to keep state so you know if you're being called a second (or more) time on the same request. 您需要保持状态,以便知道是否在同一请求上被称为第二次(或更多次)。

The f->ctx pointer is provided for this purpose. 为此提供了f->ctx指针。 You can put anything you want in it. 您可以在其中放入任何想要的东西。

typedef struct {
    int c;
    // anything you want to preserve from one call to the next
} filter_ctx;

Within your filter function: 在您的过滤功能内:

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;
}

Now you have a counter telling you how many times you've been called. 现在,您有一个柜台告诉您被叫过多少次。 So, you can make sure you only do your thing on the first call. 因此,您可以确保只在第一次通话时做自己的事情。 (Obviously you can accomplish this any way you like; using a counter is just an example.) If you want to be safe, check your incoming buckets for an EOS bucket and NULL out your f->ctx pointer when you see one. (显然,您可以按照自己喜欢的任何方式完成此操作;使用计数器只是一个示例。)如果您想安全起见,请检查传入的存储桶中是否有EOS存储桶,并在看到f->ctx指针时将其NULL f->ctx Since you're allocating from the request pool, you probably don't need to do that. 由于您是从请求池中分配的,因此您可能不需要这样做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM