302 Redirect from CGI script stopped working in Apache 2.4 -
i inherited maintenance of self-written cgi application without documentation , have never met original author. application stopped working in debian 8, worked in debian 7 , centos 5. main changes upgrade apache 2.2 (used debian 7 & centos 5) apache 2.4 (used debian 8) , upgrade perl 5.8 (in centos 5) respectively perl 5.14 (in debian 7) perl 5.20. problematic part boils down following script (a 302-redirect):
#!/usr/bin/perl $|=1; # activate auto-flushing of stdout use strict; use warnings; $crlf = "\015\012"; print stdout "status: 302 moved temporarily$crlf" . "location: /does_not_matter$crlf" . "uri: /does_not_matter$crlf" . "connection: close$crlf" . "content-type: text/html; charset=utf-8$crlf$crlf"; close stdout; while(1) { sleep 1; }
the observed behavior redirect never reaches client long script still running when used apache 2.4, there no error message in apache's error.log. changed client (firefox, chromium, wget), apache module (mod_cgid & mod_cgi), sent additional headers, removed close stdout
, removed $|=1
, replaced $crlf
\n
, made script fork , exit parent process (so apache no longer parent process), no avail. things worked: use apache 2.2, turn script nph-cgi-script (which has send complete http headers apache not modify in way, if contain errors), make script exit instead of entering endless loop. confirmed via tcpdump packages redirect indeed never leave server before script killed. , date-line in response , time of eventual arrival gather apache receives output (& adds date-line headers), not send response client.
don't bother answering, figured solution out myself , write answer. want make solution available others might encounter same problem.
the problem missing message body. 302 redirect may contain message body (see rfc 2616, section 4.3 (message body): "all other responses include message-body, although may of 0 length"), content-length-line optional (section 4.4 of rfc 2616 says message body length can determined closing connection if content-length-line missing). since apache can not know whether want send message body or not, has wait until close connection or send message body (apache 2.2 apparently behaved erroneously here not waiting message body - or maybe close stdout;
not in perl 5.20 did in older perl versions). correct script should therefore (verified work both in apache 2.2 , in apache 2.4) - difference additional $crlf
terminates zero-length message body:
#!/usr/bin/perl $|=1; # activate auto-flushing of stdout use strict; use warnings; $crlf = "\015\012"; print stdout "status: 302 moved temporarily$crlf" . "location: /doesnotmatter$crlf" . "uri: /doesnotmatter$crlf" . "connection: close$crlf" . "content-type: text/html; charset=utf-8$crlf$crlf$crlf"; close stdout; while(1) { sleep 1; }
it https://stackoverflow.com/a/8062277/2845840 pointed me in right direction.
Comments
Post a Comment