I'm currently building a portfolio site for our company in AngularJS with UI-router. We're using the HTML5 url scheme, and I've got the standard .htaccess in place to rewrite requests to index.html ( though in production this will be running on a .NET server ).
Some sections of the site are made up of freeform html documents rendered via ng-include directives, to allow our developers and designers the maximum freedom to create some pages however they want - for example client case studies that may warrant quite different layouts and media.
The pages are all loaded via a slug parameter to a state, something like '/work/some-case-study-name'. The state handler then takes the slug parameter and supplies that as url to an html file for the ng-include to load. For example the url above would resolve to '/partials/case-studies/some-case-study-name.html'. This is all loaded into a directive.
At the moment, it seems to be impossible to catch a mis-typed slug url though. It appears that either through the .htaccess setup or angular's routing system, when ng-include fails to find the requested html file, it always returns 200OK and just renders the route of the site.
Does anyone know of a way to make ng-include return a 404 if the document it's trying to load does not exist?
thanks!
I'm not great at .htaccess rewrite configuration, but after trying several examples, this was the only one I could find that reliably returned a 404 for resources that genuinely don't exist in an angular html5 setup:
https://ejd.dev/2013/05/31/angular-html5Mode-with-yeoman/
Specifically:
# Apache .htaccess
# angularjs pushstate (history) support:
# See http://www.josscrowcroft.com/2012/code/htaccess-for-html5-history-pushstate-url-routing/
<ifModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !index
RewriteCond %{REQUEST_URI} !.*\.(css|js|html|png) #Add extra extensions needed.
RewriteRule (.*) index.html [L]
</ifModule>
The difference between this and others (including the official example on the angular site) seems to be the rule matching specific file extensions. With this in place I get a 404 when trying to load a non-existent file via ng-include, which is exactly what I'm after.
EDIT:
Also - for .NET peeps, here's the equivalent web.config:
<?xml version="1.0"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Main Rule" 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=".*\.(css|js|html|png|jpg)" negate="true" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>