2017-02-11 4 views
8

Я после нормализованных/канонических URL-адресов для SPA с сервером ExpressJS.ExpressJS маршрутизатор нормализованный/канонические URL

Хотя это SPA, который подкреплен серверным маршрутизатором - шаблоны могут немного отличаться для URL-адресов приложений. Одно из отличий - <link rel="canonical" href="https://example.com{{ originalPath }}">. Не релевантная деталь, но объясняет контекст вопроса. Я ожидаю, что будет только один URL-адрес, который отвечает 200, его варианты перенаправляются на него с 301/302 (работает для живых людей и поисковых систем).

Я бы хотел, чтобы URL-адреса были чувствительными к регистру и строго (без дополнительной косой черты), аналогично параметрам Router, но неканонические URL-адреса (которые отличаются в случае или дополнительной косой чертой) должны делать 301/302 перенаправление на канонический URL-адрес вместо 404.

В большинстве приложений я просто хочу заставить URL-адреса для маршрутов * быть нижним (за исключением запросов) без дополнительных косых черт. То есть app.all('*', ...), и перенаправляет являются:

/Foo/Bar/ -> /foo/bar 
/foo/Bar?Baz -> /foo/bar?Baz 

Но могут быть исключения, если маршруты определены в явном виде. Например, есть верблюд-обсаженных маршруты:

possiblyNestedRouter.route('/somePath')... 
possiblyNestedRouter.route('/anotherPath/:Param')... 

И все неканонические URLs должны быть перенаправлены на канонический (случай параметра остаются без изменений):

/somepath/ -> /somePath 
/anotherpath/FOO -> /anotherPath/FOO 

Логика канонических URLs вполне прямо, поэтому странно, что я не мог найти что-либо по этой теме относительно ExpressJS.

Каков наилучший способ для этого? Есть уже средние средства, которые могут помочь?

ответ

4

Я искал npms, я не смог найти ни одного, поэтому это поцарапало мой разум, и я закодировал небольшую задачу для express для каждого запроса, который, кажется, работает нормально. Добавьте это в свой код.

var urls = { 
    '/main' : '/main', 
    '/anotherMain' : '/anotherMain' 
} 

app.use(function(req, res, next){ 

    var index = req.url.lastIndexOf('/'); 

    //We are checking to see if there is an extra slash first 
    if(req.url[index+1] == null || req.url[index+1] == undefined || req.url[index+1] == '/'){ 
    //slashes are wrong 
    res.send("please enter a correct url"); 
    res.end(); 
    }else{ 

     for(var item in urls){ 
     if(req.url != item && req.url.toUpperCase() == item.toUpperCase()){ 
      res.redirect(item); 
      console.log("redirected"); 
      //redirected 
     }else if (req.url == item) { 
      console.log("correct url"); 
      next(); 
     }else{ 
      //url doesn't exist 
     } 
    } 

    } 
    next(); 

}); 

app.get('/main', function(req, res){ 
    res.render('mainpage'); 
}); 

app.get('/anotherMain', function(req, res){ 
    res.send("here here"); 
}); 

ПРИМЕНЕНИЕ

Все, что вам нужно сделать, это добавить свой URLs к urls объект, как это сделано выше с приданием ему такой же ключевое значение. Вот и все. Посмотрите, насколько это просто. Теперь все ваши запросы клиентов будут перенаправлены на правильную страницу с учетом чувствительности.

UPDATE

Я также сделал один для POST запросов, я думаю, что это довольно точно, вы должны также дать ему попробовать. Если вы хотите переадресовать, когда пользователь смешивает косые черты, вам нужно написать для него regex. У меня не было времени, и мой мозг был обжарен, поэтому я сделал простой. Вы можете изменить его, как хотите. Каждая веб-структура имеет свой собственный набор правил.

var urlsPOST = { 
    '/upload' : '/upload' 
} 

app.use(function(req, res, next){ 

    if(req.method == 'POST'){ 

    var index = req.url.lastIndexOf('/'); 

    if(req.url[index+1] == null || req.url[index+1] == undefined || req.url[index+1] == '/'){ 

     //slashes are wrong 
     res.sendStatus(400); 
     res.end(); 
     return false; 

    }else{ 

     for(var item in urlsPOST){ 
      if(req.url != item && req.url.toUpperCase() == item.toUpperCase()){ 
      res.redirect(307, item); 
      res.end(); 
      return false; 
      //redirected 

      }else if (req.url == item) { 
      console.log("correct url"); 
      next(); 

      }else{ 
      res.sendStatus(404).send("invalid URL"); 
      return false; 
      //url doesn't exist 
      } 
     } 
    } 
    } 
    next(); 
}); 
1

Вы, вероятно, хотите, чтобы написать свой собственный промежуточное программное обеспечение для этого, что-то вдоль линий этого:

app.set('case sensitive routing', true); 
 

 
/* all existing routes here */ 
 

 
app.use(function(req, res, next) { 
 
    var url = find_correct_url(req.url); // special urls only 
 
    if(url){ 
 
    res.redirect(url); // redirect to special url 
 
    }else if(req.url.toLowerCase() !=== req.url){ 
 
    res.redirect(req.url.toLowerCase()); // lets try the lower case version 
 
    }else{ 
 
    next(); // url is not special, and is already lower case 
 
    }; 
 
});

Теперь имейте в виду, что это промежуточное ПО может быть помещен после того, как все текущие маршруты , так что если он не соответствует существующему маршруту, вы можете попытаться найти то, что должно быть. Если вы используете нечувствительный к регистру маршрут, вы хотели бы сделать это до ваших маршрутов.

+0

Но как насчет запросов, не связанных с GET? А как насчет чувствительных к регистру маршрутов, таких как 'somePath'? Они могут быть смонтированы, т. Е. Сегмент маршрута не будет первым после первоначального '/' в url. – estus

+1

это позволит получить все типы маршрутов, однако вы можете выполнять перенаправление только по запросам GET и сохранять все содержимое. Если вы хотите попытаться выполнить более разумное сопоставление (после вставки чувствительности к регистру в строке 1), вы можете использовать app._router.stack для перечисления всех маршрутов и попытаться найти чувствительную к регистру часть –

0

Используя тот же код, что и @ user8377060 только с регулярным выражением вместо этого.

// an array of all my urls 
    var urls = [ 
    '/main', 
    '/anotherMain' 
    ] 

    app.use(function(req, res, next){ 

    var index = req.url.lastIndexOf('/'); 

    //We are checking to see if there is an extra slash first 
    if(req.url[index+1] == null || req.url[index+1] == undefined || req.url[index+1] == '/'){ 
    //slashes are wrong 
    res.send("please enter a correct url"); 
    res.end(); 
    }else{ 

     for(var item in urls){ 
     var currentUrl = new RegExp(item, 'i'); 

     if(req.url != item && currentUrl.test(item)){ 
      res.redirect(item); 
      console.log("redirected"); 
      //redirected 
     }else if (req.url == item) { 
      console.log("correct url"); 
      next(); 
     }else{ 
      //url doesn't exist 
     } 
    } 

    } 
    next(); 

    }); 
+1

Спасибо за идею. Однако я не вижу причины использовать новый 'RegExp'. Это требует побега. Это будет соответствовать сегментам свободно, это вообще нежелательно. Сегменты Url в 'urls' могут быть сделаны регулярными выражениями, если они должны быть регулярными выражениями. – estus