No route registered for static file in Azure App Service - reactjs

I have a Azure App Service that runs a ReactJS application. In the release pipeline I extract a zip file that contains my Cypress test results.
When I navigate to my Kudu console I can find the correct folder and files in my PS D:\home\site\wwwroot\e2e\mochawesome-report> folder. But when I navigate to
a video:
https://exampleUrl/e2e/mochawesome-report/video/onboarding.spec.js.mp4
The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
But when I navigate to: https://exampleUrl.azurewebsites.net/e2e/mochawesome-report/screenshot/customer-card.spec.js/Customer card action tab -- can click on the account tab (failed).png
I can view the image.
Is there some configuration needed to view static files?
##EDIT##
Added my web.config:
<?xml version="1.0"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="React 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" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
I'm pretty sure I found this somewhere on the web.
Something else I noticed. I can now open a .html and .css, .js and .png files but no .json, .woff, .woff2 and mp4.

You need to define file extensions to your web app.
Add these lines to your web.config, below your </rewrite>, then restart your Web App:
<staticContent>
<mimeMap fileExtension=".mp4" mimeType="video/mp4" />
</staticContent>
To add other extensions (like json):
<mimeMap fileExtension=".json" mimeType="text/plain" /
The result would be:
<staticContent>
<mimeMap fileExtension=".mp4" mimeType="video/mp4" />
<mimeMap fileExtension=".json" mimeType="text/plain" /
</staticContent>

Related

Why does my HTTP GET call to a subroute in react app gives a 404 NOT Found instead of HTML?

When I try to do a GET call to a subroute of my react application I get a 404.
When I do this to my homepage it returns correctly the HTML.
When just accessing the subroutes via the browser my webpage gets correctly rendered.
I'm Using React version 16.9.0.
I'm hosting the web application in Azure App service.
The reason for this question is to use an external program that can check for deadlinks in a website. At the moment I get 404's for every call to a subroute.
GET calls in Postman:
www.test.be => works
www.test.be/custom-route => gives a 404
This is my React Router Wrapper component:
import React from 'react';
import { Switch, Route } from 'react-router-dom';
import Home from 'home/containers/home-container.js';
import NotFoundPage from './error-pages/not-found-page';
import Questions from 'questions/containers/question-container.js';
const Body = () => {
return (
<Switch>
<Route path="/" exact component={Home} />
<Route path="/questions" component={Questions} />
<Route component={NotFoundPage} />
</Switch>
);
};
export default Body;
This is my web.config file:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<httpRuntime requestPathInvalidCharacters="<,>,*,&,:,\\,?" />
</system.web>
<system.webServer>
<httpProtocol>
<customHeaders>
<remove name="X-Powered-By" />
</customHeaders>
</httpProtocol>
<rewrite>
<rules>
<rule name="HTTPSs">
<match url="(.*)"/>
<conditions>
<add input="{HTTPS}" pattern="Off"/>
<add input="{HTTP_HOST}" negate="true" pattern="^localhost" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}"/>
</rule>
<rule name="ReactRoutes" stopProcessing="true">
          <match url=".*" />
          <conditions>
            <add input="{HTTP_METHOD}" pattern="^GET$" />
            <add input="{HTTP_ACCEPT}" pattern="^text/html" />
            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
          </conditions>
          <action type="Rewrite" url="/index.html" />
        </rule>
</rules>
</rewrite>
<security>
<requestFiltering allowDoubleEscaping="true"/>
</security>
</system.webServer>
</configuration>
You don't provide complete details but If I understand correctly, it can help you to solve your problem, if you have this problem on the server and when you open the homepage it works correctly and when open a subroute it goes to 404 page, add this to your .htaccess file
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
This is because how reactjs applications gets deployed on your production WebServer.
Reactjs applications are served deployed on with single index.html. Entire entire react project is served from index.html (This is how 'www.test.be' works). React-router programmatically updates the browser URL based on which page you navigate.
When your visit 'www.test.be/custom-url', the request is first caught and processed by the webserver. The webserver is expecting HTML file named 'custom-url.html' doesn't find it. So webserver throws a '404' i.e. 'Page not found' error. The request is not forwarded to your ReactApp - so your ReactApp never gets a chance to process the request.
The solution depends on the type of hosting service you are using. Basically, you want to redirect all URLs to React App (index.html) so that React Application will get a chance to process 404.
Update your question with the hosting service you are using (such as netlify, heroku, aws etc) and I can update this answer with a solution suitable for that hosting service.
For instance, if the webhost is netlify, you can create a file called _redirect in public/ directory with the following content
/* /index.html 200
That will redirect all traffic (*) to index.html
It happens because you don't have SSR (Server-Side Rendering). probably you're using CRA to create your ReactJs web application, so it works with CSR and the sub-routes couldn't be understood by server.
I don't mean bring SSR to your project, because you should be serious about using SSR for some special reasons. by the way, there is a very simple solutions for any kind of servers, you should redirect all requests to the index.html then react-router can understand the sub-route in the client:
Redirect all to index.html:
PM2 server:
pm2 start [path-to-build-folder/app.js] --spa
Serve:
serve -s [path-to-build-folder/app.js]
IIS:
<!--web.config url rewrite-->
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Redirect To Index" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="/index.html" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
I don't know how you deployed your ReactJs web application, because some time DevOps specialist use running ReactJs app by using serve, pm2 or node under a special port for example: 8008 then by using IIS proxy try to connect the web application to local process, so by calling the port 80 user will be able to see the website. Also, you can directly serve the application by serving index.html in the IIS, and totally your solution is redirecting all requests to index.html.
Hope this answer helps you.
try this web.config :)
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="React 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" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>

IIS Redirect all request on root

I have reactjs application with react router. I dont want to use hash history and I encountered the issue with refreshing page creating 404 error (react-router is not loaded when refreshing and browser wants to fetch non-existent content thus 404). I found some solution and I want to redirect every request to root so server always fetch index.html with import tags first.
My folder structure is simple:
ROOT/
-- index.html
-- static/
-- js/
-- main.js
-- css/
etc...
I have this web.config rule found on this site:
<rewrite>
<rules>
<rule name="redirect all requests" stopProcessing="true">
<match url="^(.*)$" ignoreCase="false" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" pattern="" ignoreCase="false" />
</conditions>
<action type="Rewrite" url="index.html" appendQueryString="true" />
</rule>
</rules>
</rewrite>
This works very fine with URLs on first folder path, I mean all request like /items, /contact are good. But requests like /items/detail are broken because browser is looking into items folder and not into document root. Also very important thing is that my webpack generate index.html script tags in this manner: <script type="text/javascript" src="./static/js/main.js">.
Is it possible that src attribute is wrong because of that ./? How can I tell server (IIS 10) "hey don't look anywhere else but into document root?"
Thanks guys.
This is a solution I found were I have some paths I still want to handle by my IIS but the rest I want react to take care.
<configuration>
<system.webServer>
<rewrite>
<rewriteMaps>
<rewriteMap name="^(.*)$" />
</rewriteMaps>
<rules>
<rule
name="redirect all requests"
stopProcessing="true"
>
<match url="^(.*)$" />
<conditions logicalGrouping="MatchAll">
<add
input="{REQUEST_URI}"
pattern="/someOtherResourceIstillWantIIStoHandle(.*)$"
negate="true"
/>
<add
input="{REQUEST_FILENAME}"
matchType="IsFile"
negate="true"
/>
<add
input="{REQUEST_URI}"
pattern="/resourcecentre(.*)$"
negate="true"
/>
</conditions>
<action type="Rewrite" url="/index.html" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>

How to configure IIS URL Rewrite module to work with "HTML 5 pushState" style and hash fragments on url?

Angular 2 has a PathLocationStragy to work with html5 routes and a HashLocationStrategy to work with hash fragments '#' on routes.
The issue here is when we use OIDC (OpenID Connect) for user authentication and PathLocationStragy (or html5mode for routes on AngularJS) because OpenID on some flows returns data after a '#' fragment after redirect back to the site after user logging with a url as follow:
http://mysite/callback#code=7b60c0570d7c4da0fc60678c0e46deadd5eeab0a659203fd44efb7cd51b2cdab&id_token=eyJhb ...
For html5 routes is very common the settings bellow on IIS Url Rewrite:
...
<system.webServer>
<rewrite>
<rules>
<remove name="AngularJS Routes" />
<rule name="AngularJS 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" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
</rules>
</rewrite>
</system.webServer>
...
But when the web sever receives the url with http://mysite/callback#code=7b60c0570d7c4d from Authorization Server after user logging the response for this request is: 403 - Forbidden: Access is denied.
I think that the problem is with the Url rewrite settings, not with AngularJS or Angular 2 app´s...
How to solve that? How to use AngularJS/Angular 2 with html5 route style and OpenID Connect?
Fragment values are not sent to the server, they are only handled client-side by the browser. The browser is only sending http://mysite/callback

MVC 6, .NET Core RC2 Rewrite to index.html on non /api urls

I am using MVC 6 with .NET Core RC2
In my startup.cs I have the following (as most people suggest):
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseMvc();
}
In my wwwroot/web.config file I have:
<configuration>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<handlers>
<add name="httpPlatformHandler" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified"/>
</handlers>
<httpPlatform processPath="%DNX_PATH%" arguments="%DNX_ARGS%" stdoutLogEnabled="false" startupTimeLimit="3600"/>
<rewrite>
<rules>
<rule name="IndexHomeRule" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true"/>
<add input="{REQUEST_URI}" matchType="Pattern" pattern="^/api/" negate="true" />
</conditions>
<action type="Rewrite" url="/index.html" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
My goal is that all non /api urls will be rewritten to index.html for Angularjs to handle the routing with html5mode. The main directory will load index.html but other than that I get 404 errors for every other url. How can I set up rewriting if not through web.config?
The only controller I have right now is api/BuyersController.cs which routes using [Route("api/[controller]")]
The URL rewriting for ASP.NET CORE RC2 through to RTM is currently broken as it exists in your question.
The ASP.NET team is currently working on some middleware as a direct ASP.NET solution to this problem. The github issue tracking this is located below.
https://github.com/aspnet/BasicMiddleware/issues/43
There are some solutions in this other issue thread that could be of help to you in the interim.
https://github.com/aspnet/IISIntegration/issues/192

ASP.net WebAPI ignoring web.config?

I am setting up a web.config in wwwroot to redirect all requests to index.html for angularjs to handle. This excludes existing files and folders and anything from /api.
The problem is, it's not working that way. I simply get blank pages for anything where a file does not exist.
Here is my web.config:
<configuration>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<handlers>
<add name="httpPlatformHandler" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified"/>
</handlers>
<httpPlatform processPath="%DNX_PATH%" arguments="%DNX_ARGS%" stdoutLogEnabled="false" startupTimeLimit="3600"/>
<rewrite>
<rules>
<rule name="IndexHomeRule" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true"/>
<add input="{REQUEST_URI}" matchType="Pattern" pattern="^/api/" negate="true" />
</conditions>
<action type="Rewrite" url="/index.html" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
I can't figure out any reason for it to still be trying to load the files instead of redirecting them to index.html
I am using .NET Core RC2 and I have static files and default files set to be used. I am using VS2015. I set the project up as a WebAPI from the beginning. Not empty.
You can use Microsoft.AspNetCore.SpaServices:
app.UseMvc(options =>
{
options.MapRoute("Api",
template: "api/{controller}/{action?}/{*path}",
defaults: new { controller = "Home" });
options.MapSpaFallbackRoute("spa-fallback", new { controller = "Home", action = "Index" });
});

Resources