IIS, Node.js и веб-приложение с IISNode не настроены правильно с помощью Virtual Directory

У меня есть следующая настройка в IIS:

  • Веб-сайт по умолчанию (www.foo.com), содержащий стандартный сайт html
  • Веб-приложение под веб-сайтом по умолчанию (www.foo.com/bar) работает с IIS Node
  • Node используется экспресс

Я не могу на всю жизнь меня правильно настроить эту штуку, поэтому, когда я попал в веб-приложение, приложение правильно работает с приложением node. Я думаю, что моя проблема заключается в web.config. Может ли кто-нибудь помочь мне написать правильный web.config, чтобы это правильно работало? Текущая версия моей конфигурации будет отвечать мне на сервер node ответ, который говорит, что он не может получить ресурс при любом URL-адресе, который я печатаю.

Вот текущая версия моей конфигурации:

<configuration>
  <system.webServer>    
    <handlers>
      <add name="iisnode" path="app.js" verb="*" modules="iisnode" />
    </handlers>    
    <rewrite>
      <rules>
        <rule name="bar">
          <match url="bar/*" />
          <action type="Rewrite" url="app.js" />
        </rule>
      </rules>
    </rewrite>    
  </system.webServer>
</configuration>

Ответы

Ответ 1

Я столкнулся с тем же вопросом некоторое время назад, запуская мое приложение в виртуальном каталоге.

После многого времени потраченного впустую и борьбы я смог собрать все части, чтобы заставить мои приложения работать в виртуальном каталоге, в том числе приложения, использующие Socket.io

Поскольку документации для этого конкретного сценария недостаточно, а доступных ресурсов, которые я нашел, только частично описано, как решить эту проблему. Вот учебник о том, как получить все это. У меня лично есть несколько веб-сервисов Node.js, реализующих либо REST API, либо Socket.io, используя эту настройку.

Я настоятельно рекомендую использовать шаблон Web.config ниже, чтобы заставить это работать.

Шаблон IISNode Web.config

https://gist.github.com/pbaio/f63918181d8d7f8ee1d2

Конфигурация в приведенной выше ссылке содержит некоторые комментарии, которые я привел там, чтобы помочь с легкостью использования. Он настроен на использование app.js в качестве основного файла, но если ваш файл назван чем-то другим, просто переключите значение, чтобы использовать этот файл.

Чтобы получить эту конфигурацию, вам понадобится модуль перезаписи URL-адресов для IIS, если вы еще не установили его.

Настройка по умолчанию

По умолчанию этот шаблон настроен для работы в стандартном веб-приложении, работающем в IIS, а не в среде виртуального каталога. Однако с некоторой незначительной настройкой вы можете использовать тот же Web.config для запуска приложения Node.js в виртуальном каталоге.

Получить Express для использования вашего виртуального каталога

IISNode делает все ключи, объявленные в ваших переменных среды <appSettings>. Мы можем использовать это в наших интересах, чтобы настроить наш путь к виртуальному каталогу и предоставить его нашему основному файлу. В шаблоне выше наш основной файл app.js.

Получить наш путь к виртуальной директории

Нам нужно получить путь, по которому наше приложение будет перенаправлено из нашего файла Web.config. Мы делаем это, обращаясь к нашим переменным среды на нашем объекте процесса. Добавьте следующую строку в наш app.js файл.

var virtualDirPath = process.env.virtualDirPath || '';

Это извлекает наш virtualDirPath из нашего Web.config и присваивает ему значение по умолчанию пустой строки.

Страницы маршрутизации

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

var app = require('express')();
app.get(virtualDirPath + '/', function(req, res) {
  res.render('index', { virtualDirPath: virtualDirPath });
});

В статических материалах

Мы можем легко справиться с этим следующим образом:

app.use(express.static(path.join(virtualDirPath, 'public')));

То же самое, если вы используете Bower.io:

app.use('/bower_components', express.static(path.join(virtualDirPath,'bower_components')));

Использование виртуальных каталогов с Express и Socket.io

При использовании виртуальных каталогов с Socket.io нам необходимо внести изменения в конфигурацию как для Сервера, так и для Клиента.

на стороне сервера

Нам нужно настроить наш Socket.io Server немного иначе, чем обычно.

var app = require('express')();

var virtualDirPath = process.env.virtualDirPath || '';

var server = require('http').Server(app);
var io = require('socket.io')(server, { path: virtualDirPath + '/socket.io' });
// Get the port that we should be listening on
server.listen(process.env.PORT || 8080);

В приведенном выше коде мы модифицируем наш сервер Socket.io для работы с нашим виртуальнымDirpath, а не по умолчанию ('/socket.io' - путь по умолчанию).

Изменения в Web.config

Для того, чтобы IISNode корректно работал с socket.io, нам также необходимо добавить дополнительную ссылку для повторной записи и обменять наш обработчик. Внутри конфигурационного файла шаблона сверху мы видим обработчик Socket.io в строке 57, он закомментирован в шаблоне.

<add name="iisnode-socket.io" path="app.js" verb="*" modules="iisnode" />

Затем нам нужно добавить нашу перезапись URL-адресов для путей Socket.io

<rule name="SocketIO" patternSyntax="ECMAScript">
    <match url="socket.io.+" />
    <action type="Rewrite" url="app.js"/>
</rule>

Client-Side

На стороне клиента нам просто нужно указать путь, который слушает сервер Socket.io, а не его путь по умолчанию.

var socket = io.connect('http://example.com:port', { path: '/virtualDirPath/socket.io' });

В этом случае должно быть хорошо, если приложение Socket.io работает в виртуальном каталоге с IISNode.

Информация о среде

Приложения, использующие эту конфигурацию, были созданы с помощью Node.js, Express 4.12.3 и запущены в IIS 7.5 с установленным IISNode. Кроме того, изменяя обработчик в файле conifg, Socket.io можно также использовать в виртуальном каталоге. Версия Socket.io, используемая в приведенном выше примере, была 1.3.5

Ответ 2

Я столкнулся с этой же проблемой.

В конечном итоге работала с исправлением URL-адреса запроса в моем приложении. Мы перешли от использования express к hapi, поэтому я преобразовал этот код из hapi обратно, чтобы выразить, не тестируя его в первую очередь, но он должен получить вас на стадионе.

app.use(function (req, res, next) {
    if(!settings.serverPath) return next();

    console.log(req.url);
    var regex = new RegExp('(' + settings.serverPath + ')(/.+)', "i");
    req.url = req.url.replace(regex, "$2");
    console.log(req.url);
    return reply.continue();
});

//set up your routes here...