Michael Scheidegger Michael Scheidegger - 1 year ago 109
AngularJS Question

Node/Angular url-rewrite not working

I am pretty new to angular/node. That being said I am having an issue where refreshing my page just returns a JSON body which is being served up from my webserver.

I have tried creating middleware so that my index.html is an entry point for the application but for some reason on this particular page it does not want to work.


//set up web server
var express = require('express');
var path = require('path');
var app = express();
var port = process.env.port || 5000;
var rootPath = path.normalize(__dirname);

//init body parser
var bodyParser = require('body-parser');
extended: true
//serve up static css/js files from public directory
app.use(express.static(rootPath + '/public'));
app.use(express.static(rootPath + '/src'));

//init sql
var sql = require('mssql');
var config = require('./dbconfig');

sql.connect(config, function (err) {
if (err !== null) {

//set up routes
var searchRouter = require('./src/webserver/routes/searchRoutes')();
app.use('/search', searchRouter);

app.get('*', function (req, res) {
res.sendFile(rootPath + '/src/index.html');
// res.render(rootPath + '/src/index.html');

//start server
app.listen(port, function (err) {
console.log('running server on port ' + port);

searchService.js - this is a service which is sending a json response to the client. There is a route and controller bewteen this code handling the response.

var sql = require('mssql');

var searchService = function () {

function searchIssues(req, res, searchterm) {
var fetch = 50; //show 50 results at a time
var offset = 0; //will extract out of request eventually
var ps = new sql.PreparedStatement();
ps.input('searchterm', sql.NVarChar);
ps.input('fetch', sql.Int);
ps.input('offset', sql.Int);
ps.prepare('select * from dbo.udfSearchIssues(@searchterm, @offset, @fetch)',
function (err) {
searchterm: searchterm,
fetch: fetch,
offset: offset
function (err, recordset) {
if (recordset.length === 0) {
res.status(404).send('Not Found');
} else {
res.setHeader('Content-Type', 'application/json');

return {
searchIssues: searchIssues

module.exports = searchService;

My angular client side routing

'use strict';
(function () {
var bugFarmApp = angular.module('bugFarmApp', ['ngResource', 'ngRoute'])
.config(function ($routeProvider, $locationProvider) {
$routeProvider.when('/issue/:issueKey', {
templateUrl: 'templates/issue.html',
controller: 'IssueController'
$routeProvider.when('/search/', {
templateUrl: 'templates/search.html',
controller: 'SearchController',
resolve: {
event: function($route, search){
return search.getIssues().$promise;
$routeProvider.when('/search/:searchval', {
templateUrl: 'templates/search.html',
controller: 'SearchController',
resolve: {
event: function($route, search){
return search.getIssuesByVal($route.current.pathParams.searchval)
redirectTo: '/'




var express = require('express');
var searchRouter = express.Router();

var router = function(){

var searchController = require('../controllers/searchController')();


return searchRouter;

module.exports = router;


var searchController = function () {

var searchService = require('../services/searchService')();

var getAllIssues = function (req, res) {
searchService.searchIssues(req, res, '');

var getIssuesByValue = function (req, res) {
if (req.params.searchval == undefined) {
var searchterm = '';
} else {
var searchterm = req.params.searchval;
searchService.searchIssues(req, res, searchterm);

return {
getAllIssues: getAllIssues,
getIssuesByValue: getIssuesByValue


module.exports = searchController;

So again just to re-cap, I load my webserver and go to localhost:3000 and everything works fine and index.html is served up. I go to my nav bar and click search and it fires a function in my angular controller which uses the location service to route me over to /search/. If I do this through the UI everything loads and all the html in my search.html template is good.

If I click refresh or try to manually type in the URL it just gives me the JSON I am getting back from SQL.

Sorry if there is something easy but I have been stuck on this for a while and have searched up and down on the forum.

EDIT: I added my express routes to the question
EDIT2: Ryan had the correct solution below. My client side routes and server side routes were using the same path.

Answer Source

The easiest solution(and cleaner IMO) is to add a prefix to all of your api routes. Something like

// app.js....

//set up routes
var searchRouter = require('./src/webserver/routes/searchRoutes')();
app.use('/api/search', searchRouter);

// ...app.js

I don't see the place in your Angular code that makes the actual ajax call to your node service but it looks you are calling it via search.getIssuesByVal in your client side routing. The service that makes the call will have something like $http.get('/search', ....); You need to change that to match your new api route: $http.get('/api/search', ....).

If you absolutely have to use the same path you would have to use content negotiation. Which means that in angular you would have to set the Accept header to application/json and then in all of your routes(or better in middleware) you would check the Accept header to determine if you should serve the index page or json.