httpd-modules-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Sorin Manolache <sor...@gmail.com>
Subject Re: Calling another URL from output filter
Date Fri, 16 Mar 2012 09:53:31 GMT
On 2012-03-16 02:57, Swaminathan Bhaskar wrote:
> Hi Sorin
>
> Can you share your code for this cae so that I can take a look to get an
> understanding. Can I call a uri on a different server before the proxy
> to the requested server ?
>


My conf on pqr.mydomain.com looks something like

<Location /my_url>
   RewriteEngine On
   RewriteRule .*  http://xyz.mydomain.com/fetchdata [P]
</Location>

<Proxy http://xyz.mydomain.com/fetchdata>
# access control directives (Order, Allow, Deny, etc)
    ProxyPass http://xyz.mydomain.com/fetchdata keepalive=On
</Proxy>

<Proxy http://abc.mydomain.com/signon>
# access control directives (Order, Allow, Deny, etc)
# RequestHeader directives to block/enable/edit the
# request headers to the signon server
    ProxyPass http://abc.mydomain.com/signon keepalive=On
</Proxy>

RewriteCond %{IS_SUBREQ} true
RewriteRule /internal_signon http://abc.mydomain.com/signon [P]


So the client accesses http://pqr.mydomain.com/my_url. My module makes a 
subrequest to /internal_signon. The rewrite rule redirects to 
http://abc.mydomain.com/signon. My module consumes the response of 
http://abc.mydomain.com/signon without producing any output. Then my 
handler returns DECLINED. Because it declines, the proxy module takes 
over and makes the request to http://xyz.mydomain.com/fetchdata.

The request to /internal_signon is made in a fixups hook. My fixups hook 
has to execute before mod_rewrite's fixup hook. So I register it as follows:

static const char * const fixups_succ[] = {"mod_rewrite.c", 
"mod_headers.c", NULL};
ap_hook_fixups(&fixups, NULL, fixups_succ, APR_HOOK_MIDDLE);

My fixups callback does something like this:

int fixups(request_rec *r) {
   if (!ap_is_initial_req(r))
      return DECLINED;
   // other conditions to see if we should handle it
   Data data;
   make_request("/internal_signon", r, &data);
   // use the data.
   return OK;
}

void make_request(const char *url, request_rec *r, Data *data) {
   request_rec *newreq = ap_sub_req_lookup_uri(url, r, NULL);
   if (NULL == newreq)
     ; // err_handler

   ap_set_module_config(newreq->request_config, &mymodule, data);

   ap_filter_t *flt = ap_add_output_filter("subreqflt", 0, newreq, 
newreq->connection);
   if (NULL == flt) {
     ap_destroy_sub_req(newreq);
     // err_handler;
   }

   int proxy_ret_code = ap_run_sub_req(newreq);
   int ret_code = newreq->status;

   ap_destroy_sub_req(newreq);

   if (ap_is_HTTP_ERROR(proxy_ret_code) || ap_is_HTTP_ERROR(ret_code)) {
     // err_handler
   }
}


The filter "subreqflt" gets the data object

Data *data = (Data *)ap_get_module_config(flt->r->request_config, 
&mymodule);

It parses the response, extracts from it the relevant data and puts them 
in the "data" object.

The subrequest response parsing is a "normal" filter. The only 
difference is that it does never "return ap_pass_brigade(flt->next, 
bb)". It always does "return APR_SUCCESS". Thus, downstream filters, 
like the one that sends the response to the client, are not called. The 
filter acts like a sink for the subrequest data.


Sorin


> Rgds
> Bhaskar
>
> On 03/05/2012 04:26 AM, Sorin Manolache wrote:
>> On 2012-03-04 19:19, Swaminathan Bhaskar wrote:
>>>
>>> Hello,
>>>
>>> How can I call another url from an output filter - here is the scenario:
>>> when a client accesses abc.mydomain.com/signon, this url autheticates
>>> the
>>> user and we dont want the response going back to the client rather call
>>> another url xyz.mydomain.com/fetchdata which will return some data
>>> ... we
>>> want to send the data from the second url and response headers from
>>> first
>>> url merged back to the client. So my thought is to intercept the
>>> response
>>> from the first url in an output ffilter and make a call from the output
>>> filter to the second url. What function call would allow me to make
>>> th call
>>> to the second url Any help appreciated
>>
>>
>> Hello,
>>
>> We did something similar but we didn't issue the 2nd request from the
>> output filter of the first.
>>
>> The first request was made by the apache subrequest API (the
>> ap_sub_req_lookup_uri and ap_run_sub_req functions). The output filter
>> ran until it encountered an end-of-stream. It did not make any other
>> request. The output filter of the subrequest did not pass any brigade
>> to downstream filters. It simply parsed the response, stored relevant
>> data in some structure and returned APR_SUCCESS to its upstream filters.
>>
>> Next, after ap_run_sub_req returned, we invoked the 2nd URL via the
>> proxy module. The useful data returned by the 1st URL was taken from
>> the structure in which the subrequest stored it.
>>
>> Calling a 2nd URL from output filters is a bit tricky, as you have
>> filter-chains invoked from within a filter-chain, so we preferred to
>> call the 2nd URL only after the request to the first completed.
>>
>> Regards,
>> Sorin
>>
>


Mime
View raw message