<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    <p><font size="+1"><font face="Tahoma">Hi Lewis,</font></font></p>
    <p><font size="+1"><font face="Tahoma">  the idea is to have a
          deployment process that places apps or whatever artifacts
          always in a certain distinct place that is determined once at
          deployment time. This will determine the address where you can
          reach the app in the namespace of NGINX. So, if the convention
          is to place an app in a directory</font></font></p>
    <p><font size="+1"><font face="Tahoma">{webroot}/{app}/releases/{version}/...</font></font></p>
    <p><font size="+1"><font face="Tahoma">served as</font></font></p>
    <p><font size="+1"><font face="Tahoma">https://{server}/{app}/releases/{version}/...</font></font></p>
    <p><font size="+1"><font face="Tahoma">you would have a single,
          official URL prefix for each app version to be served from.</font></font></p>
    <p><font size="+1"><font face="Tahoma">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</font></font></p>
    <p><font size="+1"><font face="Tahoma">/{app}/current</font></font></p>
    <p><font size="+1"><font face="Tahoma">which redirects any request
          for paths starting with this to the actual version you want to
          serve:</font></font></p>
    <p><font size="+1"><font face="Tahoma"><font size="+1"><font
              face="Tahoma">/{app}/releases/{latestVersion}</font></font></font></font></p>
    <p><font size="+1"><font face="Tahoma"><font size="+1"><font
              face="Tahoma">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.<br>
            </font></font></font></font></p>
    <p><font size="+1"><font face="Tahoma"><font size="+1"><font
              face="Tahoma">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.</font></font></font></font></p>
    <p><font size="+1"><font face="Tahoma"><font size="+1"><font
              face="Tahoma">Cheers,</font></font></font></font></p>
    <p><font size="+1"><font face="Tahoma"><font size="+1"><font
              face="Tahoma">--j.<br>
            </font></font></font></font></p>
    <p><font size="+1"><font face="Tahoma"><br>
        </font></font></p>
    <p><font size="+1"><font face="Tahoma"><br>
        </font></font></p>
    On 04.09.2019 05:29, J. Lewis Muir wrote:<br>
    <blockquote type="cite"
      cite="mid:20190904032950.ftj3l6wvi6k3ghqf@mink.imca.aps.anl.gov">
      <pre class="moz-quote-pre" wrap="">On 08/30, j94305 wrote:
</pre>
      <blockquote type="cite">
        <pre class="moz-quote-pre" wrap="">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.
</pre>
      </blockquote>
      <pre class="moz-quote-pre" wrap="">
Sorry, I forgot about your post!  Thank you for your suggestions!

Is this a keyval?

  <a class="moz-txt-link-freetext" href="https://nginx.org/en/docs/http/ngx_http_keyval_module.html">https://nginx.org/en/docs/http/ngx_http_keyval_module.html</a>

</pre>
      <blockquote type="cite">
        <pre class="moz-quote-pre" wrap="">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.
</pre>
      </blockquote>
      <pre class="moz-quote-pre" wrap="">
Is this a static map?

  <a class="moz-txt-link-freetext" href="https://nginx.org/en/docs/http/ngx_http_map_module.html">https://nginx.org/en/docs/http/ngx_http_map_module.html</a>

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?
 
</pre>
      <blockquote type="cite">
        <pre class="moz-quote-pre" wrap="">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).
</pre>
      </blockquote>
      <pre class="moz-quote-pre" wrap="">
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.)

</pre>
      <blockquote type="cite">
        <pre class="moz-quote-pre" wrap="">I would try to keep the complexity low.
</pre>
      </blockquote>
      <pre class="moz-quote-pre" wrap="">
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
<a class="moz-txt-link-abbreviated" href="mailto:nginx@nginx.org">nginx@nginx.org</a>
<a class="moz-txt-link-freetext" href="http://mailman.nginx.org/mailman/listinfo/nginx">http://mailman.nginx.org/mailman/listinfo/nginx</a>
</pre>
    </blockquote>
  </body>
</html>