Project

General

Profile

Feature #2702

REDIRECT_URI not set in mod_cgi

Added by stbuehler over 1 year ago. Updated over 1 year ago.

Status:
Fixed
Priority:
Normal
Assignee:
-
Category:
mod_cgi
Target version:
Start date:
2015-12-18
Due date:
% Done:

100%

Estimated time:
Missing in 1.5.x:

Associated revisions

Revision dbdab5db (diff)
Added by gstrauss over 1 year ago

[core] server.error-handler new directive for error pages (fixes #2702)

server.error-handler preserves HTTP status error code when error page
is static, and allows dynamic handlers to change HTTP status code
when error page is provided by dynamic handler. server.error-handler
intercepts all HTTP status codes >= 400 except when the content is
generated by a dynamic handler (cgi, ssi, fastcgi, scgi, proxy, lua).
The request method is unconditionally changed to GET for the request
to service the error handler, and the original request method is
later restored (for logging purposes). request body from the
original request, if present, is discarded.

server.error-handler is somewhat similar to server.error-handler-404,
but server.error-handler-404 is now deprecated, intercepts only 404
and 403 HTTP status codes, and returns 200 OK for static error pages,
a source of confusion for some admins. On the other hand, the new
server.error-handler, when set, will intercept all HTTP status error
codes >= 400. server.error-handler takes precedence over
server.error-handler-404 when both are set.

NOTE: a major difference between server.error-handler and the
now-deprecated server.error-handler-404 is that the values of the
non-standard CGI environment variables REQUEST_URI and REDIRECT_URI
have been swapped. Since REDIRECT_STATUS is the original HTTP
status code, REDIRECT_URI is now the original request, and REQUEST_URI
is the current request (e.g. the URI/URL to the error handler).
The prior behavior -- which reversed REQUEST_URI and REDIRECT_URI values
from those described above -- is preserved for server.error-handler-404.

Additionally, REDIRECT_STATUS is now available to mod_magnet, which
continues to have access to request.uri and request.orig_uri.

See further discussion at https://redmine.lighttpd.net/issues/2702
and https://redmine.lighttpd.net/issues/1828

github: closes #36

History

#1 Updated by stbuehler over 1 year ago

  • Target version changed from 1.4.39 to 1.4.40

#2 Updated by gstrauss over 1 year ago

REDIRECT_URI is not part of the CGI specification. Please change this ticket to Feature request, and not Bug.

Please also provide more information about REDIRECT_URI and why and when you expect it, e.g. it is provided in mod_fastcgi and mod_scgi.

#3 Updated by gstrauss over 1 year ago

Is this ticket potentially related to https://redmine.lighttpd.net/issues/1828 ("REDIRECT_STATUS == 200 on 404 redirect")?

Should whatever change is made to mod_cgi also be made in mod_ssi, which is also missing REDIRECT_URI?

#4 Updated by gstrauss over 1 year ago

diff --git a/src/mod_cgi.c b/src/mod_cgi.c
index bfbfa13..b8b2dec 100644
--- a/src/mod_cgi.c
+++ b/src/mod_cgi.c
@@ -968,6 +968,9 @@ static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer *
                if (!buffer_string_is_empty(con->request.orig_uri)) {
                        cgi_env_add(&env, CONST_STR_LEN("REQUEST_URI"), CONST_BUF_LEN(con->request.orig_uri));
                }
+               if (!buffer_is_equal(con->request.uri, con->request.orig_uri)) {
+                       cgi_env_add(&env, CONST_STR_LEN("REDIRECT_URI"), CONST_BUF_LEN(con->request.uri));
+               }

                switch (con->dst_addr.plain.sa_family) {

#5 Updated by gstrauss over 1 year ago

Please bear with me as I contemplate differences between REQUEST_URI and REDIRECT_URI, and REDIRECT_URL, none of which are standard CGI variables, and then propose a breaking change (with limited impact) to REQUEST_URI and REDIRECT_URI in mod_fastcgi and mod_scgi.

https://httpd.apache.org/docs/current/custom-error.html
Apache provides REDIRECT_* variables. In Apache, these all refer back to the original request. This includes REDIRECT_URL and REDIRECT_QUERY_STRING. REDIRECT_URL and REDIRECT_QUERY_STRING could be used to reconstruct the original request.

lighttpd provides the original URI in REQUEST_URI, which could be parsed by the receiving script into REDIRECT_URL, REDIRECT_QUERY_STRING, etc for compatibility with scripts written for Apache.

lighttpd REQUEST_URI would be better named REDIRECT_URI to match the convention of REDIRECT_* being info about the original request. However, lighttpd sets REDIRECT_URI to the URI of the error handler, and this in turn would be better named REQUEST_URI for the current request. This lighttpd definition of REDIRECT_URI is somewhat redundant since it can typically be constructed from standard CGI variables SCRIPT_NAME + QUERY_STRING. (I still prefer REDIRECT_URI rather than reconstructing, but think REDIRECT_URI should be named REQUEST_URI.)

For most CGI, fastcgi, scgi, SSI requests in lighttpd, con->request.orig_uri matches con->request.uri, and so REDIRECT_URI does not get set, as it would duplicate REQUEST_URI. The difference comes up when server.error-handler-404 is set, which intercepts only 403 and 404 HTTP status responses which do not originate from dynamic handlers (mod_cgi, mod_fastcgi, mod_proxy, mod_scgi)

The FAQ (https://redmine.lighttpd.net/projects/lighttpd/wiki/FrequentlyAskedQuestions) and other tickets discussing server.error-handler-404 indicate that server.error-handler-404 is intended for intercepting what would be 403 and 404 responses to the client and providing the results of an alternate request with its own HTTP status response, potentially different from 404. This is in contrast to server.errorfile-prefix, which provides a 404 error page with a 404 response and can handle other error HTTP status codes, too. There are limitations in both server.error-handler-404 and server.errorfile-prefix. server.errorfile-prefix provides only for static pages for error HTTP status codes, not dynamic error pages. server.error-handler-404 allows dynamic handlers, but intercepts only 403 and 404 HTTP status codes. Some people requiring dynamic content for 404 error pages have thus used server.error-handler-404. Other people are surprised that server.error-handler-404 returns 200 OK when the error handler is a static page to handle the 404, e.g. see https://redmine.lighttpd.net/issues/2456 and the FAQ (https://redmine.lighttpd.net/projects/lighttpd/wiki/FrequentlyAskedQuestions).

Now, given the intended use of server.error-handler-404, and the definition of PHP $_SERVER['REQUEST_URI'] at http://php.net/manual/en/reserved.variables.server.php

'REQUEST_URI'
    The URI which was given in order to access this page; for instance, '/index.html'.

it would make sense for the URI to the error handler target to be in REQUEST_URI instead of the original URI whose response was intercepted by server.error-handler-404. This is currently not the case for mod_fastcgi and mod_scgi. Also, REDIRECT_URI is not currently set for mod_cgi or mod_ssi, so we have some inconsistency between the modules. Before extending REDIRECT_URI to mod_cgi and mod_ssi, perhaps we can consider making a potentially breaking change to REQUEST_URI and REDIRECT_URI? The impact is specifically limited to those using server.error-handler-404 to intercept 403 and 404 HTTP status codes and handle them with fastcgi or scgi. Further, those scripts would have to also rely on REQUEST_URI or REDIRECT_URI. (I am not sure, but this might also affect mod_cml_lua if it uses REQUEST_URI in error handler, though unlikely since it always gets con->request.orig_uri)

Once REDIRECT_STATUS is properly updated (patch in https://github.com/lighttpd/lighttpd1.4/pull/35) any of cgi, fastcgi, scgi, and ssi can detect they are being called from an error handler by checking REDIRECT_STATUS >= 400. For those interested in the original URI, we could provide that in REDIRECT_URI instead of REQUEST_URI.

I propose that REQUEST_URI be set to con->request.uri and, when con->response.in_error_handler is set, that REDIRECT_URI be set to con->request.orig_uri.

(If you look at https://github.com/lighttpd/lighttpd1.4/pull/35, it is obvious that REDIRECT_URI could be set in con->environment in the same place that REDIRECT_STATUS is set in that patch.)

#6 Updated by gstrauss over 1 year ago

Submitted pull request https://github.com/lighttpd/lighttpd1.4/pull/36 with new directive server.error-handler and I implemented the new behavior above for the new directive. I preserved the prior behavior (which I think is backwards) for server.error-handler-404. (It bears repeating that the behavior in question occurs in 403 or 404 responses where error page content is not already provided by dynamic handlers, and so the 403 or 404 response is intercepted by server.error-handler-404, where con->request.uri is made different from con-request.orig_uri.)

The patch sets REDIRECT_STATUS and REDIRECT_URI in con->environment, making it available to all of lua magnet, CGI, SSI, FastCGI, SCGI.

[Edit] ...mod_magnet and mod_rewrite might also modify con->request.uri, so I'll add a patch that has them set REDIRECT_URI, too.

#7 Updated by gstrauss over 1 year ago

  • Tracker changed from Bug to Feature

#8 Updated by gstrauss over 1 year ago

  • Status changed from New to Patch Pending

#9 Updated by gstrauss over 1 year ago

  • Status changed from Patch Pending to Fixed
  • % Done changed from 0 to 100

Also available in: Atom