-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Quitting a Request when a Subrequest is started. #41
Comments
On Mon, Jun 6, 2011 at 9:13 PM, moodydeath
Does ngx.exec() achieve what you want? The ngx.exec() function does an internal redirection to the new Please consult the ngx_lua documentation for more details :) -agentzh |
Somehow yes, but the problem with ngx.exec is, that i have no control of the response-headers there, do i? Assuming ngx.header is implemented, that we are able to get response headers, is there the possibility to be able to customize those after ngx.exec()? Besides this, there is no way to customize the request body? ngx.location.capture can have an optional parameter for that, but ngx.exec() will take what is in ngx.var.request_body? (or do i have full access to this ngx.var? means r/w?) |
On Tue, Jun 7, 2011 at 12:30 AM, moodydeath
This should be done via output header filters. Can ngx_headers_more
No, it's irrelevant.
Well, it can be done on the C level, so we could add a "body" option I'm wondering what is the real world use case for this? Regards, |
I'm trying to create some kind of application firewall plugin for nginx on top of the lua-language... Don't worry about performance or solutions that would work better - the thing is, that in the end everything should only depend on the lua-nginx-module. And for now it should be only some kind of proof-of-concept project with the attention on reliability For now, everything is just fine, but the problem (which is the worst) is, that we can't stop the original request or better replace it with the content/headers/etc. from the subrequest. The processing would be:
I understand that this (i mean the last part) is done via output-filters... but everything would work fine as it is, if there is the possibility to stop the original plain request from being processed... As a workaround i tried to ngx.exec() to an empty location at the end of the script in my first post... But ... workaround (which i think does not solve all problems as well) :-) |
On Tue, Jun 7, 2011 at 4:19 PM, moodydeath
Are you using rewrite_by_lua or access_by_lua? If yes, you can If you're using content_by_lua, then there's no need to do such exiting anyway. Regards, |
Using rewrite_by_lua_file for this. ngx.exit(0) at the end of my testscript does not work - will end in timeouts when trying to access sites. ngx.exit(200) works (better), though some applications refuse to work 100% correct then - e.g. the ajax-stuff in the newest phpmyadmin, etc.. I can't imagine, where the fault for this behaviour is :-( |
On Tue, Jun 7, 2011 at 7:12 PM, moodydeath
Could you give me a minimized version of your test script to reproduce Thanks! |
On Tue, Jun 7, 2011 at 10:08 PM, agentzh agentzh@gmail.com wrote:
Okay...my fault...I've reproduced this issue for rewrite_by_lua* on my According to the documentation of ngx_lua, ngx.exit(0) will only quit
Use of ngx.exit() is still broken in the same way for access_by_lua* Thanks! |
On Tue, Jun 7, 2011 at 11:21 PM, agentzh agentzh@gmail.com wrote:
I've just fixed ngx.exit() for access_by_lua* in the "exit-fixes" Thanks! |
Hi, sorry for the deleay ... but i tested it and everything works fine, now! :-) I can confirm, that this code will work and output the page generated by the subrquest (ok, there are some more lines for POST-Data, etc. but generally this works) if ngx.is_subrequest == false then
res = ngx.location.capture(ngx.var.request_uri)
for i,j in pairs(res.header) do
ngx.header[i] = j
end
ngx.print(res.body)
---ngx.flush()
---ngx.eof()
ngx.exit(res.status)
end
ngx.eof() or ngx.flush() won't work here, but this is expected. Can you confirm, that - with this method - the original request will never hit nginx and only the HTTP-request for the subrequest will be performed? By the way, there's still a small problem. If a subrequest returns a 302-Error that says the page has moved there will be a location-header that contains the new url for automatic forwarding... this works fine, but with the subrequest, the location-entry will contain "localhost" as hostname in the path for the new url... :( - i think that this has something to do with the fact, that the subrequest is put there as some kind of "local" internal request? |
On Fri, Jun 10, 2011 at 9:36 PM, moodydeath
Yay! I'll merge the "exit-fixes" branch back to master when I go back
Your rewrite_by_lua_file directive always runs at the rewrite phase of
That's because your nginx virtual server is configured by the name Regards, |
Found the thing about the localhost-problem some minutes ago, too :-) ... Thanks! |
On Fri, Jun 10, 2011 at 10:06 PM, agentzh agentzh@gmail.com wrote:
I‘ve just merged the exit-fixes branch to master and tagged the Enjoy! |
Really great, thank you! :-) There are two small (?) flaws of which i don't know, if they belong to this issue or another (so i'll just post it here and don't open another one): (1): index index.html index.htm index.php; <-- this would be in the main location / for index-files When a request is set to http://domain.tld/index.php or http://domain.tld/index.htm(l) everything works correct When a request is done @ http://domain.tld/phpbb/ should be a index.php accessed it will return the correct page, but the request will last for a long time and after the normal page the response-headers will be in the output. When requesting http://domain.tld/phpbb and there should be a index.php -> a 301 error is returned This behaviour is only when the lua-script is activated, so i can exclude that the fault is in a misconfigured nginx.conf (like i had before :-) ) ... Is there something missing in my script that should handle this? if ngx.is_subrequest == false then
function set_request_method()
local val = ngx.var.request_method
if val == "GET" then
return ngx.HTTP_GET
elseif val == "HEAD" then
return ngx.HTTP_HEAD
elseif val == "PUT" then
return ngx.HTTP_PUT
elseif val == "POST" then
return ngx.HTTP_POST
elseif val == "DELETE" then
return ngx.HTTP_DELETE
end
end
res = ngx.location.capture(ngx.var.request_uri, { method = set_request_method(), body = ngx.var.request_body})
for i,j in pairs(res.header) do ngx.header[i] = j end
ngx.print(res.body)
ngx.exit(res.status)
end
The second thing is - and i have to investigate a bit more about this today and tomorrow - that with specific applications like Wordpress or phpMyAdmin the login does not work when the script is activated because they are using a 302-redirect in the login-scripts which - somehow - do not work when using my script... Debug-Messages and Tamper show that request- and response-information are actually sent in correct form... But i will have to have a closer look on it! Btw. it's no big deal, but it does not really look pretty with the wrapper for the request-methods - but is there another way for ngx.var.request_method and what ngx.location.capture needs as method? |
On Sun, Jun 12, 2011 at 7:27 PM, moodydeath
For now, ngx.location.capture cannot work with locations with internal It can be fixed by modifying ngx_lua's output filter to inspect the
Yeah, the ngx_lua ctx is cleared so the state machine does not I hope I can find some time to fix this these days. I've been
Good luck with this one! Thanks! |
On Tue, Jun 14, 2011 at 10:51 AM, agentzh agentzh@gmail.com wrote:
I've just fixed this issue in my local working tree. I'll commit my Thanks! |
…) that we could not capture locations with internal redirections in them. thanks moodydeath for reporting it in github issue \#41.
On Wed, Jun 15, 2011 at 4:14 PM, agentzh agentzh@gmail.com wrote:
Already committed to both the devel and master branches. Could you Thanks! |
Works perfect for requests to an url that ends with a "/" like http://localhost/foo/ And i think the problem with the logins that are not working (on wordpress, phpmyadmin, etc.) the issue is in ngx.location.capture not sending the body-data at the moment. Some things that could confirm my assumption: using as rewrite_by_lua_file: if ngx.is_subrequest == false then
res = ngx.location.capture("/info.php", {method = ngx.HTTP_POST, body = "foo"})
for i,j in pairs(res.header) do ngx.header[i] = j end
ngx.print(res.body)
ngx.exit(res.status)
end
/info.php is just a small phpscript which will echo the request_body in output... When the lua-code is acitve, i get a timeout from nginx (504) at the client and the error.log contains:
Somehow the request does not hit the fast-cgi component through the subrequest when using POST and a request_body. It's working without a problem when a request_body is sent to fast-cgi without lua-code in the middle. Normal GET-requests to php-pages work without problems, too. This happens on nginx 1.0.2 and 1.0.4 with the latest lua-nginx-module from master. Thanks, moody. |
On Wed, Jun 15, 2011 at 9:33 PM, moodydeath
I cannot reproduce it on my side. Could you please submit a failing
I'll look into this. But it'll also be great if you can code up a Thanks! |
… not override the current ctx completely, as mentioned in github issue #41.
On Thu, Jun 16, 2011 at 1:08 PM, agentzh agentzh@gmail.com wrote:
I cannot reproduce it using nginx 1.0.4 + latest ngx_lua master +
ngx.HTTP_POST, body = "foo"}) and here's the content of my /tmp/test.php:
Then GET /foo gives
which is what we expected. Regards, |
Hi, i'm sorry - but i just found out, that the error with the lost body only occurs on my virtual machine where i was developing the last few days (Ubuntu 10.04 with php-fpm running from ppa) I just did a clean install of nginx 1.0.4 with the latest ngx_dev_kit and lua-module on my own ArchLinux system (using latests php, too) and everything worked fine. So, the issue is on my side (some misconfiguration or so ... sorry again :( ) The other thing with locations not ending with a / is existing on this system, too. The error occurs, when there is a subfolder in the main html-directory of the location. When i point to http://domain.tld/foo/index.php or http://domain.tld/foo/ everything works correct. Only when using http://domain.tld/foo nginx returns a 301-error. It will fail with this code on my machines: if ngx.is_subrequest == false then
res = ngx.location.capture(ngx.var.request_uri)
ngx.log(ngx.ERR, "SUBR. URI: " .. ngx.var.request_uri .. " | RES.STATUS: " .. res.status .. " | RES.BODY: " .. res.body)
for i,j in pairs(res.header) do ngx.header[i] = j end
ngx.print(res.body)
ngx.exit(res.status)
end
The log-output here is this after 2 requests on foo/ and only foo
Thanks, moody |
On Thu, Jun 16, 2011 at 3:44 PM, moodydeath
Nice to hear that it does not exist :D
I'll look into this one soon :) Thanks! |
On Thu, Jun 16, 2011 at 3:44 PM, moodydeath
I think this behavior is expected. A 301 redirect is sent to rewrite Cheers, |
You're right, the original request without any lua-code interfering returns a 301 with a Location-header to the one with the / in the ending... But when it's done through the lua-code, there is the 301 - but no Location-header to be able to redirect the client. for i,j in pairs(res.header) do ngx.header[i] = j end
This works e.g. for the login in phpmyadmin pretty well. it returns a 302 with a location-header to the new one (includeing the sessionid, etc.). So the lua-code should be able to handle this with a 301 without problems, i think. With lua active the Response headers include: status, server, date, content-type, content-length, connection the location-header for the 301 is not in the header-table generated by the subrequest. res.header["Location"] is empty. Thanks, moody |
On Thu, Jun 16, 2011 at 4:15 PM, moodydeath
Okay, I think I've found the reason :) It's indeed a bug in ngx_lua. I'll fix this shortly.
BTW, please add the following line here (before the first ngx.print call):
For your those 302 error pages, ngx_lua works because it is the php
When your Lua hook is disabled, nginx replies on the standard
That's the cause of the problem. I'll fix it. Thanks for your current project! It helps spotting lots of interesting Thanks again! |
On Thu, Jun 16, 2011 at 4:32 PM, agentzh agentzh@gmail.com wrote:
I've just fixed this issue in my local working copy. I'll commit it BTW, I suggest you should use access_by_lua instead of rewrite_by_lua Thanks! |
…in ngx_http_static_module that when it issues 301 redirect for directory access w/o a trailing slash, it does not inject r->headers_out.location into the r->headers_out.headers list. thanks moodydeath for reporting it in the discussion of github issue #41.
On Thu, Jun 16, 2011 at 5:56 PM, agentzh agentzh@gmail.com wrote:
Already committed to both master and devel :) Give it shot! :D Thanks! |
Yay, working perfect! :-) Thanks for the tip with access_by... Now the issue is really "closed" ;-) moody Gree |
Hi,
the topic is a bit misleading, but here is what i mean exactly:
I can hit a subrequest via ngx.location.capture() for the uri the normal request is meant for (ngx.var.uri).
Then i have e.g. a res-variable which contains res.header, res.body and res.status.
Then i can cange the contents of the variables and e.g. write the headers back to ngx.header[] ...and output the res.body via ngx.print(res.body)
BUT how can i stop the original request from being processed at all? (flush or eof won't do this, i think?)
The baseline for the explanation would be: I want to catch a request, change it, do a subrequest with the information gathered and then output the information received by the subrequest (i don't want the original request to be executed at all!)?
Is there any way to achieve this behaviour? - My attemps when trying to force the stop of the request fail...
Here's a example code what i would like to do:
The text was updated successfully, but these errors were encountered: