【REST API連携】MSXML2.ServerXMLHTTP を用いたJSONレスポンスの取得とスクリプト制御によるWebサービス統合
開発現場でふと立ち返るべき現実がある。それは、どれほどモダンなクラウドインフラが構築されようとも、社内のレガシーなWindows端末や閉域網のサーバー群では、いまだにVBScript(WSH)がインフラの接着剤として静かに、しかし強固に稼働し続けているという事実だ。
「なぜ、今さらVBScriptなのか」
そう嘲笑う者もいるだろう。だが、追加のランタイムインストールすら許されない厳格なセキュリティポリシーが敷かれた環境において、OS標準機能だけで動作するVBScriptは、業務自動化の最終防衛ラインとして圧倒的な価値を持つ。
今回は、このVBScriptを用いて外部のREST APIと通信し、JSONレスポンスを安全に取得・制御する極限のテクニックを伝授する。ネット上に散らばる「動くだけの脆いコード」を卒業し、プロダクション環境に耐えうる堅牢なWebサービス統合の設計思想を叩き込んでほしい。
—
1. なぜ `MSXML2.ServerXMLHTTP` なのか?
VBScriptからHTTP通信を行う際、初心者はよく `MSXML2.XMLHTTP` を使いがちだ。しかし、業務自動化エンジニアの視点から言えば、サーバーサイドやタスクスケジューラーでの無人実行において `XMLHTTP` の採用は自殺行為に等しい。
`XMLHTTP` と `ServerXMLHTTP` の決定的な違い
- `MSXML2.XMLHTTP`:
ブラウザ(Internet Explorer)のセキュリティコンテキストやキャッシュ機構を引きずる。非同期処理やUIスレッドとの連動を前提としており、無人実行(WSH)環境では予期せぬダイアログ表示によるフリーズや、セッションの固着を引き起こす。
- `MSXML2.ServerXMLHTTP`(今回採用する真の勝者):
完全に独立したサーバーサイド向けのコンポーネント。UIとの切り離しがされており、厳密なタイムアウト制御、プロキシ認証、SSL/TLSのハンドリングにおいて圧倒的な安定性を誇る。
—
2. 現場で絶対に踏んではいけない「3つの地雷」
API連携スクリプトを書いていて、本番稼働後に突然システムが停止する原因のほとんどは、以下のいずれかを見落としていることにある。
1. 無限ブロック(タイムアウト未設定)
ネットワークの切断やAPIサーバーの障害時、タイムアウトを設定していないHTTPリクエストは無限にスレッドを占有し続けます。WSHスクリプトがゾンビ化し、タスクマネージャーから手動でkillするまでCPUを蝕み続ける悪夢を見たければ、タイムアウトを省略するといい。
2. 文字化け(UTF-8の罠)
VBScriptのネイティブな文字列型はBSTR(UTF-16)だが、モダンなREST APIが返すJSONはほぼ100% `UTF-8` である。`responseText` をそのまま処理すると、日本語が盛大に文字化けするか、パースエラーを引き起こす。`responseBody`(バイト配列)を正確にADODB.Streamでデコードする一手間が不可欠だ。
3. JSONパーサーの不在
VBScriptには、JavaScriptの `JSON.parse` のようなネイティブなJSONパーサーが存在しない。外部のCOMコンポーネントを入れる権限がない環境では、正規表現(RegExp)を用いた擬似パース、もしくは安全なスクリプトエンジンの評価(`Eval`)を駆使してデータを抽出しなければならない。
—
3. 【プロダクションコード】完全堅牢・REST API連携テンプレート
以下のコードは、タイムアウト制御、UTF-8バイナリデコード、そして安全なデータ抽出のロジックをすべて網羅した、そのまま実務に投入できる完成形のVBScriptである。
‘ ==============================================================================
‘ Script Name : RestApiIntegrationTemplate.vbs
‘ Description : MSXML2.ServerXMLHTTP を用いた堅牢なREST API連携サンプル
‘ Author : Chief Architect
‘ ==============================================================================
Option Explicit
‘ — 設定定数 —
Const API_ENDPOINT = “https://jsonplaceholder.typicode.com/todos/1” ‘ 接続先API
Const REQ_TIMEOUT_RESOLVE = 5000 名前解決タイムアウト (ms)
Const REQ_TIMEOUT_CONNECT = 5000 接続タイムアウト (ms)
Const REQ_TIMEOUT_SEND = 10000 送信タイムアウト (ms)
Const REQ_TIMEOUT_RECEIVE = 10000 受信タイムアウト (ms)
Sub Main()
Dim http, jsonText
WScript.Echo “INFO: APIリクエストを開始します -> ” & API_ENDPOINT
‘ 1. HTTPリクエストの実行とレスポンス取得
jsonText = CallRestApi(API_ENDPOINT, “GET”, “”, “”)
If jsonText = “” Then
WScript.Echo “ERROR: APIからのレスポンス取得に失敗しました。”
Exit Sub
End If
WScript.Echo “INFO: レスポンスの取得に成功しました。データを解析します。”
‘ 2. データの抽出(VBScriptにおける擬似パース)
‘ ※本番では正規表現やJScriptオブジェクトの併用で堅牢に抽出する
Dim userId, id, title, completed
userId = ExtractJsonValue(jsonText, “userId”)
id = ExtractJsonValue(jsonText, “id”)
title = ExtractJsonValue(jsonText, “title”)
completed = ExtractJsonValue(jsonText, “completed”)
‘ 3. 業務処理(ログ出力およびファイル・DB連携へのブリッジ)
WScript.Echo “————————————————–”
WScript.Echo ” User ID : ” & userId
WScript.Echo ” ID : ” & id
WScript.Echo ” Title : ” & title
WScript.Echo ” Completed : ” & completed
WScript.Echo “————————————————–”
‘ TODO: ここで取得した変数をDB(ADODB)やCSVファイル出力に渡す
End Sub
‘ ==============================================================================
‘ HTTP通信カプセル化関数(タイムアウト・UTF-8デコード完備)
‘ ==============================================================================
Function CallRestApi(url, method, requestBody, bearerToken)
Dim http
Set http = CreateObject(“MSXML2.ServerXMLHTTP.6.0”)
On Error Resume Next
‘ タイムアウトの設定 (Resolve, Connect, Send, Receive)
‘ ※ミリ秒単位。これを怠るとネットワーク障害時にスクリプトがフリーズします。
http.setOption 2, 1305 ‘ SXH_OPTION_ignore_CERT_DATE_INVALID 等が必要な場合は調整
http.setTimeouts REQ_TIMEOUT_RESOLVE, REQ_TIMEOUT_CONNECT, REQ_TIMEOUT_SEND, REQ_TIMEOUT_RECEIVE
http.Open method, url, False
‘ ヘッダーの設定
http.setRequestHeader “Content-Type”, “application/json; charset=utf-8”
http.setRequestHeader “Accept”, “application/json”
If bearerToken <> “” Then
http.setRequestHeader “Authorization”, “Bearer ” & bearerToken
End If
‘ 送信実行
If method = “POST” Or method = “PUT” Then
http.Send requestBody
Else
http.Send
End If
If Err.Number <> 0 Then
WScript.Echo “HTTP Error (Exception): ” & Err.Description
CallRestApi = “”
Exit Function
End If
On Error GoTo 0
If http.Status <> 200 Then
WScript.Echo “HTTP Error Status: ” & http.Status & ” ” & http.statusText
CallRestApi = “”
Exit Function
End If
‘ 【極めて重要】UTF-8のバイナリ(responseBody)を正確にテキスト化する
Dim stream
Set stream = CreateObject(“ADODB.Stream”)
stream.Type = 1 ‘adTypeBinary
stream.Open
stream.Write http.responseBody
stream.Position = 0
stream.Type = 2 ‘adTypeText
stream.Charset = “utf-8”
CallRestApi = stream.ReadText
stream.Close
Set stream = Nothing
Set http = Nothing
End Function
‘ ==============================================================================
‘ 簡易JSON値抽出関数(正規表現ベース)
‘ ※複雑なネスト構造がないフラットなJSONオブジェクトのパースに最適
‘ ==============================================================================
Function ExtractJsonValue(json, key)
Dim re, matches, val
Set re = New RegExp
‘ ダブルクォーテーションで囲まれたキーに続く値(文字列、数値、真偽値)をキャプチャ
re.Pattern = “””” & key & “””\s:\s(“”([^””])”|([0-9\.]+)|(true|false))”
re.IgnoreCase = True
re.Global = False
If re.Test(json) Then
Set matches = re.Execute(json)
‘ マッチしたグループから実際の値を取り出す
val = matches(0).SubMatches(0)
‘ 前後のダブルクォーテーションを除去
If Left(val, 1) = “””” And Right(val, 1) = “””” Then
val = Mid(val, 2, Len(val) – 2)
End If
ExtractJsonValue = val
Else
ExtractJsonValue = “”
End If
Set re = Nothing
End Function
‘ 実行トリガー
Call Main()
—
4. アーキテクトからの実践的アドバイス:ファイル・DB連携への拡張
上記スクリプトで取得したデータを、単にコンソールに出力して終わるわけにはいかない。実際の業務自動化では、これを基幹データベース(SQL Server / Oracle / Access)へのインサートや、監査ログとしてのCSV出力に繋げる必要がある。
- データベース連携時の注意点:
`ADODB.Connection` を用いる際、APIから取得した文字列にシングルクォート(`’`)が含まれている場合、SQLインジェクションや構文エラーの原因になる。必ず `Replace(val, “‘”, “””)` によるエスケープ処理、または `ADODB.Command` とパラメーターコレクションを使用した安全なバインド変数を活用すること。
- ファイル出力時の文字コード:
CSV等に出力する場合も、VBScript標準の `FileSystemObject` (FSO) の `CreateTextFile` はデフォルトでANSI(Shift-JIS)になるため、API由来の特殊文字や絵文字などが含まれていると文字化けする。ここでも前述の `ADODB.Stream` を用いて `Charset = “utf-8″`(BOM付き/無し)でファイル書き込みを行うのがプロの選択だ。
—
結びにかえて
VBScriptはレガシーな技術と揶揄されがちだが、その本質を理解し、適切なエラーハンドリングとリソース管理(オブジェクトの確実に `Nothing` を代入する作法など)を徹底すれば、現代のクラウドサービスやモダンWebAPIとも互角に渡り合える強力な武器となる。
「動けばいい」という妥協を捨て、障害耐性の高いコードを書くこと。それこそが、現場を真に支える自動化エンジニアの誇りである。さあ、このコードをあなたの環境にデプロイし、堅牢なシステム構築の第一歩を踏み出してほしい。
