> I added some debug logging to see headers_out() before and after calling > no_cache(1). no_cache(1) appears to be setting the specified headers and > internal_redirect() appears to be ignoring them.
alright, I think I see what's going on here. I'll explain technically and then try to explain the rationale I think is behind it. the reason $r->no_cache(1) isn't affecting your code is that an internal_redirect() is purposefully ignoring the headers_out table when it issues the redirect. to paraphrase the code, when you call $r->internal_redirect apache creates a _new_ request and sends that request through the standard request cycle, starting with uri translation. when the new request is created it copies various things from the current request, one of which is _not_ the headers_out table. here's the code from http_request.c in 1.3: request_rec *new; ... new->headers_in = r->headers_in; new->headers_out = ap_make_table(r->pool, 12); so, when you call $r->internal_redirect() you get the properties of the incoming request, but inherit none of the properties of current response. please note this is an apache thing, not a mod_perl thing, so it's nothing that mod_perl is doing "wrong." as with almost all that mod_perl does, the API of internal_redirect() is an apache C one that mod_perl merely passes on to you in perl. ok, now for the rationale. I can only suspect that the reason for this behavior is that the point of internal_redirect() is to act just like a full external redirect (ie returning REDIRECT with a Location header) except you're not letting the browser know about it. in other words, internal_redirect() is a transparent replacement of the current content with content from a different URI, cache headers and all. in truth, I think the behavior you're observing is the desirable one for the vast majority of cases of using an internal redirect. for example, sending the ETag header from the current request when calling internal_redirect() to another URI would probably break the rules surrounding ETag, which is supposed to be unique for each resource. but of course, none of this helps your code. hopefully it at least helps your understanding :) if you're just playing around I guess the workaround is to use a subrequest instead of internal_redirect(). for example my $sub = $r->lookup_uri($lucky); $sub->no_cache(1); $sub->run; if you really want to use internal_redirect() I have a rather complex solution that _might_ work. take this module: http://www.modperlcookbook.org/code/ch03/Cookbook-SimpleRequest-0.01.tar.gz crack it open and s/assbackwards/no_local_copy/. then from your code you would call $r->no_local_copy(1) instead of $r->no_cache(1). it's not guaranteed to work but it probably will :) of course, in mod_perl 2.0 you get access to no_local_copy() without the acrobatics. HTH --Geoff