NGINX perl module to server files

Hello,

I have created perl NGINX module to server static files on the NGINX
(mainly images). For security reasons I am generating the AES:CBC
encrypted
url which I am decrypting on the NGINX and serving the file via NGINX
perl
module. The problem is that I am sometimes getting the bellow response
with
HTTP response code set to 000:

XX.XX.XX.XX - - [01/Sep/2013:01:20:37 +0400] “GET
/media/u5OU/NRkImrrwH/TThHe7hns5bOEv+Aou2/VJ8YD/ts= HTTP/1.1” 000
39078 "
http://XXXX/full/JcbyEJTb8nMh+YH0xSg1jgl4N7vWQi2xBPep7VcJmD8=http://gruppu.com/full/JcbyEJTb8nMh+YH0xSg1jgl4N7vWQi2xBPep7VcJmD8="
“Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:23.0) Gecko/20100101
Firefox/23.0”

The way how I handle the url in the perl module is :

In case the file is found:
$r->sendfile($fileresult[0]);
$r->flush();
return OK;

else:
$r->status(404);
return DECLINED;

My question is if I am sending the files correctly or is there any other
specific value i should send back from perl (besides returning OK).

If needed I can send the nginx.conf.

Thanks for your help.

Regards,

Jorge

Hello list,

here is the strace of the NGINX serving my media file (Jpg) to the
client:

Accepting the connection:

25003 accept4(6, {sa_family=AF_INET, sin_port=htons(53907),
sin_addr=inet_addr(“XXX.XXX.XXX.XX”)}, [16], SOCK_NONBLOCK) = 3

Opening the file:
25003 open("/usr/site/gruppe/media/t_pics/images/thumbs/714.jpg",
O_RDONLY|O_NONBLOCK|O_LARGEFILE) = 15
25003 fstat64(15, {st_mode=S_IFREG|0755, st_size=5420, …}) = 0

Sending the file to the client with sendfile:
25003 sendfile64(3, 15, [0], 5420) = 5420

So from above it turns out that there were no headers sent and thus the
status code probably defaulted to “000” on NGINX.

Adding the send_http_header before the $r->sendfile() solves the issue.
$r->send_http_header();

Now I have the correct HTTP status code, anyway the content type
defaults
to “application/octet-stream” which is configured as default content
type
on nginx. Well, is there a way to have NGINX correctly set the
Content-Type
after handling the request on perl content handler or should I make my
own
mapping and set the content-type myself in send_http_header ?

HTTP/1.1 200 OK Server: nginx/1.5.5 Date: Sun, 01 Sep 2013 21:17:41 GMT
Content-Type: application/octet-stream Transfer-Encoding: chunked
Connection: keep-alive

Regards,

Jorge

Hello!

On Sun, Sep 01, 2013 at 04:29:46PM -0500, Jorge Sanchez wrote:

[…]

So from above it turns out that there were no headers sent and thus the
status code probably defaulted to “000” on NGINX.

Adding the send_http_header before the $r->sendfile() solves the issue.
$r->send_http_header();

Glad to see you’ve solved your problem with perl code.

BTW, there are some examples at
Module ngx_http_perl_module which may
help.

Now I have the correct HTTP status code, anyway the content type defaults
to “application/octet-stream” which is configured as default content type
on nginx. Well, is there a way to have NGINX correctly set the Content-Type
after handling the request on perl content handler or should I make my own
mapping and set the content-type myself in send_http_header ?

The Content-Type nginx set by itself is based on an extension as
seen in URI. As there is no extension in URIs you use, it uses
default type. If a default type isn’t what you want - you should
either set response type explicitly, or reconsider URIs used.

In your particular case, I would recommend you to use
$r->internal_redirect() to an internal location instead of trying
to send files yourself. (Or, alternatively, perl_set + rewrite
should also work.) It should be much easier than trying to send
files yourself from perl.

See here for more details:

http://nginx.org/en/docs/http/ngx_http_perl_module.html


Maxim D.
http://nginx.org/en/donation.html