Reputation: 2413
I have a WebApp with an AspNetCore WebAPI + AngularApp on Azure with IIS rewrite rules in my Web.Config based on this article: https://weblog.west-wind.com/posts/2017/Apr/27/IIS-and-ASPNET-Core-Rewrite-Rules-for-AspNetCoreModule
I would like to avoid rewriting on Swagger, so I added this rule as the first rule:
<rule name="swagger" enabled="true" stopProcessing="true">
<match url="swagger/.*" />
<action type="None" />
</rule>
Based on this website: https://www.regextester.com/
The rules is supposed to exclude swagger/ and all the subfolders and files too. But It s not the case.
This is what I can see when I open http://[MYWEBSITE]/swagger/
The Angular app works correctly.
I already made some search about that:
Thanks for your help.
EDIT 1:
Just to let you know, with the default web.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="dotnet" arguments=".\[MYWEBAPP].Api.dll" stdoutLogEnabled="false" stdoutLogFile="\\?\%home%\LogFiles\stdout" />
</system.webServer>
</configuration>
I can correctly see Swagger working:
EDIT 2:
During my tests, I removed the rewrite rules to focus only on the Handlers and I noticed that theses rules make problem:
It s normal, Swagger is build in the .NetCore WebApi. I m looking for a way to exclude a specific folder from a handlers.
Based on this response: IIS Handlers exclude a Directory when processing htm requests
I created a web.config in 'D:\home\site\wwwroot\wwwroot\swagger' on Azure with the following configuration:
<system.webServer>
<handlers>
<remove name="StaticFileModuleHtml" />
<remove name="StaticFileModuleJs" />
<remove name="StaticFileModuleCss" />
<remove name="StaticFileModulePng" />
</handlers>
</system.webServer>
EDIT 3:
Clearly the problem comes from the Static handlers. If I want to use Swagger, I need to disable them. If I want to access to my angular App, I need to add them.
I saw here: https://github.com/domaindrivendev/Swashbuckle.AspNetCore#swashbuckleaspnetcorecli
That it seems possible to extract the content from the SwaggerUi directly in a folder on built, but currently, the Nugget Package is not available: https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/601
I will keep you update. If someone has an idea, it will be helpful. I m probalbly not the only to try to do that :).
But the problem is still there.
Upvotes: 4
Views: 6937
Reputation: 156
First of all, because Swagger does not make a real folder, so it is not a perfect idea to make a folder in wwwroot named swagger and make that web.config inside of it. I consider that the default address for your swagger UI is: localhost:[random-port-number]/swagger/index.html. It can be different based on your swagger version and you can also change it to something else like below:
app.UseSwagger(c =>
{
c.RouteTemplate = "SampleApi/swagger/{documentName}/swagger.json";
});
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/SampleApi/swagger/v1/swagger.json", "Sample API");
c.RoutePrefix = "SampleApi/swagger";
});
For more information see this article. The version of my Swashbuckle.AspNetCore is 4.0.1 I also added API to the routes in order to be able to use your Microsoft web APIs in your project from font-end by React or Angular or anything else, you just need to add this to your main web.config in the project:
<rules>
<rule name="wwwroot-static" stopProcessing="true">
<match url="([\S]+[.](html|htm|svg|js|css|png|gif|jpg|jpeg|ico|axd))" />
<!--Handle static file requests and server them from the wwwroot-->
<conditions logicalGrouping="MatchAll">
<add input="{HTTP_METHOD}" pattern="GET|HEAD" />
<add input="{REQUEST_URI}" pattern="/swagger/.*" negate="true" />
</conditions>
<action type="Rewrite" url="wwwroot/{R:1}" />
</rule>
<rule name="html5-routes" stopProcessing="true">
<match url=".*" />
<!-- Handle all paths except /api/ and pass the route onto the wwwroot/index.html -->
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<!-- Add rule to negate file requests e.g. css/html/images-->
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<!-- Add rule to negate directories-->
<add input="{REQUEST_URI}" pattern="^/api/" negate="true" />
<add input="{REQUEST_URI}" pattern="/swagger/.*" negate="true" />
<!-- Add rule to negate paths and let them through the MVC-->
<add input="{HTTP_METHOD}" pattern="GET|HEAD" />
</conditions>
<action type="Rewrite" url="wwwroot/index.html" />
</rule>
</rules>
Upvotes: 2
Reputation: 2413
I finally found a solution!
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="wwwroot-static" stopProcessing="true">
<match url="([\S]+[.](html|htm|svg|js|css|png|gif|jpg|jpeg))" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_URI}" pattern="swagger/" negate="true" />
</conditions>
<action type="Rewrite" url="wwwroot/{R:1}" />
</rule>
<rule name="empty-root-index" stopProcessing="true">
<match url="^$" />
<action type="Rewrite" url="wwwroot/index.html" />
</rule>
<rule name="AngularJS-Html5-Routes" 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" />
<add input="{REQUEST_URI}" pattern="swagger/" negate="true" />
</conditions>
<action type="Rewrite" url="wwwroot/index.html" />
</rule>
</rules>
</rewrite>
<handlers>
<add name="StaticFileModuleHtml" path="*.htm*" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" />
<add name="StaticFileModuleSvg" path="*.svg" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" />
<add name="StaticFileModuleJs" path="*.js" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" />
<add name="StaticFileModuleCss" path="*.css" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" />
<add name="StaticFileModuleJpeg" path="*.jpeg" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" />
<add name="StaticFileModuleJpg" path="*.jpg" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" />
<add name="StaticFileModulePng" path="*.png" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" />
<add name="StaticFileModuleGif" path="*.gif" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" />
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="dotnet" arguments=".\[MYWEBAPP].dll" stdoutLogEnabled="false" stdoutLogFile="\\?\%home%\LogFiles\stdout" />
</system.webServer>
</configuration>
My mistake during the Edit 2 was to create a Swagger folder in wwwroot/wwwroot instead of wwwroot/ directly.
Here is the web.config to add in wwwroot/swagger:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<handlers>
<!--We need to add this web.config to avoid conflict on Azure between Angular App and Swagger -->
<remove name="StaticFileModuleHtml" />
<remove name="StaticFileModuleSvg" />
<remove name="StaticFileModuleJs" />
<remove name="StaticFileModuleCss" />
<remove name="StaticFileModuleJpeg" />
<remove name="StaticFileModuleJpg" />
<remove name="StaticFileModulePng" />
<remove name="StaticFileModuleGif" />
</handlers>
</system.webServer>
</configuration>
You can now access to:
I hope it will help someone :). If you have any questions, please ask.
Upvotes: 4