I have a Apache2 server with mod_mono in a Virtual Machine which has Ubuntu 16.04. I have noticed that the server is not answering to requests with the Range
header correctly. Initially it was not possible to even seek a specific time on video files, but using mod_headers
and adding Header set Accept-Ranges bytes
to the VirtualHost file corrected this.
However it never answers with 206 Partial Content
, even when a Range
is requested. The problem this causes is that when the user chooses to continue a download, the download of the file starts again from the beginning. On mobile devices it means the content is impossible to watch because the answer 200 OK
sends the entire video, which the devices simply don't have enough memory for.
The image below shows the problem. I was watching a video and paused it. When selected to play the video again, the entire video is downloaded again, which uses more bandwidth and device's memory. Seeking causes this too.
What configuration should I do to make the Partial Content response work?
The actual configuration:
httpd.conf:
ServerName exemplo
User web_server
Group web_server
ServerRoot /home/web_server/server
IncludeOptional mods-enabled/*.load
IncludeOptional mods-enabled/*.conf
IncludeOptional conf-enabled/*.conf
IncludeOptional sites-enabled/*.conf
Listen 80
<IfModule ssl_module>
Listen 443
</IfModule>
<IfModule mod_gnutls.c>
Listen 443
</IfModule>
PidFile apache2log/httpd.pid
ErrorLog apache2log/error.log
HostnameLookups Off
LogLevel warn
<Directory "/">
Require all denied
Options -Indexes
AllowOverride None
</Directory>
<FilesMatch "^\.ht">
Require all denied
</FilesMatch>
LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined
LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %O" common
LogFormat "%{Referer}i -> %U" referer
LogFormat "%{User-agent}i" agent
CheckSpelling Off
CheckCaseOnly On
mono_conf.conf (it's on sites-enabled):
<VirtualHost *:80>
ServerName local-server-1
ServerAdmin web-admin@local-server-1
DocumentRoot /home/web_server/server/mono
MonoServerPath local-server-1 "/usr/bin/mod-mono-server"
MonoSetEnv local-server-1 MONO_IOMAP=all;MONO_OLD_RX=1
MonoApplications local-server-1 "/:/home/web_server/server/mono"
<Location "/">
MonoSetServerAlias local-server-1
</Location>
<Location /mono>
SetHandler mono-ctrl
Order deny,allow
Deny from all
Allow from 127.0.0.1
</Location>
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/javascript
</IfModule>
<Directory "/home/web_server/server/mono">
SetHandler mono
Header set Accept-Ranges bytes
Allow from all
Require all granted
</Directory>
</VirtualHost>
<VirtualHost *:443>
SSLEngine On
SSLCertificateFile "/tmp/server.crt"
SSLCertificateKeyFile "/tmp/server.key"
ServerName local-server-1
ServerAdmin web-admin@local-server-1
DocumentRoot /home/web_server/server/mono
MonoServerPath local-server-1 "/usr/bin/mod-mono-server"
MonoSetEnv local-server-1 MONO_IOMAP=all;MONO_OLD_RX=1
MonoApplications local-server-1 "/:/home/web_server/server/mono"
<Location "/">
MonoSetServerAlias local-server-1
</Location>
<Location /mono>
SetHandler mono-ctrl
Order deny,allow
Deny from all
Allow from 127.0.0.1
</Location>
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/javascript
</IfModule>
<Directory "/home/web_server/server/mono">
SetHandler mono
Header set Accept-Ranges bytes
Allow from all
Require all granted
</Directory>
</VirtualHost>
Browser request:
GET http://localhost/arquivos/video.webm
Host: localhost
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:57.0) Gecko/20100101 Firefox/57.0
Accept: video/webm,video/ogg,video/*;q=0.9,application/ogg;q=0.7,audio/*;q=0.6,*/*;q=0.5
Accept-Language: pt-BR,pt;q=0.8,en-US;q=0.5,en;q=0.3
Referer: http://localhost/Default.aspx
Range: bytes=18120704-
Cookie: ASP.NET_SessionId=46ED58B6CD7745987060CDF5
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Server response:
Date: Thu, 18 Jan 2018 04:45:55 GMT
Server: Apache/2.4.18 (Ubuntu)
Last-Modified: Thu, 18 Jan 2018 02:16:55 GMT
X-AspNet-Version: 4.0.30319
Content-Length: 26728741
Cache-Control: private
Accept-Ranges: bytes
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: video/webm
I was able to solve this issue by creating a handler specifically to check if the Request has a Range and then give a Response with the range and the needed headers.
On the HTML it was required to add the following on each address of the files I want to allow Range requests:
The PartialHandler.ashx contains the following ProcessRequest:
With this, all videos worked on all devices I tested, the entire re-downloads of the entire video files every time it was paused or seek are no longer happening and the mobile devices are being able to play them.