View Full Version : Sendfile does not forward extra headers
aemadrid
04-29-2008, 04:01 PM
I changed my Rails app from using send_file (from Rails) to using the headers as it says in the wiki http://www.litespeedtech.com/support/wiki/doku.php?id=litespeed:wiki:feature:internal_redire ct but now all my downloads open directly in the browser instead of forcing the "Save as..." dialog. Here is my previous Rails code:
response.headers['Pragma'] = 'cache'
response.headers['Cache-Control'] = 'public, must-revalidate, max-age=0'
send_file res.full_path, :filename => res.filename, :type => res.content_type, :disposition => "attachment", :stream => true
And here are the headers I receive:
HTTP/1.x 200 OK
Date: Tue, 29 Apr 2008 22:03:43 GMT
Server: LiteSpeed
X-Runtime: 0.06450
Content-Transfer-Encoding: binary
Pragma: cache
Content-Type: application/pdf
content-disposition: attachment; filename="M1304846_Messner_Ad_FINAL.pdf"
Cache-Control: public, must-revalidate, max-age=0
Set-Cookie: infocenter2_prod=24406976884d8229ff1904a660384981; domain=infocenter.iflo.com; path=/
Content-Length: 996315
Connection: close
And here is my new code:
response.headers['Pragma'] = 'cache'
response.headers['Cache-Control'] = 'public, must-revalidate, max-age=0'
response.headers['Status'] = '200 OK'
response.headers['Content-Disposition'] = "attachment; filename=" + res.filename
response.headers['Content-Type'] = res.content_type
response.headers['Location'] = res.web_path
response.headers['X-LiteSpeed-Location'] = res.web_path
render :nothing => true
And here is the headers I receive:
HTTP/1.x 200 OK
Date: Tue, 29 Apr 2008 21:53:03 GMT
Server: LiteSpeed
Last-Modified: Fri, 20 Oct 2006 12:15:22 GMT
Content-Type: application/pdf
Content-Length: 996315
Connection: close
My guess is that LS does not forward the extra headers like 'Content-Disposition' or 'Cache-Control'. Is there any way to force it do forward those headers or is there any other way to force the opening of the dialog instead of opening on the browser and still use the LS acceleration?
Thanks in advance,
Adrian Madrid
mistwang
04-29-2008, 04:32 PM
LiteSpeed should forward "Content-Disposition", but not "Cache-Control".
You can Use Apache directive "AppendHeader" to add the control control header you want.
You do not need to set "Location" header when "X-LiteSpeed-Location" is set.
For "Content-disposition" header, you really need to check the response header produced by rails.
aemadrid
04-29-2008, 05:12 PM
This is a log I added to see which headers where in the response _after_ rendering nothing.
Apr 29 16:53:04 server2 rails[28807]: XyzController : download :: LS : headers : {"Status"=>"200 OK", "X-LiteSpeed-Location"=>"/con_tent/000810_M1304846_Messner_Ad_FINAL.pdf", "Location"=>"/con_tent/000810_M1304846_Messner_Ad_FINAL.pdf", "cookie"=>[], "Pragma"=>"cache", "Content-Type"=>"application/pdf", "Content-Disposition"=>"attachment; filename=M1304846_Messner_Ad_FINAL.pdf", "Cache-Control"=>"public, must-revalidate, max-age=0"}
After looking at the source of Rails I'm pretty sure that Rails is sending all headers but I would like to test that. How can I test which headers Rails is actually sending? My setup is several Thin servers and LS with one load balancer and multiple proxies for those thin servers. Is there a way to log those requests between each Thin server and LS?
Thanks in advance,
Adrian Madrid
mistwang
04-29-2008, 05:15 PM
If you can hit those thin servers directly, try
lynx -mime_header http://thin_server_addr/...
aemadrid
04-29-2008, 05:19 PM
I was hoping for a log file because I use send_file since I need authentication/sessions and all that. I'll add a temporary unrestricted action and report back.
AEM
mistwang
04-29-2008, 05:21 PM
You can use FireFox + FireBug add-on as well.
aemadrid
04-29-2008, 05:22 PM
Should have thought of that too. The thin servers are bahind the firewall though but it might be easier to open temporarily a port.
AEM
aemadrid
04-30-2008, 02:38 PM
This Rails code:
response.headers['Pragma'] = 'cache'
response.headers['Cache-Control'] = 'public, must-revalidate, max-age=0'
response.headers['Status'] = '200 OK'
response.headers['Content-Disposition'] = "attachment; filename=" + res.filename
response.headers['Content-Type'] = res.content_type
response.headers['Location'] = res.web_path
response.headers['X-LiteSpeed-Location'] = res.web_path
render :nothing => true
Generates this headers directly from Thin:
HTTP/1.1 200 OK
X-Litespeed-Location: /con_tent/000748_1302863f.pdf
Etag: "7215ee9c7d9dc229d2921a40e899ec5f"
X-Runtime: 0.00131
Location: /xyz/000748_1302863f.pdf
Pragma: cache
Content-Type: application/pdf; charset=utf-8
Content-Disposition: attachment; filename=1302863f.pdf
Cache-Control: public, must-revalidate, max-age=0
Content-Length: 1
Set-Cookie: xyz_prod=b7fc71c50c694b8e26e5ec35032ed1fe; domain=xyz.com; path=/
Connection: keep-alive
Server: thin 0.8.1 codename Rebel Porpoise
Generates this headers from LSWS proxying Thin:
HTTP/1.1 200 OK
Content-Type: text/html
Set-Cookie: _session_id=27071a726f9a056309bf4ffa7c19f7a5; path=/
Cache-Control: no-cache
Transfer-Encoding: chunked
Date: Wed, 30 Apr 2008 20:22:07 GMT
Server: LiteSpeed
Connection: Keep-Alive
Keep-Alive: timeout=5, max=100
And just for fun, this Rails code:
head :ok, :content_disposition => "attachment; filename=" + res.filename,
:content_type => res.content_type,
:location => res.web_path,
:pragma => 'cache',
:cache_control => 'public, must-revalidate, max-age=0'
Generates this Thin headers:
HTTP/1.1 200 OK
Etag: "7215ee9c7d9dc229d2921a40e899ec5f"
X-Runtime: 0.00128
Location: /xyz/000748_1302863f.pdf
Pragma: cache
Content-Type: application/pdf; charset=utf-8
Content-Disposition: attachment; filename=1302863f.pdf
Cache-Control: public, must-revalidate, max-age=0
Content-Length: 1
Set-Cookie: xyz_prod=53819e7598f8964c9bc375b3af715c0a; domain=xyz.com; path=/
Connection: keep-alive
Server: thin 0.8.1 codename Rebel Porpoise
And this LS headers after proxying Thin:
HTTP/1.1 200 OK
Content-Type: text/html
Set-Cookie: _session_id=4ecd8d12dd1cebe4d4b549f547936331; path=/
Cache-Control: no-cache
Transfer-Encoding: chunked
Date: Wed, 30 Apr 2008 20:22:08 GMT
Server: LiteSpeed
Connection: Keep-Alive
Keep-Alive: timeout=5, max=100
Conclusion: Litespeed is not forwarding two specific headers, Content-Type and Content-Disposition when using Location to accelerate sending files.
Anyting else I should test or can we assume that the conclusion stands?
mistwang
04-30-2008, 03:02 PM
which version of LSWS are you using?
LSWS will forward Content-Disposition, but not the others. You should only use "X-Litespeed-Location" and get rid of "Location".
LSWS serve the internal redirected request as a fresh request, those headers are not inherited, especially for static files. However, those header can be added as extra response headers.
Content-Type follows the server MIME configuration. You need to set ".pdf" with MIME type "application/pdf", instead of "text/html".
aemadrid
04-30-2008, 03:14 PM
which version of LSWS are you using?
LSWS will forward Content-Disposition, but not the others. You should only use "X-Litespeed-Location" and get rid of "Location".
LSWS serve the internal redirected request as a fresh request, those headers are not inherited, especially for static files. However, those header can be added as extra response headers.
I'm running Litespeed Web Server Standard v3.3.11 on Linux.
Linux xyz.com 2.6.9-42.0.10.EL #1 Fri Feb 16 17:06:10 EST 2007 i686 i686 i386 GNU/Linux
In my second example I am only sending Location and LS doesn't seem to be sending the Content-Disposition header at all.
Content-Type follows the server MIME configuration. You need to set ".pdf" with MIME type "application/pdf", instead of "text/html".
Where can I add the mime types information?
Thanks in advance,
Adrian Madrid
mistwang
04-30-2008, 05:03 PM
http://www.litespeedtech.com/docs/webserver/config/context/#addMIMEType
aemadrid
04-30-2008, 09:10 PM
Any chance of getting the Content-Disposition header bug considered?