Sendfile does not forward extra headers

aemadrid

Well-Known Member
#1
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_redirect but now all my downloads open directly in the browser instead of forcing the "Save as..." dialog. Here is my previous Rails code:

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:

Code:
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:

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:

Code:
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
 
Last edited:

mistwang

LiteSpeed Staff
#2
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

Well-Known Member
#3
This is a log I added to see which headers where in the response _after_ rendering nothing.

Code:
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
 

aemadrid

Well-Known Member
#5
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
 

aemadrid

Well-Known Member
#7
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

Well-Known Member
#8
Investigation Results

This Rails code:

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:

Code:
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:

Code:
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:

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:

Code:
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:

Code:
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

LiteSpeed Staff
#9
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

Well-Known Member
#10
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.

Code:
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
 
Top