IIS returns 500 when Node app returns a 4xx
Asked Answered
M

5

5

I have also asked this on the iisnode github project

I am using IISNode via a Windows Azure Website.

If my Node app returns a 2xx status code (200, 201, etc), then all is well and works as expected.

if my Node app returns a 4xx status code, for example: response.send(404, "not found") (I am using Restify) then I get a 500 sent to the client and the body is simply "The page cannot be displayed because an internal server error has occurred."

If I do azure site log tail <sitename>, then when the 500 gets sent to the client, the log contains HTML of a 404.

...
<body> 
<div id="content"> 
<div class="content-container"> 
<h3>HTTP Error 404.0 - Not Found</h3> 
<h4>The resource you are looking for has been removed, had its name changed,
or is temporarily unavailable.</h4> 
</div> 
...

I really just want IISNode/IIS to take my 404 and send it on down to the client. This is also true of 401s, 409s, etc. They all cause a 500 to get sent instead.

I have tried <customErrors mode="off" /> and <httpErrors existingResponse="passThrough" /> in my web.config to no avail. Here is my web.config now:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.web>
    <customErrors mode="off" />
  </system.web>
  <system.webServer>         
    <httpErrors existingResponse="PassThrough" />
    <staticContent>
       <mimeMap fileExtension=".svg" mimeType="image/svg+xml" />
       <mimeMap fileExtension=".ico" mimeType="image/x-icon" />
    </staticContent>
    <handlers>
      <add name="iisnode" path="server.js" verb="*" modules="iisnode"/>
    </handlers>
    <rewrite>
      <rules>
        <rule name="DynamicContent">
           <conditions>
            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True"/>
           </conditions>
           <action type="Rewrite" url="server.js"/>
           <match url="/*" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>

For what it's worth, I can't get IISnode to do anything but return 200s from my node app. Trying to get IIS to serve my static files, enable node-inspector, or really any of the more interesting IISNode features cause a 500 for me. No idea why, and would love to get past it!

Similar StackOverflow Questions

this question is pretty much exactly my problem. Except that <httpErrors existingResponse="PassThrough" /> does not work for me. I feel like I have something more fundamentally wrong with my IISNode setup, so if anyone has any ideas on things to try I'm all ears.

Misgovern answered 21/3, 2014 at 3:28 Comment(3)
I have an IISNode app running without the issue and the only major difference between my web.config and yours is I don't have the <match url="/*" /> rule in the DynamicContent, does removing it change anything for you? I also don't have the httpErrors section.Stelle
I took out the match tag and that didn't change anything. I also tried creating a fresh website and deploying to that with the same results.Misgovern
I have a handful of other things I plan to try this weekend. If I find a solution, I'll update here (and github)Misgovern
A
3

for some reason the following section in your config is causing this issue:

<staticContent>
    <mimeMap fileExtension=".svg" mimeType="image/svg+xml" />
    <mimeMap fileExtension=".ico" mimeType="image/x-icon" />
</staticContent>

As a workaround, remove this section if possible and retry. I will investigate why this section is causing this issue.

Arabeila answered 21/3, 2014 at 19:45 Comment(2)
I'll give this a shot tonight when I get home. Not sure what to do without those mimemaps though.Misgovern
This does work, and I appear to no longer need staticContent anyway. I'm not sure why that is. But since everything is working, not going to question too much now :) Thanks Ranjith!Misgovern
M
1

As Ranjith pointed out, the staticContent section is the cause of the conflict. I just found you can limit those entries inside of location entries, so you can get all of IISNode as desired and still serve up static content. My web.config now looks like this:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.web>
    <customErrors mode="off" />
  </system.web>
  <system.webServer>
    <handlers>
      <add name="iisnode" path="server.js" verb="*" modules="iisnode"/>
    </handlers>
    <rewrite>
      <rules>
        <rule name="Redirect to https" stopProcessing="true">
          <match url="(.*)" />
          <conditions>
            <add input="{HTTPS}" pattern="off" ignoreCase="true" />
          </conditions>
          <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Found" appendQueryString="true" />
        </rule>

        <rule name="StaticContent">
          <action type="Rewrite" url="public{REQUEST_URI}"/>
        </rule>

        <rule name="DynamicContent">
           <conditions>
            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True"/>
           </conditions>
           <action type="Rewrite" url="server.js"/>
        </rule>
      </rules>
    </rewrite>
    <httpErrors existingResponse="PassThrough" />
  </system.webServer>

 <location path="public/fonts">
    <system.webServer>
      <staticContent>
         <mimeMap fileExtension=".woff" mimeType="application/font-woff" />
      </staticContent>
    </system.webServer>
  </location>
</configuration>

The added location entry at the end works around the 500 and static content conflicts.

Misgovern answered 16/4, 2014 at 13:33 Comment(0)
I
0

I'm getting the exact same...500 error page returned from Azure/IIS. I used the web.config that Azure automatically generated as the basis, then added <customErrors mode="off" /> and <httpErrors existingResponse="PassThrough" />. I also removed the default staticContent node. Nothing is working.

Below is the web.config that I'm uploading to Azure. What in here is causing IIS/iisnode to return a 500 error page instead of the simple text error message I have node/express returning to the client?

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.web>
    <customErrors mode="off" />
  </system.web>
  <system.webServer>
    <httpErrors existingResponse="PassThrough" />
    <webSocket enabled="false" />
    <handlers>
      <add name="iisnode" path="server.js" verb="*" modules="iisnode"/>
    </handlers>
    <rewrite>
      <rules>
        <rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
          <match url="^server.js\/debug[\/]?" />
        </rule>
        <rule name="DynamicContent">
          <conditions>
            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True"/>
          </conditions>
          <action type="Rewrite" url="server.js"/>
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>
Imperfection answered 25/3, 2014 at 16:40 Comment(3)
have you tried removing the NodeInspector rule? I've never had any luck with that one.Misgovern
Hi Erik, I tried your web.config along with the following server.js and I get the expected error code i.e 409 back. Server.js: ---------------------------- var http = require('http'); http.createServer(function (req, res) { res.writeHead(409, {'Content-Type': 'text/html'}); res.end('Hello, world!'); }).listen(process.env.PORT); -------------- If you could share a simple repro application, I will investigate further.Arabeila
This did the trick #15144905Imperfection
S
0

This works for me:

<?xml version="1.0" encoding="utf-8"?> 
  <configuration>
    <system.webServer>
      <handlers>
        <add name="iisnode" path="app.js" verb="*" modules="iisnode"/>
      </handlers>
      <rewrite>
        <rules>
          <rule name="DynamicContent">
            <match url="/*" />
            <action type="Rewrite" url="app.js"/>
          </rule>
        </rules>
      </rewrite>
    </system.webServer>
  </configuration>
Smidgen answered 25/3, 2014 at 17:31 Comment(1)
doesn't work for me. In node I'm using express to res.send(400, 'this is my error');. Azure/IIS is turning that into a standard IIS 500 error page.Imperfection
I
0

I had the same issue (IIS Node on Win Server 2012R2). So I did not get the target content in the body.

At the beginning I had response:

code: 400
body: Bad Request

Then I added <httpErrors existingResponse="PassThrough" /> and I got response:

code: 500
body: The page cannot be displayed because an internal server error has occurred

Then I have changed IIS Feature Delegation for "Error Pages" to "Read/Write" and this resolved my issue. Finally I had proper response:

code: 400
body: { "error": {...} }

I hope this helps.

Inexpiable answered 28/12, 2018 at 18:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.