nmaier / mod_xsendfile

Apache2 module that processes X-SENDFILE headers to serve static files from dynamic handlers efficiently
https://tn123.org/mod_xsendfile/
Apache License 2.0
186 stars 38 forks source link

Not working using mod_rewrite links #12

Open ghost opened 12 years ago

ghost commented 12 years ago

Hello,

I am having issues running XSendFile on Apache when using mod_rewrite to have custom download links.

For example download works when url is like http://www.site.com/dl1.php?x=parameters but doesn't work when having http://www.site.com/download/parameters/ and that is processed using mod_rewrite to

RewriteRule ^download/(.*)/$ download.php?x=$1 [QSA,L]

In my httpd.conf I have line "XSendFile On" and Apache was restarted... I have also added that in .htaccess too but no success...

Can someone help me out on this one?

Best Regrards, Tim

Azuka commented 12 years ago

I have this issue as well. Is there any way to get either this or subdirectories of allowed file paths working?

ghost commented 12 years ago

I haven't find way around...

tenfef commented 12 years ago

I gave in and just redirected http://www.site.com/download/parameters/ to http://www.site.com/dl1.php?x=parameters in htaccess It's a little inelegant but its fine for my requirements.

Tobion commented 11 years ago

I also had quite some issues when trying to send a file using xsendfile when mod_rewrite is active. So when the file in question is located under a directory where mod_rewrite is active then there seems to be a conflict and the file path cannot be resolved, thus resulting in an error. This also happens when the path is excluded from mod_rewrite so when the send file path should not even be rewritten. The only solution seems to be to make sure that the files are not stored under a mod_rewrite enabled directory. So when mod_rewrite is active for /project/web/ then don't store the files there but one hierarchy above in /project/files/ for example. This is a better project structure anyway as the files are not located in a web accessible dir.

Johnson145 commented 10 years ago

I also have this problem, too. Sadly the above workaround is not a solution for me.

I also have found out, that it is working by adding a absolute path the XSendFilePath config, but not by using the standard config and trying to access a file in the working directory.

I just can't find a solution. Would you be so kind, to have a look at my post at http://stackoverflow.com/questions/20705731/mod-xsendfile-wont-work-with-cgi-and-mod-rewrite ?

In addition to that I might have found out somehting more about another problem/bug with php in cgi mode.

nmaier commented 10 years ago

mod_xsendfile does construct absolute paths from relative paths based on the request URI, which might in fact be a sub-request in some cases. This does not always produce the results you expect.

_Therefore, I would always use absolute URIs in the X-SENDFILE header._

The second consequence of the above is that the constructed path, not necessarily being what you expect, auto-whitelist a directory you do not expect, while then of course not whitelisting the directory you would have expected.

_Therefore, always white-list URIs._

In short, Apache might not consider the same directory to be the current working directory of a request as you (or a backend *CGI). Rewriting only adds to the confusion.

I actually considered dropping the relative paths/auto-whitelist stuff altogether for this reasons, because it can be admittedly very confusing, and is also under-documented. I guess it is a little late to drop it entirely, but I should at least mark it deprecated.

Johnson145 commented 10 years ago

Thanks for the fast reply.

At the moment I am using absolute links in the xsendfile header, but its still not working with mod_rewrite. I can't add all separated paths to the whitelist as there are too many single projects and I have only the possibility to ask my provider to add them. So I would have to so this each time I start a new project.

The only other solution I can think about is to whitelist the root path of everything. But in this case I really would give access to every file on my server. This is not the best practice and also I'm not sure if my provider would allow this at all.

Is there any way to get xsendfile working in this case? Maybe a possibility to override the request path information via PHP or anything else before calling the xsendfile header? Or do I maybe have to use another path than obvious to get it work?

Would it be helpful if every mod_rewrite request looks exactly the same except one parameter?

nmaier commented 10 years ago

Store the files you want to serve with x-sendfile in a root that is OK to be served...

I don't know of any way to patch up mod_xsendfile to work better with relative paths without making it non-generic. You may try to patch something together that works better for you, of course.

Another idea might be to allow whitelisting of paths containing wildcards...

Johnson145 commented 10 years ago

Wildcards sounds interesting. By calling it an idea: Do you mean it would be an idea to integrate such a feature in xsendfile or is your module already able to handle paths containing wildcards?

In my case all files I want to serve are always in a folder (e.g.) called domain.com/download. There are very many domains, but all using the same structure, so a possibility to add all these public folders to the whitelist without having to add everything else would be really great.

Johnson145 commented 10 years ago

I guess no answer means that it's not possible right now?

jeffteeters commented 10 years ago

A suggested modification: Allow XSendFilePath to be specified in .htaccess. I think this would be very helpful for those of us who do not have access to the Apache configuration file. Otherwise we can't whitelist anything and have to rely on only using the working directory which seems to be difficult to determine if mod_rewrite is used.

raminasri commented 10 years ago

Hello, In your HT access file of main website try to use [L,R=301] in place of just [QSA,L] or [L]

For instance in place to use: RewriteRule ^download/(.*)/$ download.php?x=$1 [QSA,L]

Use: RewriteRule ^download/(.*)/$ download.php?x=$1 [L,R=301]

Tell me if resolved your problem guys !

mfprysl commented 3 years ago

@raminasri this solved the problem! It is funny to answer after 7 years, but this was an important issue for me today and your answer solved the problem. Cheers!