web-dev-qa-db-ja.com

IIS、Node.js、およびIISNodeが仮想ディレクトリで正しく構成されていないWebアプリケーション

IISには次の設定があります。

  • 標準のhtmlサイトをホストするデフォルトのWebサイト(www.foo.com)
  • デフォルトのWebサイト(www.foo.com/bar)の下にあるWebアプリケーションが実行中IISノード
  • ノードプロジェクトはエクスプレスを利用しています

私は一生の間、このことを正しく構成することができないので、Webアプリケーションにアクセスすると、ノードアプリケーションが正しく提供されます。私の問題はweb.configにあると思います。誰かがこれを正しく機能させるために正しいweb.configを書くのを手伝ってもらえますか?現在のバージョンの構成では、入力した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>
16
poindexter12

しばらく前に同じ問題が発生し、仮想ディレクトリでアプリを実行していました。

多くの時間を無駄にし、苦労した後、すべての要素をまとめて、アプリを仮想ディレクトリで動作させることができました。これには、Socket.ioを使用するアプリも含まれます。

この特定のシナリオと利用可能なリソースに関するドキュメントはあまりないので、私が見つけたのは、この問題を解決する方法を部分的にしか説明していないことです。これは、これらすべてを機能させる方法に関するチュートリアルです。私は個人的に、このセットアップを使用してREST APIまたはSocket.ioのいずれかを実装する複数のNode.jsWebサービスを持っています。

これを機能させるには、以下のWeb.configテンプレートを使用することを強くお勧めします。

IISNodeWeb.configテンプレート

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

上記のリンクの設定には、使いやすさを向上させるために私がそこに入れたコメントがいくつかあります。 app.jsをメインファイルとして使用するように構成されていますが、ファイルの名前が異なる場合は、代わりにそのファイルを使用するように値を切り替えるだけです。

この構成を機能させるには、 IIS用のURL書き換えモジュール がまだインストールされていない場合は必要です。

デフォルト設定

デフォルトでは、このテンプレートはIISで実行され、仮想ディレクトリ環境では実行されない標準のWebアプリで機能するように設定されています。ただし、若干の調整を加えることで、この同じWeb.configを使用してノードを実行できます。仮想ディレクトリ内の.jsアプリ。

Expressを入手して仮想ディレクトリを使用する

IISNodeは、<appSettings>環境変数で宣言されたすべてのキーを作成します。これを利用して、仮想ディレクトリパスを設定し、メインファイルに公開できます。上記のテンプレートでは、メインファイルはapp.jsです。

仮想ディレクトリパスを取得する

Web.configファイルで、アプリケーションのルーティング元のパスを取得する必要があります。これを行うには、プロセスオブジェクトの環境変数にアクセスします。 app.jsファイルに次の行を追加します。

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

これにより、Web.configからvirtualDirPathが取得され、デフォルト値の空の文字列が与えられます。

ルーティングページ

次に、virtualDirPathをルートの前に追加し、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サーバーを通常とは少し異なる方法で構成する必要があります。

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サーバーを変更して、デフォルトのパスではなくvirtualDirpathで動作するようにしています('/socket.io'がデフォルトのパスです)。

IISNodeがsocket.ioで適切に機能するためには、URLの書き換えを追加し、ハンドラーを交換する必要もあります。上からのテンプレート構成ファイル内で、57行目にSocket.ioハンドラーがあり、テンプレートでコメントアウトされています。

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

次に、Socket.ioパスのURL書き換えを追加する必要があります

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

クライアント側

クライアント側では、Socket.ioサーバーがリッスンしているパスを、デフォルトのパスではなく指定する必要があります。

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

この時点で、IISNodeを使用して仮想ディレクトリでSocket.ioアプリケーションを実行すると、すべてがうまくいくはずです。

環境情報

この構成を使用するアプリは、Node.js、Express 4.12.3で構築され、IISNodeがインストールされたIIS 7.5で実行されます。さらに、conifgファイルのハンドラーを変更することにより、Socket.ioは次のことができます。仮想ディレクトリでも使用できます。上記の例で使用したSocket.ioのバージョンは1.3.5でした。

24
peteb

静的ファイルを提供できない場合は、ビルドを実行する前にベースのhref urlを仮想ディレクトリパスに変更してから、サーバーから静的ファイルを提供してください。これが誰かに役立つことを願っています。

0
Melvin

私は これと同じ問題 に遭遇しました。

最終的には、アプリケーションのリクエストURLを修正することができました。 Expressの使用からhapiに切り替えたので、最初にテストせずに、このコードをhapiからexpressに戻しましたが、これで問題は解決するはずです。

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...
0
Josh C.