Lost session data when setting http headers (in CodeIgniter) - php

EDIT #2
Ok, the problem is different to what I originally thought, so I'm putting this 'edit' up the top. I've also updated the question title (the old one was 'Streaming wav audio from a mysql blob').
The problem now seems to be related to CodeIgniter sessions. The above script will only run if the user is logged in. For some reason, when I manually set the response headers (either
with php's header() or codeigniters output class) I can see from my logs that everything gets reloaded and reinitilised -- and that the session data is lost, so the user is no longer logged in, so the script is actually outputting an error.
Once I removed any requirement or reference to session data the audio plays fine... but this isn't really an option unless I can manage to authenticate the user some other way. Very frustrating.
.
.
.
** Original Text **
I have a mysql blob which contains audio data in wav format. I'm trying to output that to the browser to stream in whatever audio player plugin the browser wants to use.
The audio player works fine if I point it at a physical .wav file, so that doesn't seem to be a problem. However, if I point it at my PHP script I get a 'Search for suitable plugin?' popup in Firefox (which fails to find anything), and just an empty inactive player in Chrome.
Here's the PHP, the $aud object contains information retrieved from the database:
header("Content-length: $aud->size");
header("Content-type: audio/x-wav");
echo $aud->recording;
exit();
If I add header("Content-Disposition: attachment; filename=$name"); to the above I get to download the file, which then plays fine in an external audio player, but that's not what I want.
This snippit is part of a CodeIgniter application, if that would make a difference. I have routing set up so that /audio/$id.wav will grab the appropriate data and output it with the code above.
Can anyone see or think of any reason the above might not be working?
EDIT
These are the headers returned by the php script:
Date: Tue, 22 Mar 2011 22:12:06 GMT
Server: Apache/2.2.16 (Ubuntu)
X-Powered-By: PHP/5.3.3-1ubuntu9.3
Set-Cookie: ci_session=<long encrypted session string>; expires=Wed, 23-Mar-2011 00:12:06 GMT; path=/
Content-Length: 12345
Keep-Alive: timeout=15, max=98
Connection: Keep-Alive
Content-Type: audio/x-wav
200 OK
And for comparison, these headers are returned when I force a download of the above audio and open that wav file directly in the browser:
Date: Tue, 22 Mar 2011 22:10:53 GMT
Server: Apache/2.2.16 (Ubuntu)
Last-Modified: Tue, 22 Mar 2011 22:08:30 GMT
Etag: "200a83-3039-49f197bfcb380"
Accept-Ranges: bytes
Content-Length: 12345
Content-Type: audio/x-wav
200 OK
Saving and then opening the file directly does work. Having the PHP script output to the browser does not.

I would start investigating this problem by comparing the HTTP content-length, content-type, and all the other headers sent by the web server when pointing to the physical .wav file, with the headers sent when trying to open the PHP script. I think the actual content body is correct, according to your post stating that if you download the file as an attachment, it can be played with an audio player application.

Try adding this header in there:
header('Content-Transfer-Encoding: binary');
See if that helps it out.

Related

Downloading Blobs from TrueVault with spaces in the filename

I'm using the TrueVault REST API to upload/download Blobs per the documentation at https://docs.truevault.com/Files
To download an existing Blob, I'm passing the Blob URL directly to the client's web browser (Firefox) via a PHP Header redirect. The client is able to download the Blob content from TrueVault without issue, but when using Firefox I've noticed that if the Blob being downloaded has spaces in the filename, the filename is truncated when downloading.
For instance, if I upload a Blob to TrueVault with filename 'Test File.txt', it gets downloaded to Firefox as just 'Test'. I've seen this behavior in other PHP apps and the fix has been to put quotes around the filename in the Response Headers, as seen here.
I've traced the Response Headers from TrueVault when downloading and I can see where the filename is being passed to the client without any quotes around the name. Since the client is downloading the Blob directly from TrueVault, there's nothing I can do in my code to affect this behavior. Anyone else seeing this behavior? Any suggestions?
Strict-Transport-Security: max-age=31536000
Server: gunicorn/18.0
Date: Wed, 29 Apr 2015 14:40:28 GMT
Content-Type: application/zip
Content-Length: 11377
Content-Disposition: attachment; filename=Test file with Spaces.docx
Connection: keep-alive
Cache-Control: no-cache
This issue will be addressed by 4/30/2015. Thanks for bringing this to our attention.

PHP or Apache seems to be caching files read via file_get_contents or include (unwanted behaviour)

Our web application has version numbers that get served out to the client on each request so we can detect an update to the code (ie rolling updates) and displays a popup informing them to reload to take advantage of the latest update.
But I'm experiencing some weird behaviour after the update of the version number on the server, where some requests return the new version number and some return the old, so the popup keeps poping up until you have reloaded the page a few times.
Originally I suspected maybe apache was caching files it read off disk via file_get_contents so instead of storing the version number in a plain text file, I now store it in a php file that gets included with each request, but I'm experiencing the exact same issue!
Anyone have any ideas what might be causing apache or php it self to be serving out old information after i have done an update?
EDIT: I have confirmed its not browser caching as I can have the client generate unique urls to the server (that it can deal with via rewrite) and i still see the same issue where some requests return the old version number and some the new, and clearing the browser cache doesn't help
EDIT 2: The response headers as requested
HTTP/1.1 200 OK
Date: Mon, 23 Jul 2012 16:50:53 GMT
Server: Apache/2.2.14 (Ubuntu)
X-Powered-By: PHP/5.3.2-1ubuntu4.7
Cache-Control: no-cache, must-revalidate
Pragma: no-cache
Expires: Sat, 26 Jul 1997 05:00:00 GMT
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 500
Connection: close
Content-Type: text/html
EDIT 3: So trying to reproduce to get the response headers I found I could only make it happen going through our full deploy process which involves creating versioned folders storing the code and symlinking the relavant folder into the webroot. Just changing the version number wasn't enough to cause it to happen! So seems to be somehow related to the symlinks i create!
I have the same problem when there is a change in the symlink. Have a look at https://bugs.php.net/bug.php?id=36555 it's maybe what you are looking for.
Try (as said in this bug report) setting realpath_cache_size is 0.

Test if X-Sendfile header is working

I am looking for a way to confirm if X-Sendfile is properly handling requests handed back to the webserver by a script (PHP). Images are being served correctly but I thought I would see the header in curl requests.
$ curl -I http://blog2.stageserver.net/wp-includes/ms-files.php?file=/2011/05/amos-lee-feature.jpg
HTTP/1.1 200 OK
Date: Wed, 04 Jan 2012 17:19:45 GMT
Server: Cherokee/1.2.100 (Arch Linux)
ETag: "4dd2e306=9da0"
Last-Modified: Tue, 17 May 2011 21:05:10 GMT
Content-Type: image/jpeg
Content-Length: 40352
X-Powered-By: PHP/5.3.8
Content-Disposition: inline; filename="amos-lee-feature.jpg"
Configuration
Cherokee 1.2.100 with PHP-FPM 5.3.8 in FastCGI:
cherokee.conf: vserver!20!rule!500!handler!xsendfile = 1
(Set by vServer > Behavior > Extensions php > Handler: Allow X-Sendfile [check Enabled])
Wordpress Network / WPMU 3.3.1:
define('WPMU_SENDFILE',true); is set in the wp-config.php the following just before wp-settings.php is included. This will trigger the following code to be executed in WP's wp-includes/ms-files.php:50 serves up files for a particular blog:
header( 'X-Sendfile: ' . $file );
exit;
I have confirmed that the above snippet is executing by adding an additional header for disposition right before the exit(); call. That Content-Disposition is present with curl results above and not originally in the ms-files.php code. The code that was added is:
header('Content-Disposition: inline; filename="'.basename($file).'"');
Research
I have:
Rebooted php-fpm / cherokee daemons after making configuration changes.
Tried several tricks in the comments over at php.net/readfile and replaced the simple header in ms-files.php with more complete code from examples.
php.net/manual/en/function.readfile.php
www.jasny.net/articles/how-i-php-x-sendfile/
*codeutopia.net/blog/2009/03/06/sending-files-better-apache-mod_xsendfile-and-php/*
Confirmed [cherokee support][5] and tested [with and without][6] compression even though I don't think it would apply since my images are serving correctly. I also found a suspiciously similar problem from a lighttpd post.
*cherokee-project.com/doc/other_goodies.html*
code.google.com/p/cherokee/issues/detail?id=1228
webdevrefinery.com/forums/topic/4761-x-sendfile/
Found a blurb here on SO that may indicate the header gets stripped
stackoverflow.com/questions/7296642/django-understanding-x-sendfile
Tested that the headers above are consistent from curl, wget, Firefox, Chrome, and web-sniffer.net.
Found out that I can't post more than 2 links yet due to lack of reputation.
Questions
Will X-Sendfile be present in the headers when it is working correctly or is it stripped out?
Can the access logs be used to determine if X-Sendfile is working?
I am looking for general troubleshooting tips or information here, not necessarily specific to PHP / Cherokee.
Update
I have found a suitable way to confirm X-Sendfile or X-Accel-Redirect in a test or sandbox environment: Disable X-Sendfile and check the headers.
With Allow X-Sendfile disabled in Cherokee:
$ curl -I http://blog2.stageserver.net/wp-includes/ms-files.php?file=/2011/05/amos-lee-feature.jpg
HTTP/1.1 200 OK
Date: Fri, 06 Jan 2012 15:34:49 GMT
Server: Cherokee/1.2.101 (Ubuntu)
X-Powered-By: PHP/5.3.6-13ubuntu3.3
Content-Type: image/jpeg
X-Sendfile: /srv/http/wordpress/wp-content/blogs.dir/2/files/2011/05/amos-lee-feature.jpg
Content-Length: 40352
The image will not load in browsers but you can see that the header is present. After re-enabling Allow X-Sendfile the image loads and you can be confident that X-Sendfile is working.
According to the source on github X-Sendfile headers will be stripped.
If I'm skimming the file correctly, it's only logging success if it's been compiled in debug mode.
You could check memory usage of sending large files with and without xsendfile.
They are being stripped, simply because having them present will prevent one of the reasons to use it, namely having the file served without the recepient knowing the location of the file being served.

Downloading invoices (PDF) does not complete

We have a magento commerce site running on an IIS 6.0 server with PHP 5.2.11 running magento.
Whenever user tries to use the print to download pdf to their computer from the admin panel the download does not complete. I can see that the full file is downloaded to the computer but the browser still keeps on saying it is downloading. This means the file gets save with a .part in the end and users cant open the file as pdf. If i remove .part extension created by firefox then i can view the pdf correctly. This means the data is sent to the browser from server in full but download does not terminate.
See headers below on response while starting to download the pdf
HTTP/1.x 200 OK
Cache-Control: must-revalidate, post-check=0, pre-check=0
Pragma: public
Content-Length: 1456781
Content-Type: application/pdf
Content-Encoding: gzip
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Last-Modified: Fri, 18 Dec 2009 10:23:37 +0000
Vary: Accept-Encoding
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET, PHP/5.2.11
Content-Disposition: attachment; filename=invoice2009-12-18_10-23-37.pdf
Date: Fri, 18 Dec 2009 10:23:37 GMT
I guess it is something to do with not closing the connection after sending the whole file through? Please help!
Thanks.
I had the exact same problem (Apache), I temporarily solved the issue by turning off the gzip compression on the responses. My guess is that the size being reported by Magento (which it gets from a strlen() call on the PDF content) to the browser does not reflect the real content size that the browser gets given that it gets compressed later on. This results in the browser waiting for more data which is never going to arrive..
edit: worth noting that in my case I was going to the site through a reverse proxy.
Have you tried explicitly calling exit; after you output the pdf data. Sounds like an IIS thing.

http headers to send file to html5 <audio>

I want use html5's new tag to play a wav file (currently only supported in FF.)
https://developer.mozilla.org/En/HTML/Element/Audio
I"m using php's readfile command to get the wav file off the hdd, and write it to the http response.
But its not working. The audio widget in firefox just has the loading animation running constantly.
The tag seems to be fine as I can put a different url in it's src/source and it works fine. I can use an tag and that downloads the file and it plays using Quicktime fine.
So I thinking perhaps its one/all of the content headers.
Using the FF Extension httpfox I can see these response headers arrive from the server:
(Status-Line) HTTP/1.1 200 OK
Date Mon, 12 Oct 2009 03:04:33 GMT
Server securesauce
Cache-Control private
Expires Mon, 26 Jul 1997 05:00:00 GMT
Pragma private
Vary Accept-Encoding
Content-Encoding gzip
Content-Length 8217
Keep-Alive timeout=15, max=100
Connection Keep-Alive
Content-Type audio/x-wav
So everything looks how I'd expect it to. The only headers I'm explicitly setting in the script (others are set elsewhere in the app) are:
Cache-Control private
Pragma private
Content-Type audio/x-wav
When I tried a different wav file (random one off the internet) httpfox didn't list any response headers.
Because its a php file sending out the content, I can't just send no headers, as I'd have to at least send the content-type.
Any ideas?
Source excerpt:
header('Cache-Control: private');
header('Pragma: private');
header("Content-Type: $contentType");
readfile($filepath);
exit;
Which formats and MIME types are supported by Mozilla is documented on their wiki. It doesn't look like the MIME type is your problem, but it's quite possible that this WAVE file isn't using the plain PCM audio which Firefox supports. WAVE can actually contain other formats like ADPCM, MP3 and whatnot. These may be supported by QuickTime, but there's no guarantee that it will play in a HTML5 browser. To be sure, try opening the file in a audio editor and saving it again as a WAVE PCM file.
You're missing X-Content-Duration. It's needed for the client to seek accurately during playback, and some clients refuse media content unless the duration is included. Also include Content-Duration, which is slowly replacing X-Content-Duration.
Here is some more information: Configuring web servers for HTML5 Ogg video and audio
Also, I would avoid using gzip or encryption on your output.
Have you tried the url of the audio file directly in your browser? If it contains an error or a warning that will make your header obsolete. and also try to open the audio file from the browser, see if it is correct.
I had the same trouble sending an ogg audio file using php. Playing with the headers did not help.
Then I updated from firefox 3.5.2 to 3.5.4 - that fixed the problem.

Categories