В ноябре 2017 года я писал об оригинальном switchcase, небольшой JavaScript-библиотеке для написания декларативных и функциональных переключателей с поддержкой литералов, функциональных тестов, регулярных выражений. Недавно пользователь закрыл проблему, решенную много месяцев назад, и это заставило меня пересмотреть код. Я понял, что с очень небольшими улучшениями код можно было бы использовать в качестве маршрутизатора, потому что маршрутизаторы фактически являются интеллектуальными коммутаторами.

На прошлой неделе я опубликовал результаты: маршрутизатор, который можно использовать на стороне клиента для обмена хэшами или общей маршрутизации событий, на сервере для маршрутизации запросов и в любом другом месте, где вы хотите использовать функциональность, подобную маршрутизатору. Ниже приведены несколько примеров. Первый — маршрутизатор запросов на стороне сервера, второй — маршрутизатор хэширования на стороне клиента. Обработка ошибок была удалена, а объекты фиктивны для упрощения примеров. Обратите внимание на отсутствие необходимости выполнять какую-либо специальную настройку для использования сервером или клиентом.

const router = switchcase()
  .route("/data/:name",{req:{params:{name}},res} => {
    const msg = `Requested object with name ${name}`
    console.log(msg);
    return true;
});
router.handle({
  req:{url:"https://site.com/data/joe"},
  res:{}});
const router = switchcase()
  .route("/:id/:name", async ({params:{id,name}) => {
    const res = await fetch(`https://site.com/data/${name}`);
      html = await res.text();
    document.getElementById(id).innerHTML = html;
  });
router.handle({newURL:"https://localhost/tab1/joe"});

В дополнение к тому, что не требуется никакой специальной настройки для использования сервером или клиентом и он обрабатывает параметры, основанные на двоеточии, маршрутизатор switchcase достаточно умен, чтобы обрабатывать запросы или события с любой из следующих поверхностей:

{request:{path: <some path string>},response:<some response object>}
{request:{location: <URL object>},response:<some response object>}
{request:{url: <some URL string>},response:<some response object>}
{req:{path: <some path string>},res:<some response object>}
{req:{location: <URL object>},res:<some response object>}
{req:{url: <some URL string>},res:<some response object>}
{newURL: <some URL string>} // matches a hashchange browser event
{path: <some path string>},...}
{location: <URL object>},...}
{url: <some URL string>},...}
{path: <some path string>},...}

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

const router = switchcase({},{
    pathRouter:{
      route:(object) => new URL(object.rqst.url).pathname
    }
  })
  .route("/data/:name",{rqst:{params:{name}},rsp} => {
    const msg = `Requested object with name ${name}`
    console.log(msg);
    return true;
});
router.handle({
  rqst:{url:"https://site.com/data/joe"},
  rsp:{}});

Как и в исходном switchase, ваши условия тестирования, обычно параметризованные пути, не обязательно должны быть строками. Они могут быть функциями или регулярными выражениями и могут каскадироваться, например.

let authorized; 
const router = switchcase()
  .route(()=>true,({req}) => // try to authorize all requests
     { 
       authorized = auth(req); 
     } // note, returns undefined, so route cascades
  )
  .route(/.*secret.*/,{res} => {
    if(authorized) {
      res.end("a secret");
    } else {
       res.status = 403;
       res.end("Unauthorized");
    }
    return true; // returns a value, so routing stops
});

Попробуйте switchcase и, если вам понравится, похлопайте нам!