7

(* As some comments recommended, I removed index.ejs and use index.html in the project by following this answer. So I have adjusted my OP *)

I develop in Mac with apache a MEAN-stack application that can be requested by https://localhost:3000/#/home. In production with a nginx server, the application can be requested by https://www.myapp.io/#/home. The fragment-identifier # is needed in all cases because of angular ui-router.

So I wanted to make pretty url without # (eg, https://www.myapp.io/home, https://localhost:3000/home) work. I have done the following:

1) added $locationProvider.html5Mode(true); $locationProvider.hashPrefix('') in app.config(['$stateProvider'....

2) added <base href="/" /> in index.html

As a result, https://localhost:3000/#/home changes automatically to https://localhost:3000/home in the browser bar, similarly for https://www.myapp.io/#/home.

However, directly entering https://localhost:3000/home or https://www.myapp.io/home in the browser will raise an error (I don't know how to turn previous <h1><%= message %></h1><h2><%= error.status %></h2><pre><%= error.stack %></pre> in error.ejs to error.html, so I don't have more details).

So now, the goal is to make https://localhost:3000/home and https://www.myapp.io/home work.

By following this thread, I added the follows to app.js:

app.use('/js', express.static(__dirname + '/js'));
app.use('/dist', express.static(__dirname + '/../dist'));
app.use('/css', express.static(__dirname + '/css'));
app.use('/partials', express.static(__dirname + '/partials'));    
app.all('/*', function(req, res, next) {
    res.sendFile('index.html', { root: __dirname });
});

And in apache of mac, here is my httpd-vhosts.conf, after restarting apache, https://localhost:3000/home still returns an error.

<VirtualHost *:443>
    ServerName localhost
    DocumentRoot "/Users/SoftTimur"

    SSLEngine on
    SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
    SSLCertificateFile /etc/apache2/ssl/localhost.crt
    SSLCertificateKeyFile /etc/apache2/ssl/localhost.key

    <Directory "/Users/SoftTimur">
        RewriteEngine on

        # Don't rewrite files or directories
        RewriteCond %{REQUEST_FILENAME} -f [OR]
        RewriteCond %{REQUEST_FILENAME} -d
        RewriteRule ^ - [L]

        # Rewrite everything else to index.html to allow html5 state links
        RewriteRule ^ index.html [L]

        Options Indexes FollowSymLinks
        AllowOverride All
        Order allow,deny
        Allow from all
        Require all granted
    </Directory>
</VirtualHost>

In production, here is the nginx server block. After restarting nginx, https://www.myapp.io/home still returns an error.

server {
    listen 443 ssl;

    server_name myapp.io www.myapp.io;

    ssl_certificate /etc/letsencrypt/live/myapp.io/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/myapp.io/privkey.pem;

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_dhparam /etc/ssl/certs/dhparam.pem;
    ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:EC$
    ssl_session_timeout 1d;
    ssl_stapling on;
    ssl_stapling_verify on;
    add_header Strict-Transport-Security max-age=15768000;

    index index.html;

    root /opt/myapp

    location / {
        try_files $uri $uri/ /index.html;
    }

    location ~ /.well-known {
        allow all;
    }

    location / {
        proxy_set_header    Host                $host;
        proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
        proxy_set_header    X-Forwarded-Proto   $scheme;
        proxy_set_header    Accept-Encoding     "";
        proxy_set_header    Proxy               "";
        proxy_pass          https://127.0.0.1:3000;

        # These three lines added as per https://github.com/socketio/socket.io/issues/1942 to remove sock$

        proxy_http_version 1.1;
        proxy_set_header   Upgrade $http_upgrade;
        proxy_set_header   Connection "upgrade";
    }
}

Could anyone help?

Community
  • 1
  • 1
SoftTimur
  • 5,630
  • 38
  • 140
  • 292

2 Answers2

1

I think the better question you should be asking yourself is why don't you have index.html? Perhaps I've been asleep for too long, but browsers aren't really capable of executing JavaScript by itself on a webpage, without an underlying DOM from an HTML document.

Once you've got that figured out, you might as well succeed with the official configuration suggestion from angular-ui on GitHub.

cnst
  • 25,870
  • 6
  • 90
  • 122
  • I have `index.ejs` rather than `index.html`. But I'm not sure how to modify the suggestion from angular-ui on GitHub... – SoftTimur Apr 21 '17 at 05:30
  • What's in index.ejs? Perhaps not having index.html is the root cause? – cnst Apr 21 '17 at 05:33
  • This is [ejs](https://www.npmjs.com/package/ejs). When I created this application, I followed some examples where `index.ejs` is used (eg, [this one](https://scotch.io/tutorials/use-ejs-to-template-your-node-application)). I just realised that I don't really use the feature of `ejs`, so I would change that to `index.html`, and see what happens, I will test it tomorrow and update... – SoftTimur Apr 21 '17 at 05:58
  • 1
    @SoftTimur, I think you're missing how `ejs` works. I'm pretty sure it requires either HTML bootstrapping (e.g., after all, you must have some sort of `index.html`, with something like ``), or processing on the server (e.g., with nodejs and/or friends). – cnst Apr 22 '17 at 02:13
0

Remove the nginx configuration you added. This can be achieved by performing the following:

There are 2 things that need to be done.

  1. Configuring $locationProvider

  2. Setting our base for relative links

See the following link for more detailed instructions on how to accomplish this: Pretty URLs in AngularJS: Removing the #

For Angular 1.6 you will also need to change the hashPrefix:

appModule.config(['$locationProvider', function($locationProvider) {
$locationProvider.html5Mode(true);
$locationProvider.hashPrefix('');
}]);

I know in your question you stated that you had already done these two steps, but if you follow this tutorial perfectly it will work as I have tested this on my own Angular application (which is also hosted thru nginx).

To go with the server configuration route, I would recommend following this link: AngularJS with Pretty URLs: Removing the # in Amazon S3

Additionally, here is the actual server configuration changes to make.

And lastly, I think you're mistaken with regard to how ejs works. It requires either HTML bootstrapping (after all, you must have some sort of index.html, with something like <script src="https://npmcdn.com/ejs/ejs.min.js"></script>), or processing on the server (e.g., with nodejs and/or friends).

Community
  • 1
  • 1
lax1089
  • 3,403
  • 3
  • 17
  • 37
  • My steps 1) and 2) are what your link describes, they are not enough. – SoftTimur Apr 15 '17 at 14:41
  • What version of Angular are you using? – lax1089 Apr 15 '17 at 14:48
  • Which link (`Angular 1.6`) are you using? – SoftTimur Apr 15 '17 at 14:52
  • `https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js`. Those two steps remove the `#` from the url (change eg, `https://.../#/new` to `https://.../new`), but it does not treat the new url (eg, `https://.../new`). That's why in a php server, they use also [.htaccess](https://ngmilk.rocks/2015/03/09/angularjs-html5-mode-or-pretty-urls-on-apache-using-htaccess/) on top of those two steps. – SoftTimur Apr 15 '17 at 14:58
  • I'm using Angular 1.5 in my test application. I use Angular-CLI so I do not provide an actual link, just list the version I want in the config file. See updated answer for server config route, that should accomplish what you want – lax1089 Apr 15 '17 at 15:12
  • What puzzles me (and this question is about) is the server config. I know that github link... as I said, I don't have `index.html` in my application, I don't know how to adapt that link to my application, and I would appreciate a more precise answer for that... – SoftTimur Apr 15 '17 at 15:16
  • Instead of index.html have you tried using index.ejs? – lax1089 Apr 15 '17 at 15:19
  • I tried... I think I need to know what I am doing and should do rather than just trying... – SoftTimur Apr 15 '17 at 15:20