Hello,
I am running Flask apps with uWSGI as a middleware, communicating with
httpd via FastCGI sockets.
Ever since OpenBSD 6.1 I started running into problems with all of my
Flask apps. They would get caught in a redirect loop for root paths
(see [1]).
I did some debugging, and it seems that Flasks routing engine Werkzeug
has an option called `strict_slashes`[2], which will append a slash
and redirect to directory requests without a trailing slash.
When the root URL of an app is requested, e.g. "http://foo.bar",
PATH_INFO will be set to an empty string. This causes Werkzeug to
respond with a redirect, but the next request will still come in with
PATH_INFO as "", resulting in a redirect loop.
Attached diff causes PATH_INFO to be "/" in such a case, effectively
fixing the problem for me. However, I am not well versed with the
httpd code-base. Maybe it should be corrected with a different
approach. Just sending this in to get the ball rolling.
The CGI RFC[3] states that "/" and "" are valid paths. I would assume
that for applications mounted at root, PATH_INFO should be "/" instead
of "" when requesting the index.
[1]: https://github.com/reyk/httpd/issues/71
[2]: http://werkzeug.pocoo.org/docs/0.14/routing/#werkzeug.routing.Rule
[3]: https://tools.ietf.org/html/rfc3875#section-4.1.5
Index: httpd.c
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/httpd.c,v
retrieving revision 1.67
diff -u -p -r1.67 httpd.c
--- httpd.c 28 May 2017 10:37:26 -0000 1.67
+++ httpd.c 18 Jan 2018 07:20:58 -0000
@@ -722,8 +722,12 @@ path_info(char *path)
*p = ch;
/* Break if the initial path component was found */
- if (ret == 0)
+ if (ret == 0) {
+ /* ensure leading / if path component is a directory */
+ if (S_ISDIR(st.st_mode))
+ return (p - start - 1);
break;
+ }
}
return (p - start);