简体   繁体   中英

IIS URL Rewrite in AngularJS with Node for Angular HTML5 Mode

I have an AngularJS app built on top of Node.JS that is hosted in Azure (IIS) and uses HTML5 mode. In situations where I don't use Node.JS and just use AngularJS with IIS I can rewrite URLs so that a page refresh doesn't cause a 404 error using the following rule in the IIS Web.config:

<rule name="AngularJSHTML5Mode" stopProcessing="true">
      <match url=".*"/>
      <conditions logicalGrouping="MatchAll">
        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true"/>
        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true"/>
        <add input="{REQUEST_URI}" pattern="^/(api)" negate="true"/>
      </conditions>
      <action type="Rewrite" url="/"/>
</rule>

However, when using Angular on top of Node.js (with ExpressJS) I get an error such as "Cannot GET /myroute" on page refresh, even with the above rule in IIS. Is there something I need to configure in Server.js or a different rule in Web.config.

Here is what I have in Express at the moment. I am using Express 4:

// Initialize Express App
var app = express();

var listener = app.listen(1337, function () {
    console.log('Listening on port ' + listener.address().port); //Listening on port 1337
});

app.use(express.static(__dirname + "/public"));

I understand that page refreshes shouldn't happen in a SPA as a matter of practice, but they do, and I need to account for this.

I've experimented and this is what has worked for me:

web.config (site.js is the entry point to my node app)

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <httpErrors existingResponse="PassThrough" />

        <iisnode nodeProcessCommandLine="&quot;c:\program files\nodejs\node.exe&quot;" watchedFiles="*.js" 
      interceptor="&quot;%programfiles%\iisnode\interceptor.js&quot;" promoteServerVars="LOGON_USER"/>
        <handlers>
            <add name="iisnode" path="site.js" verb="*" modules="iisnode" />
        </handlers>

        <rewrite>
            <rules>
                <clear />
                <rule name="default">
                    <match url="/*" />
                    <conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
                    <action type="Rewrite" url="site.js" />
                </rule>
            </rules>
        </rewrite>

        <security>
            <requestFiltering>
                <hiddenSegments>
                    <add segment="node_modules" />
                </hiddenSegments>
            </requestFiltering>
        </security>
    </system.webServer>
</configuration>

static file server in express + url rewrite

app.use(express.static(clientDir));

// for SPA
app.get('/*', function(req,res, next){
    res.format({
        html: function(){
            res.sendFile(path.join(clientDir, 'index.html'));
        },
        json: function(){
            next();
        }
    });
});

//routes...

I have also tried to implement url rewrite with virtual app in iis. This doesn't work. Instead, I had to configure a path within my node module to strip the leading part of the route.

However, you can have iis serve the static files once your app has bootstrapped.

Upon further digging, I didn't need the Web config. I have this in my server.js to institute the connection to the Angular index file:

var app = express();

app.use(express.static(__dirname + "/public"));


var listener = app.listen(1337, function () {
    console.log('Listening on port ' + listener.address().port); //Listening on port 1337
});

This part is critical, at the end of all your GETs, POSTs, etc. I added this as the last function. It needs to be last since it is a catch all and if you put it before a GET or POST function it won't see it as Express but a broken Angular route, and if your App.js is configured correctly, will route to the homepage (not desired):

// Placed at end for routing non-Express calls/AngularJS refreshes
app.use('/*', function (req, res) {
    res.sendFile(__dirname + '/public/index.html');
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM