Difficulty adding headers

i need to ensure the Accept-Ranges header is present to serve video
files
while supporting forward/backwards seeking.
i notice in many tutorials for nginx that this header is shown as being
present in server response headers by default, yet not on my present
setup.

i have used the following to add the header manually in the relevant
places,
yet so far have not been successful:

streamable mp4

location ~* .(mp4|mp4a)$
#location ~* .mp4$
#location ^~ /file/download/
{
mp4;
mp4_buffer_size 4M;
mp4_max_buffer_size 20M;
gzip off;
gzip_static off;
limit_rate_after 10m;
limit_rate 1m;
# here you add response header “Content-Disposition”
# with value of “filename=” + name of file (in variable
$request_uri),
# so for url example.com/static/audio/blahblah.mp3
# it will be /static/audio/blahblah.mp3
# ----
#set $sent_http_content_disposition filename=$request_uri;
# or
#add_header “content_disposition” “filename=$request_uri”;

# here you add header "Accept-Ranges"
#set $sent_http_accept_ranges bytes;

more_set_headers ‘Accept-Ranges: bytes’;

add_header “Accept-Ranges” “bytes”;

add_header "Cache-Control" "private";
add_header "Pragma" "private";
# tell nginx that final HTTP Status Code should be 206 not 200
return 206;

}

as you can see, i have played with various options, yet none have
succeeded.
i am not even sure that any of these directives are being called at all.
(this is part of a large-ish config file for a social network with many
features).

i am aware that nginx ignores add_header directives except for the ones
in
the final location block for the presently served file… yet so far this
awareness has not yielded a solution.

i am also not seeing a return code of 206 - instead the usual 200 is
returned when i access an mp4 file directly via curl.

anyone know what i am missing? thanks

Posted at Nginx Forum:

thanks for responding here.
the 206 code was advised by every tutorial i found online.
i am using nginx 1.7.2, so cannot upgrade.

You shouldn’t try to add Accept-Ranges header manually. It will
be added automatically when nginx supports range requests to the
resource in question.

how do i notify nginx to serve particular file extensions with the
accept-ranges header?

what would cause these headers to not be outputted in this case?

Posted at Nginx Forum:

also… since only the headers added via the final location block will be
used, does this then mean that i need to put conditional logic into that
block to check the current url for particular paths - if some headers
are
needed for some paths only… ?

since most of my served items will end in the .php location codeblock,
if my
thinking here is correct, i would essentially need to move nearly all of
my
existing location config blocks inside the php codeblock and then maybe
use
‘if’ statements to apply headers in appropriate ways.
or am i missing something here?

Posted at Nginx Forum:

Hello!

On Fri, Jun 27, 2014 at 11:50:47AM -0400, ura wrote:

i need to ensure the Accept-Ranges header is present to serve video files
while supporting forward/backwards seeking.
i notice in many tutorials for nginx that this header is shown as being
present in server response headers by default, yet not on my present setup.

i have used the following to add the header manually in the relevant places,
yet so far have not been successful:

You shouldn’t try to add Accept-Ranges header manually. It will
be added automatically when nginx supports range requests to the
resource in question.

streamable mp4

location ~* .(mp4|mp4a)$
#location ~* .mp4$
#location ^~ /file/download/
{
mp4;

Range requests to responses of mp4 module are supported starting
at 1.5.13 (previously, range requests was supported only for files
returned without modifications).

If it doesn’t work for you, it’s probably time to upgrade.

[…]

# tell nginx that final HTTP Status Code should be 206 not 200
return 206;

This is just wrong, as it prevents nginx from returning a
requested resource and unconditionally returns 206 response with
an empty response body.

Again, you shouldn’t try to return 206 manually. The 206 response
code is set automatically when a requested range is returned
(instead of the full response).


Maxim D.
http://nginx.org/

Hello!

On Fri, Jun 27, 2014 at 12:54:09PM -0400, ura wrote:

thanks for responding here.
the 206 code was advised by every tutorial i found online.
i am using nginx 1.7.2, so cannot upgrade.

Ok, so your problem is likely due to “return 206” added. Just
remove it, as well as other garbage from your config you don’t
understand. It’s really good idea to read the documentation to
make sure you understand what you are writing into your config
instead of blindly following “tutorials online”.

I very much doubt there is any tutorial which suggests to use
“return 206” though, as it’s always wrong.

You shouldn’t try to add Accept-Ranges header manually. It will
be added automatically when nginx supports range requests to the
resource in question.

how do i notify nginx to serve particular file extensions with the
accept-ranges header?

Again: you shouldn’t do anything. If range requests are
supported, the header will be added automatically.

what would cause these headers to not be outputted in this case?

See above, mostly likely it’s caused by “return 206” in your
config.


Maxim D.
http://nginx.org/

i just did a test of inserting a meaningless header into the response,
by
adding the add_header directive into the various levels of the nginx
config,
beginning with http, then server and then the location that i have setup
to
focus on mp4 files.

i found that the header is successfully inserted inside the http and
server
blocks, yet when i request an mp4 file via curl, the header is not
returned… which suggests to me that the location block i am using is
dysfunctional in some way.

currently i am using the block below, though i have used various other
versions which also failed.

location ~ .(mp4|mp4a)$
{
add_header “name” “value”;
}

Posted at Nginx Forum:

this stackoverflow response on the topic is one that quotes the code i
used… i have also seen this page linked by several other pages which
said
this was a workable approach:

i am not blindly following anything - i am looking at all the available
information and referred to the nginx documentation - i am using what
works
and disregarding what does not. so far i have not found an explanation
of
this situation i am experiencing in the documentation or on forums,
hence i
am here asking.

in any case, i removed return 206;
the situation did not change.
i am unclear why removing ‘return 206’ would cause a 200 response to
become
a 206 response! :wink:

" If range requests are
supported, the header will be added automatically."

i am making a simple request for a static mp4 file via curl to nginx
1.7.2…
i am not clear on your use of the idea of ‘if range requests are
supported’
in this context. how would i know if they are supported or not?

Posted at Nginx Forum:

Hello!

On Fri, Jun 27, 2014 at 02:23:47PM -0400, ura wrote:

this stackoverflow response on the topic is one that quotes the code i
used… i have also seen this page linked by several other pages which said
this was a workable approach:

I think I understand the problem of the author of this question.
I’ve added an answere there - most likely, it has ssi or something
like enabled for all MIME types.

i am not blindly following anything - i am looking at all the available
information and referred to the nginx documentation - i am using what works
and disregarding what does not. so far i have not found an explanation of
this situation i am experiencing in the documentation or on forums, hence i
am here asking.

in any case, i removed return 206;
the situation did not change.
i am unclear why removing ‘return 206’ would cause a 200 response to become
a 206 response! :wink:

The 206 code indicates that “this was 200, but due to Range header
only part of the actual response is returned”.

" If range requests are
supported, the header will be added automatically."

i am making a simple request for a static mp4 file via curl to nginx 1.7.2…
i am not clear on your use of the idea of ‘if range requests are supported’
in this context. how would i know if they are supported or not?

If you don’t see the Accept-Ranges header added to a response, then
range requests are not supported.

If you don’t see Accept-Ranges header added to responses to a
static mp4 file, then there is something wrong in your config.
Either a response is handled in a wrong location and ends up being
handled not by nginx, or there is a filter active for some/all
responses which may modify them and hence disables range support.

If you can’t trace the problematic configuration and/or not sure
it’s the case, you may start testing with a clean config. E.g.,
with trivial configuration like this:

http {
    include mime.types;

    server {
        listen 8080;

        location / {
            mp4;
        }
    }
}

A request to static mp4 file results in:

$ curl -I http://localhost:8080/mp4/test.mp4
HTTP/1.1 200 OK
Server: nginx/1.7.3
Date: Fri, 27 Jun 2014 18:38:24 GMT
Content-Type: video/mp4
Content-Length: 7147296
Last-Modified: Fri, 15 Jun 2012 15:50:37 GMT
Connection: keep-alive
ETag: “4fdb59cd-6d0f20”
Accept-Ranges: bytes


Maxim D.
http://nginx.org/

Hello!

On Fri, Jun 27, 2014 at 07:26:04PM -0400, ura wrote:

preloads and streams correctly when i play it via the video.js player on my

i even downloaded a php class to correct the moov atom for the mp4 file, in
case that was the challenge here. although some files did need to be fixed,
the issue of the video files’ moov atoms being in the wrong position, is not
the cause of my main challenge with the pre-buffering of videos.

so now i am stuck again, with no idea of what i am missing from my server to
activate pre-buffering of video. perhaps i will message the video.js coders
directly.

As far as I see, “video.js” isn’t a player per se, but rather an
interface for HTML5 player in your browser. You may start
debugging with just a

I’ve just tested with a simple video tag and the mp4 file from the
video.js “Getting Started” page, and it seems to work fine here
with the following html code:

The only problem I faced was due to OS X 10.9 network stack bug,
it seems to have problems with packet retransmission after 25 days
of uptime. As the mp4 file in question is big enough, it used to
trigger the problem when streamed from my development VM here, and
connection used to got stuck after 4M or so. And it seems that
Chrome isn’t able to recover from such a problem when streaming
video using HTML5

It’s highly unlikely you are facing the same problem, but rather a
reminder that HTML5 video streaming is still quite fragile and
should be handled with care.


Maxim D.
http://nginx.org/

ok, thanks for clarifying.
i just did a clean test as suggested and do indeed see the Accept-Ranges
header being returned automatically by nginx.

in doing that - the mp4 video still does not stream/pre-buffer as i am
desiring.

i accessed the test video file that is on the homepage of the video.js
website via curl and there is no Accept-Ranges header being sent in the
response for their file, on their server… yet their test video file
preloads and streams correctly when i play it via the video.js player on
my
local dev machine (served via nginx).

when i download their test video and play it via my same dev machine
here,
the preloading does not function.

so…
a) Accept-Ranges is not the cause of the lack of streaming here.
b) the same file will preload on another server, yet not on mine (the
headers being sent from the other server are not obviously different to
the
ones being sent from my own nginx server).

i even downloaded a php class to correct the moov atom for the mp4 file,
in
case that was the challenge here. although some files did need to be
fixed,
the issue of the video files’ moov atoms being in the wrong position, is
not
the cause of my main challenge with the pre-buffering of videos.

so now i am stuck again, with no idea of what i am missing from my
server to
activate pre-buffering of video. perhaps i will message the video.js
coders
directly.

Posted at Nginx Forum:

after more exploration, i see that files which are placed in the root of
my
site can be preloaded and seeked correctly when played via the video.js
package or directly as a video element.
however, the videos that are played via the php application that runs my
site are stored outside of the root directory of the site and i suspect
that
this is the cause of them not being streamed. (i am using the elgg
social
framework (www.elgg.org)). when i request one of these files from it’s
extermal/absolute url via curl, the accept_ranges header is not present,
yet
the header IS present when i place the same file at the public root of
the
site manually and request the file via curl.

e.g. the site is at : /var/www/html/mysite/
and the videos are at: /var/www/data/paths/

so the root directive for the server in the nginx config is
/var/www/html/mysite/

what appears to be occurring is that the request for the mp4 file is
being
processed via php so is using the .php location in my nginx config
instead
of the .mp4 config… thus the mp4; directive is not being triggered for
mp4
files.
when i place the mp4 directive inside the php location block i just get
prompted to download a file whenever i navigate to a php page.

so this would appear to be a case of either needing some conditional
logic
in the nginx config file or a re-design of the architecture of the elgg
php
application. this was already highlighted in a related thread in the
elgg
community, though not to resolve this explicit problem - only to improve
performance.
(anyone excited to team up to create an enhanced video plugin for elgg? : Elgg.org)

Posted at Nginx Forum:

Hello!

On Sat, Jun 28, 2014 at 11:25:30AM -0400, ura wrote:

when i place the mp4 directive inside the php location block i just get
prompted to download a file whenever i navigate to a php page.

In no particular order:

  1. For HTML5 video streaming to work, you don’t need “mp4”
    directive in your nginx config. It’s only needed for flash-based
    pseudo streaming. HTML5 video streaming will work fine without
    the mp4 module, using standard HTTP range requests.

  2. If php is used to return a response, it’s php code
    responsibility to return various headers, including Accept-Ranges,
    as well as byte-ranges support itself.

  3. It would be more or less trivial to serve static files with
    nginx regardless of their location in the filesystem hierarchy.
    There are “root” and “alias” directives which can be set at
    location{} level, see Module ngx_http_core_module and
    Module ngx_http_core_module.

  4. (Following you next message) X-Accel-Redirect can be used to
    effectiently return static files, see
    XSendfile | NGINX for some links.


Maxim D.
http://nginx.org/

one of the core elgg coders was speaking about using the X-Sendfile
header
to bypass php processing and serve the file directly, though i don’t
know
enough about how the architecture of nginx/php would handle that to know
if
it would help here or not.

Posted at Nginx Forum:

ok, thanks.

  1. i was thinking that this was the case, based on the results i have
    seen,
    yes.
  2. ah, ok - i didn’t appreciate that. i found this page with php code:
    http://licson.net/post/stream-videos-php/

is there a standard / recommended way to approach this with nginx?

  1. i believe the problem i am encountering is that i am unable to
    explicitly
    redirect file requests for a specific path (e.g. a path i create for use
    with streaming videos, called ‘stream’) to a specific static address in
    the
    server’s filestorage, because every request is being handled via a php
    file
    and there is a .php location block in the site config. so if i create a
    location:

location /stream/ {
internal;
root /var/www/data/;
}

and then navigate to www.mysite.tld/stream/blah.mp4

what is occuring is that the stream block is never processed and the
.php
block in the config is triggered instead… i’m not 100% clear on why
this is
occurring.

here’s a sample elgg nginx config file that is basically similar to
mine:

i have created a new thread in the forum here for this topic, since you
have
really helpfully addressed my original question and the topic has
changed.
(new thread: using 'X-Accel-Redirect' in 'internal' with PHP to stream videos?)

i will play some more with this shortly and see if i can make any
progress.
thanks for your focus. :slight_smile:

Posted at Nginx Forum:

Hello!

On Mon, Jun 30, 2014 at 04:34:51PM -0400, ura wrote:

ok, thanks.

  1. i was thinking that this was the case, based on the results i have seen,
    yes.
  2. ah, ok - i didn’t appreciate that. i found this page with php code:
    http://licson.net/post/stream-videos-php/

is there a standard / recommended way to approach this with nginx?

Streaming videos with php is silly, so recommended approach is
“Don’t do that”.

}

and then navigate to www.mysite.tld/stream/blah.mp4

First of all, try removing “internal”, as it will prevent handling
of all external requests.

what is occuring is that the stream block is never processed and the .php
block in the config is triggered instead… i’m not 100% clear on why this is
occurring.

here’s a sample elgg nginx config file that is basically similar to mine:
A sample Nginx configuration for Elgg-1.8 · GitHub

If you don’t understand how requests are handled in your config,
it’s probably good idea to throw it away and start with something
simple without regex locations, rewrites, if’s and so on.

i have created a new thread in the forum here for this topic, since you have
really helpfully addressed my original question and the topic has changed.
(new thread: using 'X-Accel-Redirect' in 'internal' with PHP to stream videos?)

Just a note: it’s not forum, it’s a mailing list.


Maxim D.
http://nginx.org/

the config i am using is inherited from the designers of the elgg
platform
and i have explored it enough to know most of what it is doing.
perhaps i need to replace the location block that targets .php files
with
one that explicitly lists all the possible locations of php files
instead…
which would leave the possibility open for the new ‘stream’ location
block i
am using here.

i was using the internal keyword since i am wanting to do what i can to
ensure that the video files are only available to site visitors once
they
have passed a security process (handled by php and sql). the site here
is a
social network and all media items have an associated privacy level - so
the
files cannot all be public, which is the origin of these issues. the
files
are held outside of the nginx site root directory for this reason.

Streaming videos with php is silly, so recommended approach is
“Don’t do that”.

how else can a video be served from a PHP social networking app, where
the
file needs to be ‘behind’ privacy/security checks?
wouldn’t there need to be some kind of PHP processing just to set up the
externally accessible path for the video file (after the viewer’s
credentials have been checked)?
to be clear, i am not saying that the final path for the video is a .php
file… the final path would be filename.mp4… however, the php location
block is triggered along the processing path anyway - as the config is.

(i am using the web interface for forum.nginx.org… so this is a mailing
list and also a forum). :wink:

Posted at Nginx Forum:

Hello!

On Fri, Jul 04, 2014 at 09:48:04AM -0400, ura wrote:

social network and all media items have an associated privacy level - so the
files cannot all be public, which is the origin of these issues. the files
are held outside of the nginx site root directory for this reason.

Sure. The problem is that you try to “navigate to
www.mysite.tld/stream/blah.mp4”, and it won’t work if the location
in question is internal.

block is triggered along the processing path anyway - as the config is.
There are more than one way to do security checks. Most obvious
ones is to use either X-Accel-Redirect, or auth_request, or
secure_link.


Maxim D.
http://nginx.org/

Ah, votre problème semble être un peu compliqué, je ne pourrais pas vous
aider, désolé