iisnode - IIS7.5: 405 Method not allowed when performing PUT request - node.js

I started to do some experimentation with iisnode and expressjs to create a REST like API with node.
So on the server.js I created something like
app.put("/test", function(req, res){
...
});
However, when I execute the PUT request I get a 405 Method not allowed from the IIS 7.5 installation.
Any idea on how to solve this?
BTW, I googled already and tried to add the PUT verbs here and there in the different Handler Mappings with no success...

I now finally found the solution to this problem namely the WebDavModule was blocking my PUT requests.
To resolve the issue:
Open your IIS Manager
Goto your application configuration and open "Modules"
Search WebDavModule and remove it (menu on the right)
It then worked for me.
Alternatively, in your application's web.config add
<system.webServer>
...
<modules>
<remove name="WebDAVModule"/>
</modules>
</system.webServer>

One reason may be that your web.config does not map the particular request you are making to the iisnode handler. In that case the request is picked up by the static request handler which does not support PUT methods and responds with a 405.
To fix this you need a iisnode handler registration like this in your web.config: https://github.com/tjanczuk/iisnode/blob/master/src/samples/helloworld/web.config#L7
In addition, if you plan to use URL that do not end with the name of your node.js file (like seems to be the case above), you will need to use a URL rewrite module to tell IIS exactly which requests should have their URLs rewritten to point to the URL of your node.js entry point. Read more at: http://tomasz.janczuk.org/2011/08/using-url-rewriting-with-nodejs.html

Related

Why am I getting a 404 for my LESS file on my Azure App Service?

Ok, so... famous saying... this works locally, but not when I deploy.
I recently switched to using Less.js so that I could dynamically change my less variables with Javascript. Again, locally this works like a champ.
In my header I have it referenced:
<link rel="stylesheet/less" type="text/css" href="~/Content/main.less" />
<script src="//cdnjs.cloudflare.com/ajax/libs/less.js/3.9.0/less.min.js"></script>
When I use Visual Studio to deploy this to my Azure App Service I get a 404 on the less file and it all breaks.
I FTP'd into my server and the file is indeed there. https://i.imgur.com/cV5FQOW.png
I double checked to make sure that my properties for the less file are right. I have the build action set to Content and Copy if Newer. https://i.imgur.com/I3DbfHg.png
No matter what I do, if I go looking for that main.less file the azure server returns a 404.
As an FYI, the site is a ASP.Net MVC 5 website. I am using bundling, but only for external css like JQueryUI. I have removed the bundling of my CSS to work with the new stuff.
What am I missing?
Ok! After a bunch of attempts and searches I finally found a related error and found my solution.
This poor gentleman was having an issue serving up JSON files (angular2 app, http request for file json file, 404 on azure) and that made me think I had the same problem.
Eureka! I needed to update my web.config to let it serve LESS files.
<system.webServer>
<staticContent>
<mimeMap fileExtension=".less" mimeType="text/css" />
</staticContent>
<system.webServer>
Hope this helps someone else who runs into the same issue.

Express routing with a '+' in the path

I'm using express to host my Angular2 app in Azure.
As per the Angular2 style guide, I've marked some components as lazy loaded by prefixing the folder with a '+'.
When I try to GET a file in this folder (e.g. app/+about/about.component.ts) it returns a 404. However when the '+' is not in the folder name it works.
My Express config for the 'app' folder is app.use("/app", express.static('app'));
From looking at the documentation for Express I can see the '+' is used for regex patterns, but couldn't see a way to escape this. What is the workaround?
Thanks
Alex
Found my issue:
So I'm building and deploying a nodejs app in Azure by following the instructions as documented here and have found the issue is with IIS.
If I look at the logs I can see the error:
The request filtering module is configured to deny a request that contains a double escape sequence.
If I add the following to the web.config file then it works ok:
<system.webServer>
<security>
<requestFiltering allowDoubleEscaping="true" />
</security>

Microsoft.Owin.StaticFiles works in console host but I get a 404 in IIS on file requests

I have Microsoft.Owin.FileServer (v2.1.0) set up in my Owin pipeline, and setting up FileServerOptions with EnableDirectoryBrowsing = true works great for showing the directory contents in both my console host and iisexpress.
It's when I try to view a particular file (so, the StaticFiles part) I have problems in iisexpress. Still works great in the console host, but in iisexpress I get a 404:
HTTP Error 404.0 - Not Found
The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
Most likely causes:
- The directory or file specified does not exist on the Web server.
- The URL contains a typographical error.
- A custom filter or module, such as URLScan, restricts access to the file.
I do have the latest Microsoft.Owin.Host.SystemWeb referenced in the web host.
Adding <modules runAllManagedModulesForAllRequests="true"> didn't work for me (VS2013, IIS Express).
Forcing all requests to use the Owin pipeline did:
(in web.config)
<configuration>
<system.webServer>
<handlers>
<add name="Owin" verb="" path="*" type="Microsoft.Owin.Host.SystemWeb.OwinHttpHandler, Microsoft.Owin.Host.SystemWeb"/>
</handlers>
</system.webServer>
</configuration>
I had to add the following setting:
<modules runAllManagedModulesForAllRequests="true">
to get the module that Microsoft.Owin.Host.SystemWeb automatically registers to run for routes like *.txt, *.js that IIS was assuming were static files to run through the Owin pipeline.
This setting does have performance implications for actual static files, but this works for me.
I've just struggled with this for the last couple of hours, adding the handler below did work however I don't believe this was the correct approach, it caused public void Configuration(IAppBuilder appBuilder) to be invoked twice.
<add name="Owin" verb="" path="*" type="Microsoft.Owin.Host.SystemWeb.OwinHttpHandler, Microsoft.Owin.Host.SystemWeb"/>
I did some reading and found https://learn.microsoft.com/en-us/aspnet/aspnet/overview/owin-and-katana/owin-middleware-in-the-iis-integrated-pipeline
which then lead me to use UseStageMarked().
So now my call to UseStaticFiles() is followed by a called to UseStageMarker() like so:
appBuilder.UseStaticFiles();
//allows owin middlwares to be executed earlier on in the pipeline.
appBuilder.UseStageMarker(PipelineStage.Authenticate);
There is a very good read on it here:
You can find UseStageMarker inside the Microsoft.Owin package here: https://www.nuget.org/packages/Microsoft.Owin/
I hope this helps someone else.
Thanks
Steve

Custom errors not working with IISExpress

I have a asp.net mvc application and am trying to get custom errors working with IISExpress.
Works in Casini fine:
<customErrors mode="On" defaultRedirect="/error">
<error statusCode="404" redirect="/error/notfound"/>
</customErrors>
When I've deployed mvc sites to IIS (7.5) before, all I had to do get my custom errors working was to set:
<httpErrors errorMode="Detailed"/>
I've tried explicitly specifying the status codes within the httpErrors section but nothing works. Here's an example:
<httpErrors errorMode="Detailed" defaultResponseMode="Redirect">
<clear/>
<error statusCode="404" path="/error/notfound"/>
</httpErrors>
Any ideas?
Thanks
Ben
This was caused partly due to my misunderstanding of how custom errors are actually invoked and also the fact that (IMHO), the handling of errors in asp.net mvc is a bit messed up.
The first issue was that in a number of my action methods, I was checking for the existence of an object e.g. a blog post, and returning a HttpNotFoundResult if the blog post was null. I was under the assumption that this would then display the custom error page that I had set up for 404 errors.
However, this is not the case. Returning a HttpNotFoundResult simply sets the status code of the response to 404. The rest is then handled by IIS, displaying the IIS 404 error page or by your browser if it has it's own custom error page.
One solution here is to return a HttpException which will use your custom error pages since the request is be handled by asp.net.
I chose instead to create a new ActionResult that allowed me to specify a view along with a http status code. I preferred this to throwing exceptions.
The next issue was that by default a new MVC project has a greedy route defined. If you make a request to /foo/bar the default MvcHandler will look for a controller called Foo. When it can't find it, it will return 404.
I had removed the default route and had no greedy routes. This meant that urls not matching any of my routes would not be handled by asp.net and would just fall back to IIS.
The solution here was to create a wildcard route at the bottom of my routing configuration to match all other requests and forward them to a custom PageNotFound action, that sets the status code to 404 and displays my custom view.
Some things worth pointing out.
You will need to set httpErrors errorMode="Detailed" for your custom error pages to be displayed in IIS/IISExpress. The rest however can be left alone.
Setting the defaultRedirect path in the customErrors section has no effect on 500 errors. This is because the global HandleErrorAttribute handles all 500 errors and just looks for a view called "Error" to display. This means that if your custom error page is actually a controller action, it will not be invoked. The above is true even if you explicitly specify a 500 error page.
You should still keep the defaultRedirect path however, as it will be used for other status codes if they are not specified explicitly.
If you are using iisexpress you can just comment out the entire httpErrors section < !-- --> in the applicationhost.config and replace it with the following:
<httpErrors errorMode="Custom">
<error responseMode="Redirect" statusCode="404" path="../missing/index.php" />
</httpErrors>
path is the url path to your custom site specific page

IIS7 Hijacks My Coldfusion Error Page

In my exception handling file, I set a statuscode to 404 and then render n HTML page, for the error page (think fail-whale).
<cfheader statuscode="404" statustext="Application Exception">
<html><head><title>Error</title></head><body><h1>There was an error yo!</h1></body></html>
This is obviously over simplified, but just to make sure everything was demonstrated.
What I have found is that from a ASP.NET request, they can set a variable "Response.TrySkipIisCustomErrors=true" to keep IIS from showing its own error page.
How can someone in Coldfusion do it / how can I just tell IIS to stop its thinks it knows better than me shenanigans.
This might help:
<configuration>
<system.webServer>
<httpErrors existingResponse="PassThrough" />
</system.webServer>
</configuration>
For more information:
HTTP Errors (IIS.NET)
What to expect from IIS7 custom error module (IIS.NET)
If that doesn't work then you might try writing a .NET HttpModule to plug into the IIS request/response pipeline to set Response.TrySkipCustomErrors. Not ideal.
ASP.NET's worker request object calls an exported function called MgdSetStatusW. The problem here is that unless Coldfusion exposes this flag then you won't be able to set the value directly in CF.
Poking around with .NET Reflector I seen ASP.NET setting the response status using:
[DllImport("webengine4.dll", CharSet=CharSet.Unicode)]
internal static extern int MgdSetStatusW(IntPtr pRequestContext,
int dwStatusCode, int dwSubStatusCode, string pszReason,
string pszErrorDescription, bool fTrySkipCustomErrors);

Resources