Allow internal redirect to URI x, but deny external request for x?

2019-08-30 Thread J. Lewis Muir
Hello!

I'm using nginx 1.12.2 on RHEL 7, and I've got a FastCGI web app that
uses a deployment structure which uses an atomic symlink change for an
atomic app deploy, and I'm wishing to be able to do an internal redirect
in nginx to URL x, but deny an external request to the same URL x so
that I don't serve the same content at more than one URL.  Is there a
way to do that?

For example, given the external request URI

  /my-app/index.html

I want to do an internal redirect to

  /my-app/current/index.html

but deny an external request for that same URI

  /my-app/current/index.html

because I don't want to serve the app from two different URLs (e.g.,
/my-app/ and /my-app/current/).

The app structure on disk is like the Capistrano structure

  https://capistranorb.com/documentation/getting-started/structure/

That is, it's like

  /srv/www/my-app
current -> releases/1.0.2
releases
  1.0.0
  1.0.1
  1.0.2

"current" is a symlink.

In my nginx config, I've changed $document_root to $realpath_root in the
appropriate FastCGI parameters, and have the following locations:

  location /my-app/ {
rewrite ^/my-app/(?!current/)(.*)$ /my-app/current/$1 last;
index index.php;
  }

  location /my-app/current/ {
return 404;
  }

  location /my-app/releases/ {
return 404;
  }

  location ~ ^/my-app/.*?[^/]\.php(?:/|$) {
include php-fpm-realpath.conf;
  }

Given an external request for a URI that starts with

  /my-app/

this returns 404 after the internal redirect.  If I remove the two
locations that return 404, then it serves the app, but it also allows
external requests such as

  /my-app/current/

which I don't want to allow since that's a duplicate of

  /my-app/

I initially tried using the alias directive which I thought was a better
fit for what I wanted to do

  location /my-app/ {
alias /srv/www/my-app/current/;
index index.php;
  }

  location /my-app/current/ {
return 404;
  }

  location /my-app/releases/ {
return 404;
  }

  location ~ ^/my-app/(.*?[^/]\.php(?:/.*|$)) {
alias /srv/www/my-app/current/$1;
include php-fpm-realpath.conf;
  }

But that didn't seem to work with the nginx FastCGI implementation.

Thank you!

Lewis
___
nginx mailing list
nginx@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx


Re: Allow internal redirect to URI x, but deny external request for x?

2019-08-30 Thread J. Lewis Muir
On 08/30, J. Lewis Muir wrote:
> I'm wondering if the fastcgi_split_path_info function or the if
> directive is what's emitting the file op message in the error log which
> would mean that one or both of $realpath_root or $fastcgi_script_name
> are not set to what I expect. (?)

Adding

  return 200 "document_root: $document_root\nfastcgi_script_name: 
$fastcgi_script_name\n";

to the location like this

  location ~ ^/my-app/(.*?[^/]\.php(?:/.*|$)) {
alias /srv/www/my-app/current/$1;
return 200 "realpath_root: $realpath_root\nfastcgi_script_name: 
$fastcgi_script_name\n";
  }

yields the following:

  $ curl http://localhost/my-app/
  realpath_root: /srv/www/my-app/releases/1.0.2/index.php
  fastcgi_script_name: /my-app/index.php

So, that doesn't seem right!  I was expecting them to be something like:

  realpath_root: /srv/www/my-app/releases/1.0.2
  fastcgi_script_name: /index.php

Puzzled,

Lewis
___
nginx mailing list
nginx@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx


Re: Allow internal redirect to URI x, but deny external request for x?

2019-08-30 Thread J. Lewis Muir
On 08/30, J. Lewis Muir wrote:
> I initially tried using the alias directive which I thought was a better
> fit for what I wanted to do
> 
>   location /my-app/ {
> alias /srv/www/my-app/current/;
> index index.php;
>   }
> 
>   location /my-app/current/ {
> return 404;
>   }
> 
>   location /my-app/releases/ {
> return 404;
>   }
> 
>   location ~ ^/my-app/(.*?[^/]\.php(?:/.*|$)) {
> alias /srv/www/my-app/current/$1;
> include php-fpm-realpath.conf;
>   }
> 
> But that didn't seem to work with the nginx FastCGI implementation.

What exactly didn't work when I tried the alias directive, based on the
error log, seems to be that somewhere there's a file op on

  /srv/www/my-app/releases/1.0.2/index.php/my-app/index.php

which is a wrong path; it should be

  /srv/www/my-app/releases/1.0.2/index.php

In my php-fpm-realpath.conf, I have

  fastcgi_split_path_info ^(.+?\.php)(/.*)$;
  if (!-f $realpath_root$fastcgi_script_name) {
return 404;
  }
  ...
  fastcgi_param DOCUMENT_ROOT $realpath_root;
  fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
  ...

I'm wondering if the fastcgi_split_path_info function or the if
directive is what's emitting the file op message in the error log which
would mean that one or both of $realpath_root or $fastcgi_script_name
are not set to what I expect. (?)

Here are the relevant lines from the error log with the debug option:

  test location: "/my-app/"
  test location: ~ "^/my-app/(.*?[^/]\.php(?:/.*|$))"
  using configuration "/my-app/"
  open index "/srv/www/my-app/current/index.php"
  internal redirect: "/my-app/index.php?"
  rewrite phase: 1
  test location: "/my-app/"
  test location: ~ "^/my-app/(.*?[^/]\.php(?:/.*|$))"
  using configuration "^/my-app/(.*?[^/]\.php(?:/.*|$))"
  rewrite phase: 3
  http script complex value
  http script copy: "/srv/www/my-app/current/"
  http script capture: "index.php"
  http script copy: "/srv/www/my-app/current/"
  http script capture: "index.php"
  http script var: "/srv/www/my-app/releases/1.0.2/index.php"
  http script var: "/my-app/index.php"
  http script copy: ""
  http script var: "/my-app/index.php"
  http script copy: ""
  http script file op 0001 
"/srv/www/my-app/releases/1.0.2/index.php/my-app/index.php"
  http script if
  http finalize request: 404, "/my-app/index.php?" a:1, c:2
  http special response: 404, "/my-app/index.php?"
  http set discard body
  xslt filter header
  HTTP/1.1 404 Not Found

Thank you!

Lewis
___
nginx mailing list
nginx@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx


Re: Allow internal redirect to URI x, but deny external request for x?

2019-08-30 Thread J. Lewis Muir
On 08/30, J. Lewis Muir wrote:
> On 08/30, J. Lewis Muir wrote:
> > I'm wondering if the fastcgi_split_path_info function or the if
> > directive is what's emitting the file op message in the error log which
> > would mean that one or both of $realpath_root or $fastcgi_script_name
> > are not set to what I expect. (?)
> 
> Adding
> 
>   return 200 "document_root: $document_root\nfastcgi_script_name: 
> $fastcgi_script_name\n";
> 
> to the location like this
> 
>   location ~ ^/my-app/(.*?[^/]\.php(?:/.*|$)) {
> alias /srv/www/my-app/current/$1;
> return 200 "realpath_root: $realpath_root\nfastcgi_script_name: 
> $fastcgi_script_name\n";
>   }

Hmm, I think I need to call fastcgi_split_path_info first, so now I did

  location ~ ^/my-app/(.*?[^/]\.php(?:/.*|$)) {
alias /srv/www/my-app/current/$1;
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
return 200 "realpath_root: $realpath_root\nfastcgi_script_name: 
$fastcgi_script_name\nfastcgi_path_info: $fastcgi_path_info\n";
  }

which yields the following:

  $ curl http://localhost/my-app/
  realpath_root: /srv/www/my-app/releases/1.0.2/index.php
  fastcgi_script_name: /my-app/index.php
  fastcgi_path_info:

That doesn't seem right.

Still puzzled,

Lewis
___
nginx mailing list
nginx@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx


Re: Allow internal redirect to URI x, but deny external request for x?

2019-08-31 Thread J. Lewis Muir
On 08/31, Francis Daly wrote:
> On Sat, Aug 31, 2019 at 12:21:40AM +0100, Francis Daly wrote:
> 
> Hi there,
> 
> A few further thoughts here...
> 
> > It sounds like your desires are for requests:
> > 
> >  * starts with /my-app/current/ -> reject
> >  * starts with /my-app/releases/ -> reject
> >  * matches /my-app/something.php, or /myapp/something.php/anything ->
> 
> Typo there -- should be "/my-app/".

Yeah, no problem; I knew what you meant.

> But note that the "/my-app/" in the request and the "/my-app/" on the
> filesystem do not need to the same. (And also: the filesystem /my-app/
> for the php files and the filesystem /my-app/ for other files do not
> need to be the same; if you want to keep your "static" and "processed"
> content separate.)

Got it.

> > fastcgi-process the file /srv/www/my-app/current/something.php
> >  * matches /my-app/something -> just send the file
> > /srv/www/my-app/current/something
> > 
> > Is that correct? If so -- do exactly that.
> > 
> > For example (but mostly untested):
> > 
> > ==
> >   location ^~ /my-app/current/ { return 200 "nothing to see at 
> > /current/\n"; }
> >   location ^~ /my-app/releases/ { return 200 "nothing to see at 
> > /releases/\n"; }
> >   location ^~ /my-app/ {
> > location ~ \.php($|/) {
> >   fastcgi_split_path_info ^/my-app(/.*php)(.*);
> 
> If there might be more than one "php" in the request, that will split on
> "the last one". Perhaps you want to split on "the first one followed by
> slash". In that case, adjust the regex:
> 
>   fastcgi_split_path_info ^/my-app(/.*?php)($|/.*);

Yes, I ended up doing something like that:

  fastcgi_split_path_info ^/synchweb(/.+?\.php)(/.*)?$;

I think you'd want the "\." in yours before the "php", and then I think
the only meaningful difference between ours would be that yours would
match

  /my-app/.php

while mine would not because I used ".+?" to match one or more
reluctantly where you used ".*?" to match zero or more reluctantly.

I was aware of

  https://www.nginx.com/resources/wiki/start/topics/examples/phpfcgi/

which has a location of

  location ~ [^/]\.php(/|$) {

and a fastcgi_split_path_info of

  fastcgi_split_path_info ^(.+?\.php)(/.*)$;

I've always wondered exactly what the idea was with starting that
location regex with "[^/]", though.  Why require the ".php" to be
preceded by a character other than "/"? That means it would match a
request of

  /foo.php

but not

  /.php

Is it because that's considered an invalid PHP file name?  Is it because
some PHP web apps uses a directory named ".php" as a private directory
that should not be served?  I don't know.

> >   root /srv/www/my-app/current/;
> 
> You did also show a "if (!-f" config, which is "404 if the matching php
> file is not present". That can be:
> 
>   try_files $fastcgi_script_name =404;
> 
> because we have root and the variable set correctly here.

Ah, I see!  Thank you for pointing that out!  I like that better.

> >   include fastcgi.conf;
> 
> Possibly the only bits of that file that you care about are:
> 
>   fastcgi_param PATH_INFO $fastcgi_path_info;
>   fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
> 
> so you could just use those lines directly.

Yes, I could, but I was trying to make my php-fpm-realpath.conf reusable
for other apps which is why I was keeping those lines in it.  And, I
think I mentioned this earlier, but I changed them to use $realpath_root
instead of $document_root because of the symlinks and my desire to
support an atomic app deploy with no downtime and no nginx reload.

Thanks again!

Lewis
___
nginx mailing list
nginx@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx


Re: Allow internal redirect to URI x, but deny external request for x?

2019-08-31 Thread J. Lewis Muir
On 08/30, Ian Hobson wrote:
> Hi Lewis,
> 
> On 30/08/19 18:33, J. Lewis Muir wrote:
> > Hello!
> > 
> > I'm using nginx 1.12.2 on RHEL 7, and I've got a FastCGI web app that
> > uses a deployment structure which uses an atomic symlink change for an
> > atomic app deploy, and I'm wishing to be able to do an internal redirect
> > in nginx to URL x, but deny an external request to the same URL x so
> > that I don't serve the same content at more than one URL.  Is there a
> > way to do that?
> > 
> You could place the different versions away from the root so they cannot be
> obtained from the web. Then they can be served by setting up a symlink to
> the desired version.
> 
> This can be changed using "ln -sfn version/dir serving/root" and then
> restarting nginx to pick up the new version.
> 
> By not using redirects, this method should be more efficient.
> 
> Regards
> 
> Ian

Hi, Ian!

Thank you for the suggestion!  That's an interesting idea, and that
would avoid needing to exclude those URIs from being served and I think
avoid needing to change the document root and maybe some other things.

I toyed around with some designs and came up with four; I think I like
the third one best, but I'm not sure, maybe the fourth one is better.

= Design #1

Web app root:

  /srv/www/app/my-app
current -> releases/1.0.2
releases
  1.0.0
  1.0.1
  1.0.2

nginx server document root:

  /srv/www/host/localhost
my-app -> /srv/www/app/my-app/current

Comments:

  This tries to share apps between virtual hosts.  It provides no way
  for different virtual hosts to serve the same app but with the app
  configured differently.  Also, all virtual hosts have to serve the
  same version of the app.

= Design #2

Web app root:

  /srv/www/app/my-app
1.0.0
1.0.1
1.0.2

nginx server document root:

  /srv/www/host/localhost
my-app -> /srv/www/app/my-app/1.0.2

Comments:

  Similar to design #1 except now the virtual hosts can server different
  versions of the app, but for a given version, the app is still
  configured in the exact same way for all virtual hosts.

= Design #3

Web app root:

  /srv/www/localhost/app
my-app
  1.0.0
  1.0.1
  1.0.2

nginx server document root:

  /srv/www/localhost/root
my-app -> ../app/my-app/1.0.2

Comments:

  I like this because now each virtual host has its own set of deployed
  apps, so the apps can be configured specifically for that particular
  virtual host.

= Design #4

Web app root:

  /srv/www/localhost/app
my-app
  current -> releases/1.0.2
  releases
1.0.0
1.0.1
1.0.2

nginx server document root:

  /srv/www/localhost/root
my-app -> ../app/my-app/current

Comments:

  Similar to design #3 but moves where the "current" symlink lives.  So,
  the deployed version of the app is controlled under the web app root
  rather under the nginx server document root.  Maybe this is a little
  better because the nginx config reference to "my-app" can be sure to
  be correct and can be changed if desired, and be unrelated to which
  version of the app is deployed via the "current" symlink in the web
  app root.  The downside is two symlinks (i.e., a symlink to a symlink)
  as opposed to one.

Regards,

Lewis
___
nginx mailing list
nginx@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx


Re: Allow internal redirect to URI x, but deny external request for x?

2019-08-31 Thread J. Lewis Muir
On 08/31, Francis Daly wrote:
> On Fri, Aug 30, 2019 at 04:59:36PM -0500, J. Lewis Muir wrote:
> 
> Hi there,
> 
> > I was wishing for a way to specify a new root but with a modified
> > request URI.  So, I tried the alias directive, and I assumed that
> > $document_root and $realpath_root would refer to the aliased document
> > root, but obviously that can't be since nginx has no way of knowing what
> > the aliased document root should be when all it has is a location alias
> > which is the full path to the resource.  Sorry for the trouble.
> 
> It sounds like your desires are for requests:
> 
>  * starts with /my-app/current/ -> reject
>  * starts with /my-app/releases/ -> reject
>  * matches /my-app/something.php, or /myapp/something.php/anything ->
> fastcgi-process the file /srv/www/my-app/current/something.php
>  * matches /my-app/something -> just send the file
> /srv/www/my-app/current/something
> 
> Is that correct? If so -- do exactly that.

Yes!
 
> For example (but mostly untested):
> 
> ==
>   location ^~ /my-app/current/ { return 200 "nothing to see at /current/\n"; }
>   location ^~ /my-app/releases/ { return 200 "nothing to see at 
> /releases/\n"; }
>   location ^~ /my-app/ {
> location ~ \.php($|/) {
>   fastcgi_split_path_info ^/my-app(/.*php)(.*);
>   root /srv/www/my-app/current/;
>   include fastcgi.conf;
>   fastcgi_pass unix:php.sock;
> }
> alias /srv/www/my-app/current/;
>   }
> ==

Wow!  I had given up on getting this approach to work.  Honestly, I
don't think I would have thought of your solution.  Brilliant!

I tried it, and it worked after making a few tweaks!  Here's what
worked:

  location ^~ /my-app/current/ {
return 404;
  }

  location ^~ /my-app/releases/ {
return 404;
  }

  location ^~ /my-app/ {
index index.php;
location ~ [^/]\.php(?:/|$) {
  root /srv/www/my-app/current;
  fastcgi_split_path_info ^/my-app(/.+?\.php)(/.*)?$;
  include php-fpm-realpath.conf;
}
alias /srv/www/my-app/current/;
  }

I changed the root directive to come before the fastcgi_split_path_info,
but that was just aesthetic; it worked fine the other way
too.  Previously, I had the fastcgi_split_path_info call in
php-fpm-realpath.conf along with the following file-exists check after
it:

  if (!-f $realpath_root$fastcgi_script_name) {
return 404;
  }

But I moved the fastcgi_split_path_info call out of
php-fpm-realpath.conf so that I could use the custom regex like in your
suggestion.

So, your solution solved my problem!  Thank you!

On a related note, while considering those return-404s for
/my-app/current/ and /my-app/releases/, I realized that those could, in
theory, conflict with the URIs of a web app if the web app actually used
those same URIs.  For example, maybe the web app is a GitLab-type app
and a URI of /my-app/releases/ might very well be part of the app's URI
set for displaying software releases or something.  This has nothing to
do with your solution and everything to do with my initial design choice
that I was trying to achieve, and it's something I hadn't considered
before.

For my current app, it doesn't use those URIs, so it's not a problem,
but as a general scheme, it's not perfect.  I think one solution would
be to move the app root directory to a different name so that it can't
conflict.  For example, have it live at

  /srv/www/my-app-deployment

or something like that.  Then I could just return a 404 for any request
on that, e.g.:

  location ^~ /my-app-deployment/ {
return 404;
  }

Thanks again!

Lewis
___
nginx mailing list
nginx@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx


Re: Allow internal redirect to URI x, but deny external request for x?

2019-08-30 Thread J. Lewis Muir
On 08/30, Francis Daly wrote:
> On Fri, Aug 30, 2019 at 01:58:23PM -0500, J. Lewis Muir wrote:
> 
> Hi there,
> 
> >   location ~ ^/my-app/(.*?[^/]\.php(?:/.*|$)) {
> > alias /srv/www/my-app/current/$1;
> > fastcgi_split_path_info ^(.+?\.php)(/.*)$;
> > return 200 "realpath_root: $realpath_root\nfastcgi_script_name: 
> > $fastcgi_script_name\nfastcgi_path_info: $fastcgi_path_info\n";
> >   }
> > 
> > which yields the following:
> > 
> >   $ curl http://localhost/my-app/
> >   realpath_root: /srv/www/my-app/releases/1.0.2/index.php
> >   fastcgi_script_name: /my-app/index.php
> >   fastcgi_path_info:
> > 
> > That doesn't seem right.
> 
> Why not?
> 
> http://nginx.org/r/$realpath_root says is it the current root or alias
> value, resolving symlinks.
> 
> The request was /my-app/, the current request is /my-app/index.php,
> and you have alias'ed that to /srv/www/my-app/current/index.php
 
Yes, you're absolutely right.  This is where I went wrong.  I was
initially wishing to use the root directive

  location ~ ^/my-app/(.*?[^/]\.php(?:/.*|$)) {
root /srv/www/my-app/current;
include php-fpm-realpath.conf;
  }

but then the URI would be appended to that, so for a request of

  /my-app/index.php

it would result in

  /srv/www/my-app/current/my-app/index.php

which wasn't what I wanted; instead I wanted

  /srv/www/my-app/current/index.php

I was wishing for a way to specify a new root but with a modified
request URI.  So, I tried the alias directive, and I assumed that
$document_root and $realpath_root would refer to the aliased document
root, but obviously that can't be since nginx has no way of knowing what
the aliased document root should be when all it has is a location alias
which is the full path to the resource.  Sorry for the trouble.

> http://nginx.org/r/$fastcgi_script_name (and what follows) describes
> the other variables.
> 
> The request is /my-app/index.php and your fastcgi_split_path_info sets
> $fastcgi_script_name to "everything up to .php" and $fastcgi_path_info to
> "everything after .php", so long as .php is followed by / -- which it
> isn't, so both are unchanged from their defaults of "the uri" and "empty".
> 
> (I'm somewhat guessing about the last part there; a test can probably
> demonstrate whether it is incorrect.)

Yep, I'm sure you're right here as well.  Sorry for the trouble; I just
totally missed how this worked.

Thank you for your help!

Lewis
___
nginx mailing list
nginx@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx


Re: Allow internal redirect to URI x, but deny external request for x?

2019-09-03 Thread J. Lewis Muir
On 09/02, Francis Daly wrote:
> nginx does not "do" php. nginx does not care what your fastcgi server
> will do with the key/value pairs that it sends. nginx cares that the
> fastcgi server gives a valid response to the request that nginx makes.
> 
> Typically, your fastcgi server will use the value associated with
> SCRIPT_FILENAME as "the name of the file to execute". If your fastcgi
> server fails to find / read / execute that file, it will return its own
> error indication.
> 
> (So your "if", or the more common "try_files", is just an early-out,
> to sometimes avoid involving the fastcgi server. It may happen that the
> file is present when nginx looks for it, but is absent when the fastcgi
> server looks for it -- so that case does have to be handled anyway.)
> 
> In this case, if $document_root is /srv/www/my-app/current/ and
> $realpath_root is /srv/www/my-app/releases/1.0.2/, and the script
> name is test.php, then with one config, nginx would send the string
> "/srv/www/my-app/current/test.php", and with the other config nginx
> would send the string "/srv/www/my-app/releases/1.0.2/test.php".
> 
> (That is "pathname1" vs "pathname2".)
 
Understood.

> So if "one request" involves the fastcgi server reading
> "/srv/www/my-app/current/test.php", and then reading a bunch of other
> files in the same directory -- then I guess that unfortunate timing
> could lead to it reading some files from releases/1.0.1 and some from
> releases/1.0.2. (Assuming that it opens the directory afresh each time --
> which can't be ruled out.)
 
Right, that's what I was trying to avoid by using $realpath_root.  I
assumed that $realpath_root was set at the beginning of the location
processing.  That way, I could be guaranteed that it would not change
for the duration of the request handling within nginx.  And since nginx
would give that value (i.e., the path with the symlinks resolved) to
the FastCGI server, the FastCGI server would be using that same path
for the whole request and wouldn't know anything about the "current"
symlink that can change at any moment.  But perhaps that's an invalid
assumption, and the path is resolved every time $realpath_root is
expanded as a variable?  I hope not, but that would be really important
to understand.

> But if "the app" involves a http request to part1.php and then a http
> request to part2.php (or: a second http request to part1.php), I don't
> think that the symlink+realpath thing will prevent those two requests
> going to different release versions.

Hmm, good point.

I'm not sure how to do a seamless web app update deploy, then.  Maybe
it's not possible without additional constraints.

I'm assuming the app is hosted on a single nginx server.  Although, I'd
be curious how this is typically solved for a multiple-server case as
well (e.g., a load balancer with multiple identical instances of the web
app running on two or more servers).  The idea is to have no downtime.

I suppose I could encode the app version in the URI (e.g.,
/my-app/1.0.2) or in the request header.  I've seen REST APIs versioned
in the URI or in the request header, but I'm not sure web apps do that.

Or I could try to ensure that my web app updates are *always* backward
compatible if they are to keep using the same URI.  I could do that for
any web apps I write, but I can't control that for any that I don't
write and am just deploying.

Another idea I previously toyed with was to deploy the web
app in a directory structure similar to the symlink+realpath
approach but without the symlink; the path to the app root is
versioned.  In the nginx config, use the versioned path to the
app root (e.g., /srv/www/my-app/releases/1.0.2).  To deploy a new
version of the app, install to a new versioned app root (e.g.,
/srv/www/my-app/releases/1.0.3), change the app root in the nginx
config, and cause nginx to reload the config.  Note that I'm
intentionally keeping the file system path versioned so that the path
changes when a new version is deployed to avoid the need to flush any
caching that might be going on at the FastCGI server or elsewhere.

Will there be downtime for a split second when the config is reloaded?
What will happen?  Will nginx refuse connections?  Will it accept
connections but just not respond while it's reloading the config?

But this approach has the same issue that you pointed out for the
symlink+realpath approach in that I don't see a way to prevent the case
where the app involves an HTTP request to part1.php that goes to one
release and then an HTTP request to part2.php that goes to the updated
release if the deploy happens at just the right (wrong) time.

What's the best strategy for deploying a new version of an app, then?
Expect that all app updates are backward compatible?  Expect that the
app passes around a version identifier with each request that the app
will use to detect when the version has changed and force the user to
log in again or something?  Version the URI?

Thanks!

Lewis

Re: Allow internal redirect to URI x, but deny external request for x?

2019-09-03 Thread J. Lewis Muir
On 09/03, J. Lewis Muir wrote:
> On 09/02, Francis Daly wrote:
> > But if "the app" involves a http request to part1.php and then a http
> > request to part2.php (or: a second http request to part1.php), I don't
> > think that the symlink+realpath thing will prevent those two requests
> > going to different release versions.
> 
> Hmm, good point.
> 
> I'm not sure how to do a seamless web app update deploy, then.  Maybe
> it's not possible without additional constraints.

After searching the web and failing to find anything addressing this
(maybe it's out there, but I couldn't find it), I'm inclined to believe
that there are roughly two choices: either the web app maintains
backward compatibility in its request API, or it doesn't.

The web app that maintains backward compatibility in its request API
will work with the symlink+realpath approach, assuming the FastCGI
server either does no caching or caches based on the file path.  (The
path-based caching works because the path changes when an app update is
deployed because the version is encoded in the path.)  Note, however,
that even for an app that maintains backward compatibility like this,
rolling back a deploy to a previous release would not work unless it
was a patch update (as defined in the Semantic Versioning scheme).  For
example, you could safely roll back from 1.0.3 to 1.0.2, but not from
1.1.0 to 1.0.3, and not from 2.0.0 to 1.2.3.

The web app that does *not* maintain backward compatibility in its
request API will *not* work with the symlink+realpath approach.  It
might work by chance depending on the timing of the deploy, the timing
of the requests, and which requests were in flight at the time of the
deploy.  Or you could orchestrate the deploy to shut down the nginx
server, wait for an amount of time deemed to be the maximum time that
should ever elapse between the "part1.php" request and the "part2.php"
request (which may be impossible to determine, or may be infinite) such
that all "part2.php" requests will happen and fail because they couldn't
connect to the nginx server, deploy the app update, and then start the
nginx server again.  This approach will never be 100% correct.

I'd love to be enlightened on other choices, but this is my
understanding as of now, and I think I'll proceed with the
symlink+realpath approach under the expectation that the web apps I
deploy maintain backward compatibility in their request API, or they
might just break for some users when I deploy an update in which case I
might choose my deploy time to be the time of least demand on average.

Regards,

Lewis
___
nginx mailing list
nginx@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx


Re: Allow internal redirect to URI x, but deny external request for x?

2019-09-03 Thread J. Lewis Muir
On 08/30, j94305 wrote:
> I've been following this, and I would take a slightly different approach.
> 
> 1. Serve all apps under /{app}/releases/{version}/{path} as you have them
> organized in the deployment structure in the file system.
> 
> 2. Forget about symbolic links and other makeshift versioning/defaulting in
> the file system.
> 
> 3. Use a keyval mapping to handle redirections (307) of
> /{app}/current/{stuff} to /{app}/releases/{currentVersion}/{stuff}, where
> the keyval mapping provides {app} => {currentVersion}. You can update an
> manage this during deployment.

Sorry, I forgot about your post!  Thank you for your suggestions!

Is this a keyval?

  https://nginx.org/en/docs/http/ngx_http_keyval_module.html

> We usually include this in a CI/CD pipeline after deployment to dynamically
> switch to the last version (using a curl request to the NGINX API). If you
> can't use keyvals, use a static map and dynamically generate that "map"
> directive's mapping. Restart NGINX to reflect changes. Keyvals let you do
> this on the fly.

Is this a static map?

  https://nginx.org/en/docs/http/ngx_http_map_module.html

And by "dynamically generate" do you mean generate the map directive as
a config file that would be included from the main config and then cause
nginx to reload its config?
 
> The major advantage of this approach is with updates. You are most likely
> going to run into issues with browser or proxy caching if you provide
> different versions of files/apps under the same path. By having a canonical
> form that respects the version structure, you are avoiding this altogether.
> Yet, you have the flexibility to run hotfixes (replace existing files in an
> existing version without creating a new one), or experimental versions
> (which won't update the "current" pointer).

Interesting.  What I was trying to do with $realpath_root, I thought
was similar to what you're describing.  However, when you mention
browser or proxy caching, then I'm not sure.  Are you suggesting
serving from a different URI for each version of the app?  If not,
then I don't understand how your proposal behaves differently than the
symlink+realpath idea.  (But this may be because you wrote this on Aug
30, and the symlink+realpath idea had not been clearly stated yet.)

> I would try to keep the complexity low.

Agreed!  However, changing a symlink (albeit with some nginx config
changes to use $realpath_root and such) is pretty simple to me, so it's
a little harder for me to see using a keyval or a static map as keeping
the complexity low.  But if I understand your proposal correctly, it
would be more straightforward in terms of not needing to use symlinks at
all and not needing to worry about $realpath_root vs. $document_root.
Instead, you just use variables, and to update the variables, you just
use the API if using a keyval, or cause nginx to reload its config if
using the static map.

Thank you for the suggestions!

Regards,

Lewis
___
nginx mailing list
nginx@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx


Re: Allow internal redirect to URI x, but deny external request for x?

2019-08-31 Thread J. Lewis Muir
On 08/31, Francis Daly wrote:
> On Sat, Aug 31, 2019 at 09:10:09AM -0500, J. Lewis Muir wrote:
> > On 08/31, Francis Daly wrote:
> 
> Hi there,
> 
> > >  * starts with /my-app/current/ -> reject
> > >  * starts with /my-app/releases/ -> reject
> 
> Actually -- those two "rejects" should not be needed.
> 
> The app probably should not be installed in the general nginx document
> root directory. The "alias" mentioning the "app/current" directory means
> that that is the only part that nginx will try to serve files from. The
> "root" mentioning the "app/current" directory means that that is the only
> part that nginx will look in (try_files) and mention to the fastcgi server
> (fastcgi_param).
> 
> So the "app/releases" directory will not be web-accessible; and the
> "app/current" directory will only be accessible by the explicit url that
> you define.
> 
> So the full config should be of the form
> 
>   location ^~ /app-url/ {
> alias /active-app-dir/;
> location ~ \.php(/|$) {
>   root /active-app-dir;
>   fastcgi_split_path_info ^/app-url(/.*?php)($|/.*);
>   try_files $fastcgi_script_name =404;
>   include fastcgi.conf;
>   fastcgi_pass unix:php.sock;
> }
>   }

I can't believe this!  Another great insight!  Thank you!  I haven't
tried it, but yes, that looks way better, and your observation about not
needing the two rejects puts to rest my incorrect belief that there was
a URI namespace problem with the app directory structure (i.e., with the
"/current/" and "/releases/" URI components).  And yes, I will move the
app root out of the nginx document root to avoid the unnecessary risk of
an nginx misconfiguration.

> Adjust regexes based on what you want.
> 
> "app-url" can be "my-app". "/active-app-dir" can be "/opt/app/releases/3"
> or "/opt/my-app/current" or anything else.
 
Got it.

> >  Previously, I had the fastcgi_split_path_info call in
> > php-fpm-realpath.conf along with the following file-exists check after
> 
> Using "realpath" should not affect nginx at all. nginx invites the
> fastcgi server to use pathname2 instead of pathname1; so the fastcgi
> server is the only thing that should care.

Hmm, I might not be understanding this.  The rationale of using
$realpath_root instead of $document_root was to make it so that a
new version of the web app could be deployed atomically at any time
by changing the "current" symlink, meaning that, for example, if the
"current" symlink were changed right in the middle of a request being
handled in PHP, it wouldn't be possible for one part of the request to
execute in PHP in the old version of the app and another part to execute
in the new version.  By using $realpath_root, the idea was to ensure
that for any given request being handled in PHP, it would execute in its
entirety in the same version of the web app.

That's why I was doing in php-fpm-realpath.conf

  if (!-f $realpath_root$fastcgi_script_name) {
return 404;
  }

and

  fastcgi_param DOCUMENT_ROOT $realpath_root;
  fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;

So, does that make sense, or am I still not understanding this?  I don't
know what you mean by "nginx invites the fastcgi server to use pathname2
instead of pathname1."  What are pathname1 and pathname2?
 
> > For my current app, it doesn't use those URIs, so it's not a problem,
> > but as a general scheme, it's not perfect.  I think one solution would
> > be to move the app root directory to a different name so that it can't
> > conflict.  For example, have it live at
> > 
> >   /srv/www/my-app-deployment
> 
> As above -- that shouldn't matter. If the app is not deployed in the web
> server document root, only the specific alias/root directory is accessible,
> and the entire url-space below that is available.
 
Understood.

> (And you can have one url prefix /my-app/, and a separate url prefix
> /my-app-prev/, which uses the next most recent version. Restrict access
> to that location{} to your source IP address, and you can do regression
> testing between the two.)
> 
> > or something like that.  Then I could just return a 404 for any request
> > on that, e.g.:
> > 
> >   location ^~ /my-app-deployment/ {
> > return 404;
> >   }
> 
> If you don't want nginx to serve content from the my-app-deployment
> directory, it is probably easier for it to be somewhere other than
> /srv/www.
> 
> It is hard to misconfigure nginx in that case.

Agreed; I will move it out of there.

Thank you!

Lewis
___
nginx mailing list
nginx@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx


Re: Allow internal redirect to URI x, but deny external request for x?

2019-09-04 Thread J. Lewis Muir
On 09/04, Jürgen Wagner (DVT) wrote:
> This is the effect you get by having the HTTP equivalent of a symbolic link
> in the NGINX (visible to the browser), not in the file system (which is
> opaque to users). The file system link will (over time) serve different
> contents under the same URL, so in fact, addressing changes with every
> deployment. The suggested approach keeps URL addressing constant and just
> changes the entry pointer on a new deployment.
> 
> I agree that this is not the solution that first comes to ones mind, but it
> does solve a number of nasty versioning issues we have run into over time.
> Your mileage may vary :-)

Thank you for the further explanation!  Indeed it seems like a
compelling solution!

What about web search engine indexing; do you do anything to avoid
search engines indexing the versioned URLs?  I suppose that if you only
publish the unversioned entry-point URLs, search engines will respect
that?  (Maybe wishful thinking.)  Or will they follow a 307 redirect and
index those URLs?

For example, it would seem undesirable to do a web search for "my-app"
and get a list of, say, the "index.php" for each version (e.g.,
"/my-app/releases/1.0.0/index.php", "/my-app/releases/1.0.1/index.php",
"/my-app/releases/1.0.2/index.php", etc.).

So, perhaps you use a "/robots.txt" to exclude "/my-app/releases/"?

DuckDuckGo seems to respect "/robots.txt" for controlling what gets indexed

  https://help.duckduckgo.com/duckduckgo-help-pages/results/duckduckbot/

But Google says "/robots.txt" is not for keeping a web page out of their
index

  https://support.google.com/webmasters/answer/6062608

and that you should use a "noindex" directive instead.

So maybe you use both a "/robots.txt" and the robots meta tag with
content="noindex" in the served resources or perhaps "X-Robots-Tag:
noindex" in the HTTP header response?

Regards,

Lewis
___
nginx mailing list
nginx@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx


Re: Allow internal redirect to URI x, but deny external request for x?

2019-09-04 Thread J. Lewis Muir
On 09/04, Jürgen Wagner (DVT) wrote:
> Now, you want to be able to say what is the "current" version and reflect
> this in the URL namespace as well. In the file system, that's a symbolic
> link. In the URL namespace of NGINX, that could be a redirection (status
> code 307). Both approaches would work. For the redirection you need a
> location

Got it!  Thank you!  So this approach versions the URI.

> /{app}/current
> 
> which redirects any request for paths starting with this to the actual
> version you want to serve:
> 
> /{app}/releases/{latestVersion}
> 
> This can be achieved with a dynamically-generated stub you include in a
> "map" directive (requiring NGINX reload in case of changes) or a "keyval"
> map that can be changed via the NGINX API on the fly as you need it (not
> requiring reloads). The mapping will get the app name and determine the path
> of the latest version where the redirection should go to.

Got it.

> The issue about browser and proxy caches: if over time you serve multiple
> versions of an app from the same URLs, browsers (or proxies) may consider
> their cached version of some files current enough not to feel motivated
> refetching them. In some cases, you would end up with some files loaded into
> the browser being of an old version, some already a newer one. This can be
> avoided entirely by giving each version of the app a distinct canonical
> prefix that will never be re-used. The "current" redirection is simply a
> pointer to the right location for the latest version, but as it is an
> external redirection, the browser will ultimately load the app from the
> official "releases" path with the version number in it.

Wouldn't the 307 redirection mean that for *every* request, nginx has to
issue a 307 and then the client has to request the versioned URI which
nginx then has to server; so a double-request for every resource?

I agree that this approach solves the browser and proxy cache problem,
though.

How does this solve the request-chain problem where "part1.php" executes
in one version of the app, but then "part2.php" executes in the updated
version because the updated version was deployed in between?  I presume
it doesn't, which is OK, but I want to make sure I understand.

Do you know of any mainstream web apps that are deployed this way
(i.e., 307 redirect to versioned URI)?

Thank you!

Lewis
___
nginx mailing list
nginx@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx


Why 301 permanent redirect with appended slash?

2019-07-30 Thread J. Lewis Muir
Hello, all!

I have a minimal nginx.conf with one server block that sets the root
directory and one location with a prefix string of "/foo/", and for a
request of "/foo", it returns a 301 permanent redirect to "/foo/".  Why?
I expected it to return 404 or similar.  I also tried a prefix string of
"/foo", but that also results in the same 301.

Here's the server block (entire nginx.conf at end of message):


server {
listen  127.0.0.1:80;
listen  [::1]:80;
server_name localhost "" 127.0.0.1 [::1];
root/srv/www/localhost;

location /foo/ {
}
}


And here's the curl invocation:


$ curl -I 'http://localhost/foo'
HTTP/1.1 301 Moved Permanently
Server: nginx/1.12.2
Date: Tue, 30 Jul 2019 21:54:44 GMT
Content-Type: text/html
Content-Length: 185
Location: http://localhost/foo/
Connection: keep-alive



I've read in

  https://nginx.org/en/docs/http/ngx_http_core_module.html#location

where it says

  If a location is defined by a prefix string that ends with the
  slash character, and requests are processed by one of proxy_pass,
  fastcgi_pass, uwsgi_pass, scgi_pass, memcached_pass, or grpc_pass,
  then the special processing is performed. In response to a request
  with URI equal to this string, but without the trailing slash, a
  permanent redirect with the code 301 will be returned to the requested
  URI with the slash appended.

But in my case, I don't believe the request is being processed by any of
those *_pass directives.

Thank you!

Lewis

 Complete nginx.conf 
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

events {
worker_connections 1024;
}

http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

access_log /var/log/nginx/access.log main;

sendfileon;
tcp_nopush  on;
tcp_nodelay on;
keepalive_timeout   65;
types_hash_max_size 2048;

include  /etc/nginx/mime.types;
default_type application/octet-stream;

server {
listen  127.0.0.1:80;
listen  [::1]:80;
server_name localhost "" 127.0.0.1 [::1];
root/srv/www/localhost;

location /foo/ {
}
}
}

___
nginx mailing list
nginx@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx


Implicit root location?

2019-07-30 Thread J. Lewis Muir
Hello, all!

I have a minimal nginx.conf with one server block that sets the root
directory but has *no* location directives, yet for a request of "/", it
serves "/index.html".  Why?  With no locations specified, I expected it
to return 404 or similar for any request.

Here's the server block (entire nginx.conf at end of message):


server {
listen  127.0.0.1:80;
listen  [::1]:80;
server_name localhost "" 127.0.0.1 [::1];
root/srv/www/localhost;
}


Here's the contents of /srv/www/localhost:


$ ls -al /srv/www/localhost
total 4
drwxr-xr-x. 2 root root  24 Jul 30 15:50 .
drwxr-xr-x. 3 root root  23 Jun 26 21:34 ..
-rw-r--r--. 1 root root 140 Jun 26 22:22 index.html


And here's the curl invocation:


$ curl 'http://localhost/'




localhost


localhost




I know that the default index directive is


index index.html;


That explains how it knows to try index.html, but what makes it try
the root when there are no location directives?  Is there an implicit
location directive?

There is no default listed for the location directive:

  https://nginx.org/en/docs/http/ngx_http_core_module.html#location

And I couldn't find this behavior stated in "How nginx processes a
request:"

  https://nginx.org/en/docs/http/request_processing.html

Thank you!

Lewis

 Complete nginx.conf 
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

events {
worker_connections 1024;
}

http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

access_log /var/log/nginx/access.log main;

sendfileon;
tcp_nopush  on;
tcp_nodelay on;
keepalive_timeout   65;
types_hash_max_size 2048;

include  /etc/nginx/mime.types;
default_type application/octet-stream;

server {
listen  127.0.0.1:80;
listen  [::1]:80;
server_name localhost "" 127.0.0.1 [::1];
root/srv/www/localhost;
}
}

___
nginx mailing list
nginx@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx


Re: Why 301 permanent redirect with appended slash?

2019-07-31 Thread J. Lewis Muir
On 07/31, Francis Daly wrote:
> On Tue, Jul 30, 2019 at 05:12:01PM -0500, J. Lewis Muir wrote:
> 
> Hi there,
> 
> > I have a minimal nginx.conf with one server block that sets the root
> > directory and one location with a prefix string of "/foo/", and for a
> > request of "/foo", it returns a 301 permanent redirect to "/foo/".  Why?
> > I expected it to return 404 or similar.  I also tried a prefix string of
> > "/foo", but that also results in the same 301.
> 
> I get a 301 if the directory "foo" exists; and a 404 if it does not.
> 
> Do you get something different?
 
No, I get exactly what you described.  Sorry, I failed to state in my
initial email that the directory "foo" exists (as well as the file
"foo/index.html" which probably doesn't matter here).

> > But in my case, I don't believe the request is being processed by any of
> > those *_pass directives.
> 
> If you request "/directory", and "directory" exists, then the filesystem
> handler will issue a 301 to "/directory/", which I think is what you
> are seeing.
 
Indeed.

> As in: your request for "/foo" does not match any location{}, and so is
> handled at server-level, which runs the filesystem handler and returns
> 200 if the file "foo" exists, 301 if the directory "foo" exists, and
> 404 otherwise.

Yes, thank you very much for the explanation!  That all makes sense.
I couldn't find this behavior documented anywhere; is it documented
somewhere that I've missed?

> Change your config to be
> 
>   location /foo/ { return 200 "location /foo/\n"; }
> 
> and you will see when that location is used.

Nice; that's useful for testing!

> If your config has
> 
>   location /foo {}
> 
> then a similar consideration applies, except the request "/foo" is now
> handled in that location which, per the above configuration, uses the
> filesystem handler.

Understood.

Thanks!

Lewis
___
nginx mailing list
nginx@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx


Re: RHEL Yum repo instructions don't work on RHEL 7

2019-10-02 Thread J. Lewis Muir
On 10/02, Konstantin Pavlov wrote:
> Yep, that seems like the easiest solution.  I've put Client, Workstation
> and Server symlinks for respectable major releases to both stable and
> mainline repos - I'd appreciate if you try again and let me know if that
> fixes the issue for you.

I confirm that using the $releasever Yum variable in the baseurl key
value as given in the nginx documentation works now.  Thanks!

Lewis
___
nginx mailing list
nginx@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx


RHEL Yum repo instructions don't work on RHEL 7

2019-10-01 Thread J. Lewis Muir
Hello!

I'd like to report a problem with the RHEL/CentOS instructions at

  https://nginx.org/en/linux_packages.html#RHEL-CentOS

They don't work on RHEL 7.  When I attempt to install the nginx package
as root with

  yum install nginx

I get an HTTP 404 error:

  http://nginx.org/packages/centos/7Workstation/x86_64/repodata/repomd.xml: 
[Errno 14] HTTP Error 404 - Not Found

The problem seems to be the use of the $releasever Yum variable in the
baseurl key of the nginx.repo spec:

  baseurl=http://nginx.org/packages/centos/$releasever/$basearch/

On my RHEL 7 machine, that variable is evaluating to

  7Workstation

Looking at

  http://nginx.org/packages/centos/

the nginx repo is expecting $releasever to evaluate to just the release
number without the variant/edition text.  So, if in nginx.repo I change

  baseurl=http://nginx.org/packages/centos/$releasever/$basearch/

to

  baseurl=http://nginx.org/packages/centos/7/$basearch/

it works.

There's more info at

  https://access.redhat.com/solutions/1256473

I have a default

  /etc/yum.conf

and it does not have a line that sets the distroverpkg key.

I think something in the documentation or the nginx repo needs to be
changed.

One fix would be to list the release version number explicitly in the
baseurl key value like I did above.  And just say in the documentation
that you have to set the number to the version that matches your
installed version of RHEL/CentOS.

Another fix would be to add symlinks or redirects or whatever at

  http://nginx.org/packages/centos/

that would make the $releasever work.  For example:

  7Workstation -> 7
  7Server -> 7

I don't know whether there are other release variants/editions.  At some
point, "Client" was a variant/edition, I think, but it seems like these
are changing a fair amount from major release to major release, so it
may be a moving target.

And maybe there are other better fixes that I'm not aware of.

Thanks!

Lewis
___
nginx mailing list
nginx@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx


Re: How to do location /test/place?id=2

2019-10-18 Thread J. Lewis Muir
On 10/18, P.V.Anthony wrote:
> On 18/10/19 5:26 am, Jeff Dyke wrote:
> > I know this is not an answer to your question, but it begs another,
> > mainly due to the if statement.  How many of these are you going to
> > have? https://www.nginx.com/resources/wiki/start/topics/depth/ifisevil/
> > 
> > You've likely considered this, but if not wanted to throw it out there.
> > Even if you are moving domains, could you create a separate route that
> > you could key off rather than arg_id?
> 
> Oh no. I was not aware of the "if" danger. Thank you for bringing that up.
> 
> I am not able to change the application. Is there another way without using
> "if"?

The "if" behavior is weird, so it's good to avoid it if you can, but
sometimes it really is the only way to do something.  And at the top of
that "If Is Evil" page it says:

  The only 100% safe things which may be done inside "if" in a location
  context are:

  * return ...;
  * rewrite ... last;

And in your example, you were doing a return inside an "if" which is
noted as being safe in a location context.

Lewis
___
nginx mailing list
nginx@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx


Static content and Front Controller pattern under same base URI

2019-10-17 Thread J. Lewis Muir
Hello, nginxers!

What's the best way to server static content as well as dynamic content
that uses the Front Controller pattern under the same base URI?

I'm dealing with a web app partially written in PHP that expects to
serve static content as well as dynamic PHP content, using the Front
Controller pattern, both under the same base URI.  It expects to serve
static content if the file or directory exists.  But if the file or
directory does not exist, it expects request rewriting according to the
Front Controller pattern like this:


Request   Rewritten Request

/foo/ /foo/index.php
/foo/bar  /foo/index.php/bar
/foo/bar/baz  /foo/index.php/bar/baz


The following config works correctly:


location = /foo { return 301 $uri/$is_args$args; }

location /foo/ {
  alias /srv/www/localhost/app/foo/1.0.0/;
  index index.php;
  try_files $uri $uri/ @foo_front_controller;
}

location ~ ^/foo/.*?[^/]\.php(?:/|$) {
  error_page 418 = @foo_front_controller;
  return 418;
}

location @foo_front_controller {
  rewrite ^/foo(?!/index\.php)(/.+)$ /foo/index.php$1 last;
  root /srv/www/localhost/app/foo/1.0.0;
  fastcgi_split_path_info ^/foo(/.+?\.php)(/.*)?$;
  include php-fpm.conf;
  fastcgi_param REQUEST_URI $fastcgi_script_name$fastcgi_path_info$is_args$args;
}


I'm not a big fan of the location that sets the 418 error_page to the
@foo_front_controller named location, but I don't know of any other way
to essentially do a "return @foo_front_controller".  Is there a better
way?

The whole point of the @foo_front_controller named location is so that
I can have one block that defines the Front Controller logic, and then
use it in both the "/foo/" location block in the try_files directive as
the fallback for when the file or directory does not exist and in the
location block right below it for requests that are for .php files.

Is this a good approach, or is there a better way?

Example content and requests are shown below.

Thank you!

Lewis


$ ls -al /srv/www/localhost/app/foo/1.0.0
total 8
drwxr-xr-x 2 root root  38 Oct 17 17:04 .
drwxr-xr-x 3 root root  19 Oct 17 16:37 ..
-rw-r--r-- 1 root root 209 Oct 17 17:04 index.php
-rw-r--r-- 1 root root  21 Oct 17 16:44 msg.txt
$ cat /srv/www/localhost/app/foo/1.0.0/index.php



hello, world


hello, world' . "\n"; ?>
REQUEST_URI: ' . $_SERVER['REQUEST_URI'] . '' . "\n"; ?>


$ cat /srv/www/localhost/app/foo/1.0.0/msg.txt
Use the Force, Luke.
$ curl http://localhost/foo/



hello, world


hello, world
REQUEST_URI: /index.php


$ curl http://localhost/foo/index.php



hello, world


hello, world
REQUEST_URI: /index.php


$ curl http://localhost/foo/bar



hello, world


hello, world
REQUEST_URI: /index.php/bar


$ curl http://localhost/foo/bar/baz



hello, world


hello, world
REQUEST_URI: /index.php/bar/baz


$ curl http://localhost/foo/msg.txt
Use the Force, Luke.
$ curl http://localhost/foo/msg-quux.txt



hello, world


hello, world
REQUEST_URI: /index.php/msg-quux.txt



___
nginx mailing list
nginx@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx


Re: IOS keep asking password with nginx auth_basic

2019-10-17 Thread J. Lewis Muir
On 10/17, tiendungitd wrote:
> any idea about this issue?

Are you serving over HTTPS?

Are you positive that you are *not* serving any content over HTTP from
HTTPS?

Can you create an MCVE (minimal, complete, and verifiable example) for a
".txt" file over HTTP?  For a ".txt" file over HTTPS?  For a ".ivp" file
over HTTP?  For a ".ivp" file over HTTPS?

In your Pastebin access log, I see occurrences of "$1" in your requests.
Is that intentional, or is that a bug?

What Content-Type header field are you sending in your response to the
request for a resource ending in ".ivp"?

Can you try adding a user name and password for the website on the iPad
under Settings > Passwords & Accounts > Website & App Passwords?

What happens if you try Firefox and Google Chrome on the iPad?  Do they
work?

Lewis
___
nginx mailing list
nginx@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx


Re: How to do location /test/place?id=2

2019-10-17 Thread J. Lewis Muir
On 10/18, P.V.Anthony wrote:
> Currently have the following url,
> 
> https://old.example.com/test/place?id=1
> https://old.example.com/test/place?id=2
> https://old.example.com/test/place?id=3
> 
> Need to redirect only id=2 to another url.
> 
> Did the following and it works for id=2. Need id=1 and id=3 to continue
> normally without change.
> 
> location = /test/place {
>  if ($args = "id=2") {
>return 301 https://new.example.com/test/place?$args;
> }
> }

You might want to use $arg_id here (i.e., the $arg_ variable for
the  argument).  Otherwise, it won't work if any other arguments
are given.

> Or is there a way to do the following? That would be ideal.
> 
> location = /test/place?id=2 {
> return 301 https://new.example.com/test/place?id=2
> }

I don't think that's allowed.

> Unfortunately the above does not work. What is missing?

What doesn't work?

I would think your

> location = /test/place {

block would work, although not as shown, but I assume you just left
out the part that normally handles the request.  It would handle the
requests for id=1 and id=3 as before, and it's just the id=2 case that
gets redirected, right?

Lewis
___
nginx mailing list
nginx@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx


Re: PR_END_OF_FILE_ERROR after kernel update

2019-10-04 Thread J. Lewis Muir
On 10/04, Ken Wright wrote:
> Okay, I rebooted the server then tried testing the cert.  SSL Labs
> reports no secure protocols supported.  Once again, I'm lost.  I know I
> set up the server to use LetsEncrypt certs, and I've checked them;
> they're there.  I tried disabling the server's firewall and testing
> again, only to get the same message.

Can you check your nginx server logs?

Can you check that the same content can be served over plain HTTP?

Can you check that all of your nginx and Let's Encrypt configuration
files are still intact?

Can you check that your file systems are not full?

Can you share a curl command that shows your output that others could
use to compare to your output?

Lewis
___
nginx mailing list
nginx@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx