JScriptでHTTPアクセス

## はじめに

JScriptでHTTPアクセスする場合、ActiveXObjectとして、「XMLHTTP」「ServerXMLHTTP」の二種類があります。
Microsoftによれば、「XMLHTTP」はクライアント用、「ServerXMLHTTP」はサーバ用となっていますが、
ここでは、タイムアウトなどが指定できる、「ServerXMLHTTP」を利用します。

## GET

簡単なGETのサンプルです。
「open」メソッドの引数は以下となります。

|引数|名前|説明|
|:--:|:--|:--|
|1|method|要求メソッド|
|2|URL|要求先URL|
|3|Async|非同期フラグ、デフォルトは「false」(オプション）|
|4|User|認証ユーザ（オプション）|
|5|Password|認証パスワード（オプション）|

「Async」がデフォルト「false」なので、同期として動作します。
何故、デフォルト値をわざわざ設定しているかというと、「XMLHTTP」の場合はデフォルト「true」なので
コードを流用した時にハマりやすためです。

```js
try {
    // 「ServerXMLHTTP」オブジェクト生成
    var http = new ActiveXObject("Msxml2.ServerXMLHTTP");
    // 要求初期化
    http.open("GET", "http://xxx.xxx.xxx.xxx/yyyyy/", false);
    // 要求
    http.send();
    // 応答結果表示
    WScript.Echo(http.status + ":" + http.statusText);
    WScript.Echo(http.getAllResponseHeaders());
    WScript.Echo(http.responseText);
} catch (e) {
    // エラーの場合
    WScript.Echo("Error(" + (e.number & 0xFFFF) + "):" + e.message);
}
```

## POST

簡単な「POST」のサンプルです。
「GET」との違いは、メソッド名が「POST]になった事と、
要求ヘッダに「Content-Type: application/x-www-form-urlencoded」が必要だということです。
これを設定しないと、サーバ側でパラメータを取得してくれません。

また、パラメータをエスケープする関数も付け加えました。
ほとんどの場合、「encodeURIComponent」だけでも解釈してくれそうですが、
一応、スペースは「%20」ではなく「+」にするのが正しいそうです。

```js
try {
    // 「ServerXMLHTTP」オブジェクト生成
    var http = new ActiveXObject("Msxml2.ServerXMLHTTP");
    // 要求初期化
    http.open("POST", "http://xxx.xxx.xxx.xxx/yyyyy/", false);
    // 要求ヘッダ設定
    http.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    // 要求
    var params = { aaa: "bbb", 111: "222" };
    http.send(escapeParams(params));
    // 応答結果表示
    WScript.Echo(http.status + ":" + http.statusText);
    WScript.Echo(http.getAllResponseHeaders());
    WScript.Echo(http.responseText);
} catch (e) {
    // エラーの場合
    WScript.Echo("Error(" + (e.number & 0xFFFF) + "):" + e.message);
}

function escapeParams(params) {
    var param = "";
    // パラメータ数分ループ
    for (var key in params) {
        // 連結チェック
        if (param.length > 0) {
            param += "&";
        }
        // パラメータ設定
        param += encodeURIComponent(key).split("%20").join("+")
            + "=" + encodeURIComponent(params[key]).split("%20").join("+");
    }
    return param;
}
```

## タイムアウト

タイムアウト値は、「setTimeouts」メソッドで設定します。
設置値の単位は全てミリ秒となっています。
タイムアウトが発生するとErrorとなります。

「setTimeouts」メソッドの引数は以下となります。

|引数|名前|説明|
|:--:|:--|:--|
|1|resolveTimeout|名前解決までのタイムアウト値、デフォルト無限|
|2|connectTimeout|接続タイムアウト値、デフォルト60秒|
|3|sendTimeout|パラメータ送信タイムアウト値、デフォルト30秒|
|4|receiveTimeout|パラメータ受信タイムアウト値、デフォルト30秒|

「0」を設定すると無限に待つっぽいです。

```js
try {
    // 「ServerXMLHTTP」オブジェクト生成
    var http = new ActiveXObject("Msxml2.ServerXMLHTTP");
    // 要求初期化
    http.open("GET", "http://xxx.xxx.xxx.xxx/yyyyy/", false);
    // タイムアウト値設定
    http.setTimeouts(0, 60 * 1000, 30 * 1000, 30 * 1000);
    // 要求
    http.send();
    // 応答結果表示
    WScript.Echo(http.status + ":" + http.statusText);
    WScript.Echo(http.getAllResponseHeaders());
    WScript.Echo(http.responseText);
} catch (e) {
    // エラーの場合
    WScript.Echo("Error(" + (e.number & 0xFFFF) + "):" + e.message);
}
```

Errorでタイムアウト判定が嫌だという場合は、要求を非同期にして、「waitForResponse」メソッドによるタイムアウト待ちをする方法があります。

サンプルコードでは、「readyState」が完了(4)以外の場合、「waitForResponse」メソッドで応答待ちをします。
引数にはタイムアウトを設定できます。ただし、単位が秒なので気をつけて下さい。

また、これは上記の「setTimeouts」も適用されている状態なので、「receiveTimeout」より長い時間を設定した場合
さきに「setTimeouts」のタイムアウトが発生してしまうので注意してください。

```js
try {
    // 「ServerXMLHTTP」オブジェクト生成
    var http = new ActiveXObject("Msxml2.ServerXMLHTTP");
    // 要求初期化
    http.open("GET", "http://xxx.xxx.xxx.xxx/yyyyy/", true);
    // 要求
    http.send();
    // 応答ステータスチェック
    if (http.readyState != 4) {
        // 応答待機
        http.waitForResponse(10);
    }
    // 応答ステータスチェック
    if (http.readyState == 4) {
        // 応答結果表示
        WScript.Echo(http.status + ":" + http.statusText);
        WScript.Echo(http.getAllResponseHeaders());
        WScript.Echo(http.responseText);
    } else {
        // 要求キャンセル
        http.abort();
        // タイムアウト
        WScript.Echo("Timeout");
    }
} catch (e) {
    // エラーの場合
    WScript.Echo("Error(" + (e.number & 0xFFFF) + "):" + e.message);
}
```

## Proxy

Proxyは、バージョン6.0から利用できるようです。したがって、ActiveXObject生成時に6.0を指定します。

「setProxy」メソッドの引数は以下となります。

|引数|名前|説明|
|:--:|:--|:--|
|1|proxySetting|「0」前回を利用又は、自動、「1」HTTP、HTTPSは直接接続、「2」Proxyを利用して接続|
|2|ProxyServer|Proxyサーバ|
|3|BypassList|Proxy適用外のリスト|

引数１の「proxySetting」は「2」以外の挙動についてはよくわかりませんでした。

```js
try {
    // 「ServerXMLHTTP」オブジェクト生成
    var http = new ActiveXObject("Msxml2.ServerXMLHTTP.6.0");
    // 要求初期化
    http.open("GET", "http://xxx.xxx.xxx.xxx/yyyyy/", false);
    // プロクシ設定
    http.setProxy("2", "xxx.xxx.xxx.xxx:yyyy", "localhost");
    // 要求
    http.send();
    // 応答結果表示
    WScript.Echo(http.status + ":" + http.statusText);
    WScript.Echo(http.getAllResponseHeaders());
    WScript.Echo(http.responseText);
} catch (e) {
    // エラーの場合
    WScript.Echo("Error(" + (e.number & 0xFFFF) + "):" + e.message);
}
```

Proxy認証が必要な場合「setProxyCredentials」メソッドで設定できるようです。
実際に試せる環境がなかったので、このメソッドについては検証してません。
したがって、サンプルコードはありません。