PowerShell Invoke-WebRequestによるHTTPリクエスト入門


PowerShell Invoke-WebRequest による HTTP リクエスト入門:詳細解説

はじめに:Webとの対話 – なぜ PowerShell で HTTP リクエストを行うのか?

現代のシステム運用や自動化において、ネットワーク、特にHTTPを介した他のシステムとの連携は不可欠です。Webサイトからの情報取得、RESTful APIへのアクセス、クラウドサービスとの連携など、様々なタスクでHTTPリクエストが必要になります。

PowerShellは、Windowsシステム管理を中心に広く使われている強力なスクリプト環境ですが、その能力はローカルのファイルシステムやレジストリ操作にとどまりません。豊富なコマンドレット群により、ネットワークプロトコルを介した外部システムとの連携も容易に行えます。その中でも、HTTP/HTTPSプロトコルを扱うための中心的なコマンドレットが Invoke-WebRequest です。

Invoke-WebRequest は、指定したURI(URL)に対してHTTPまたはHTTPSリクエストを送信し、その応答を受け取る機能を提供します。これにより、PowerShellスクリプトから直接Webリソースを取得したり、APIを実行したりすることが可能になります。運用タスクの自動化、データ収集、他のサービスとの連携など、その用途は多岐にわたります。

この記事では、Invoke-WebRequest の基本的な使い方から、HTTPメソッドの使い分け、ヘッダーやボディの操作、認証、セッション管理、エラー処理といった応用的なトピックまで、詳細かつ網羅的に解説します。約5000語のボリュームで、初心者からある程度の経験者まで、Invoke-WebRequest を深く理解し、自在に使いこなすための知識を提供することを目指します。

HTTPプロトコルの基本的な仕組み(クライアントとサーバー、リクエストとレスポンス、メソッド、ヘッダー、ボディなど)についても適宜触れながら説明を進めますので、HTTPにあまり馴染みがない方でも安心して読み進められるでしょう。

さあ、PowerShellを使ってWebの世界と対話する方法を学んでいきましょう。

Invoke-WebRequest の基本:最初の HTTP リクエスト

Invoke-WebRequest を使う最も基本的な形式は、アクセスしたいURI(URL)を指定することです。デフォルトでは、HTTPの GET メソッドが使用されます。

“`powershell

例:MicrosoftのWebサイトにGETリクエストを送信

Invoke-WebRequest -Uri “https://www.microsoft.com/”
“`

このコマンドを実行すると、PowerShellは指定されたURIに対してHTTP GETリクエストを送信し、その応答を受け取ります。コマンドレットは、受け取った応答をオブジェクトとして返します。このオブジェクトには、応答のステータスコード、ヘッダー、ボディ(コンテンツ)、ページ内のリンクやフォームなどの情報が含まれています。

Invoke-WebRequest の出力オブジェクト

Invoke-WebRequest が返すオブジェクトは、多くの有用なプロパティを持っています。これらのプロパティを確認することで、リクエストが成功したか、どのような内容を受け取ったかなどを把握できます。

一般的なプロパティとその意味は以下の通りです。

  • StatusCode: HTTPステータスコード(例: 200 OK, 404 Not Found, 500 Internal Server Error)。リクエストが成功したか失敗したかを判断する上で最も重要です。
  • StatusDescription: ステータスコードに対応する説明テキスト(例: “OK”, “Not Found”)。
  • Content: 応答ボディの内容。通常はHTML、XML、JSONなどのテキストデータですが、バイナリデータの場合もあります。
  • Headers: 応答ヘッダーのコレクション(キーと値のペア)。サーバーの種類、コンテンツタイプ、クッキーなどが含まれます。
  • RawContent: 応答の生のテキスト表現。ステータスライン、ヘッダー、ボディ全体が含まれます。
  • Links: 応答ボディ(HTMLの場合)から抽出されたリンク要素(<a>タグなど)のコレクション。
  • Forms: 応答ボディ(HTMLの場合)から抽出されたフォーム要素(<form>タグ)のコレクション。
  • Images: 応答ボディ(HTMLの場合)から抽出された画像要素(<img>タグ)のコレクション。
  • InputFields: 応答ボディ(HTMLの場合)から抽出された入力フィールド要素(<input>, <select>, <textarea>など)のコレクション。

これらのプロパティを確認することで、リクエストの結果を詳細に分析できます。例えば、ステータスコードを確認するには、以下のようにします。

powershell
$response = Invoke-WebRequest -Uri "https://www.example.com/"
Write-Host "Status Code: $($response.StatusCode)"

応答ボディの内容を確認するには、Content プロパティを使用します。

powershell
$response = Invoke-WebRequest -Uri "https://www.example.com/"
Write-Host "Content (first 500 characters):"
Write-Host $response.Content.Substring(0, [System.Math]::Min(500, $response.Content.Length))

応答ヘッダーを確認するには、Headers プロパティを使用します。これはハッシュテーブルとしてアクセスできます。

powershell
$response = Invoke-WebRequest -Uri "https://www.example.com/"
Write-Host "Response Headers:"
$response.Headers | ForEach-Object {
Write-Host "$($_.Key): $($_.Value)"
}

このように、Invoke-WebRequest の出力オブジェクトを調べることで、Webサーバーからの応答に関する豊富な情報を得られます。

さまざまな HTTP メソッド:GETだけじゃない

HTTPプロトコルは、リソースに対する様々な操作を行うための複数のメソッド(動詞)を定義しています。Invoke-WebRequest はこれらの主要なメソッドをサポートしており、Method パラメータで指定できます。

最も一般的なメソッドは以下の通りです。

  • GET: 指定されたURIのリソースを取得します。データの取得に使用され、一般的にリクエストボディは含みません。
  • POST: 指定されたURIにデータを送信し、リソースを作成したり、特定のアクションを実行したりします。フォームデータの送信やAPIへのデータ送信に広く使われます。リクエストボディを含みます。
  • PUT: 指定されたURIのリソースを、リクエストボディの内容で置き換えます。リソースの更新に使用されます。リクエストボディを含みます。
  • DELETE: 指定されたURIのリソースを削除します。
  • HEAD: GETと似ていますが、応答としてヘッダーのみを返し、ボディは返しません。リソースの存在確認やメタデータの取得に使用されます。
  • OPTIONS: 指定されたURIで利用可能な通信オプションを説明します。
  • PATCH: 指定されたURIのリソースに部分的な変更を適用します。

Method パラメータを指定することで、これらのメソッドを使ってリクエストを送信できます。

“`powershell

例:DELETEリクエストを送信(存在しないリソースを想定)

Invoke-WebRequest -Uri “https://api.example.com/items/123” -Method DELETE
“`

多くの場合、Webサイトからの情報取得にはGET、APIへのデータ送信やリソース作成/更新にはPOSTやPUT、リソース削除にはDELETEが使われます。

POSTやPUTなどのメソッドでは、リクエストボディにデータを含める必要があります。これについては後述します。

リクエストヘッダーの操作:サーバーに情報を伝える

HTTPリクエストヘッダーは、クライアント(PowerShell)からサーバーに対して、リクエストに関する様々なメタデータを伝えるための情報です。例えば、クライアントの種類、受け入れ可能なデータ形式、認証情報などが含まれます。Invoke-WebRequest では、Headers パラメータを使ってカスタムヘッダーを追加したり、既存のヘッダーを上書きしたりできます。

Headers パラメータには、ヘッダー名とその値のペアを要素とするハッシュテーブルを指定します。

“`powershell

例:AcceptヘッダーとCustom-Headerを指定してリクエスト

$headers = @{
“Accept” = “application/json”
“Custom-Header” = “MyValue”
}

Invoke-WebRequest -Uri “https://api.example.com/data” -Headers $headers
“`

よく使われるリクエストヘッダー

  • User-Agent: リクエストを送信しているクライアント(ブラウザやアプリケーション)の種類を識別します。デフォルトでは Invoke-WebRequest が自身の情報を送信しますが、ブラウザからのリクエストを模倣するために変更することもよくあります。
    powershell
    Invoke-WebRequest -Uri "https://www.example.com/" -Headers @{"User-Agent" = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"}
  • Accept: クライアントが受け入れ可能なメディアタイプ(MIMEタイプ)を指定します。例: application/json, text/html, image/png, */* (すべて)。
  • Content-Type: リクエストボディに含まれるデータのメディアタイプを指定します。POSTやPUTなどでボディを送信する際に重要です。例: application/x-www-form-urlencoded, application/json, multipart/form-data.
  • Authorization: 認証情報(ベーシック認証、Bearerトークンなど)を含めます。
  • Cookie: サーバーから受け取ったクッキーを返します。セッション管理に利用されます。
  • Referer: リクエスト元のページのURIを示します。
  • Origin: クロスオリジンリクエストの発生元のオリジンを示します。

ヘッダーを適切に設定することで、サーバーが期待する形式でデータを送信したり、特定の認証を通過したり、Webサイトがボットからのアクセスでないと認識するように振る舞ったりすることができます。

特にAPI連携では、認証トークンを Authorization ヘッダーに含めたり、送信/受信データの形式を Content-TypeAccept ヘッダーで指定したりすることが一般的です。

リクエストボディの送信:データをサーバーに渡す

HTTPリクエストのボディは、クライアントがサーバーに送る実際のデータを含みます。主にPOSTやPUTメソッドで使用され、Webフォームの入力データ、APIへのJSONペイロード、ファイルのアップロードなどがボディに含まれます。

Invoke-WebRequest では、Body パラメータを使ってリクエストボディを指定します。Body パラメータには、いくつかの異なる形式でデータを渡すことができます。

  1. 文字列: シンプルなテキストデータや、JSON/XMLなどの構造化データを文字列として渡します。
    “`powershell
    # 例:JSON文字列をボディとしてPOST
    $jsonBody = @{
    name = “John Doe”
    age = 30
    } | ConvertTo-Json

    Invoke-WebRequest -Uri “https://api.example.com/users” -Method POST -Body $jsonBody -ContentType “application/json”
    ``
    この例では、PowerShellのハッシュテーブルを
    ConvertTo-Jsonコマンドレットを使ってJSON文字列に変換し、それをBodyパラメータに指定しています。また、ContentType` ヘッダーを “application/json” に設定することで、サーバーにボディがJSON形式であることを伝えています。

  2. ハッシュテーブル: Content-Type が “application/x-www-form-urlencoded” の場合、Body パラメータにハッシュテーブルを指定すると、キーと値のペアがURLエンコードされたフォームデータ形式に自動的に変換されてボディとして送信されます。これは、HTMLフォームからのPOSTリクエストでよく使われる形式です。
    “`powershell
    # 例:フォームデータをハッシュテーブルで指定してPOST
    $formData = @{
    username = “myuser”
    password = “mypassword”
    }

    Invoke-WebRequest -Uri “https://www.example.com/login” -Method POST -Body $formData -ContentType “application/x-www-form-urlencoded”

    ContentTypeを指定しなくても、Bodyがハッシュテーブルの場合はapplication/x-www-form-urlencodedと見なされることが多い

    “`
    ハッシュテーブルを使うと、各フィールドを個別に定義できるため便利です。

  3. ファイルパス: ファイルの内容をリクエストボディとして送信したい場合、Body パラメータにファイルパスを指定できます。
    powershell
    # 例:ファイルをボディとしてPOST(例:ファイルアップロード)
    $filePath = "C:\temp\myfile.txt"
    Invoke-WebRequest -Uri "https://api.example.com/upload" -Method POST -Body $filePath -ContentType "text/plain"
    # ファイルアップロードでは、ContentTypeにmultipart/form-dataを使うことも多いが、それはInvoke-RestMethodの方が扱いやすい場合がある。

    この場合、指定されたファイルのバイナリまたはテキストコンテンツがそのままリクエストボディとして送信されます。ContentType はファイルの種類に応じて適切に設定する必要があります。

ContentType パラメータは、リクエストボディの形式をサーバーに伝える上で非常に重要です。サーバーは ContentType ヘッダーを見て、どのようにボディを解釈すればよいかを判断します。主な ContentType の値は以下の通りです。

  • application/x-www-form-urlencoded: キーと値のペアが key1=value1&key2=value2 の形式でURLエンコードされたデータ。HTMLフォームのデフォルトのエンコーディングです。Body にハッシュテーブルを指定した場合に自動的にこの形式で送信されます。
  • application/json: リクエストボディがJSON形式のデータである場合。API連携で広く使われます。
  • text/plain: シンプルなテキストデータ。
  • multipart/form-data: ファイルのアップロードなど、複数の種類のデータを一つのリクエストで送信する場合。HTMLフォームでファイルをアップロードする際のエンコーディングです。Invoke-WebRequestmultipart/form-data を扱うのは少し複雑になるため、後述する Invoke-RestMethod の方が適している場合もあります。

適切な Method, Body, ContentType の組み合わせを選択することが、目的とするリクエストを成功させる鍵となります。

パラメータの渡し方:クエリパラメータとフォームパラメータ

Webリクエストでサーバーにデータを渡す方法には、主に「クエリパラメータ」と「フォームパラメータ(またはボディパラメータ)」があります。

クエリパラメータ

クエリパラメータは、GETリクエストなどでURIの末尾に ?key1=value1&key2=value2 の形式で付加されるパラメータです。リソースを特定したり、フィルタリングやソートの条件を指定したりするのに使われます。

Invoke-WebRequest では、Uri パラメータにクエリパラメータを含んだ完全なURLを指定します。

“`powershell

例:クエリパラメータを指定してGETリクエスト

Invoke-WebRequest -Uri “https://api.example.com/products?category=electronics&limit=10”
“`

URL文字列を直接指定する以外に、Uri オブジェクトを作成して操作することも可能です。これにより、パラメータを動的に生成する際に、URLエンコードなどを考慮する必要がなくなります。

“`powershell

例:UriBuilderを使ってクエリパラメータを構築

$uriBuilder = New-Object System.UriBuilder “https://api.example.com/products”
$query = [System.Web.HttpUtility]::ParseQueryString($uriBuilder.Query)
$query[“category”] = “electronics”
$query[“limit”] = “10”
$uriBuilder.Query = $query.ToString()
$uriWithQuery = $uriBuilder.Uri

Invoke-WebRequest -Uri $uriWithQuery
``
[System.Web.HttpUtility]は .NET Framework のアセンブリSystem.Webに含まれています。PowerShell Core ではSystem.Webがデフォルトでロードされないため、必要に応じてAdd-Type -AssemblyName System.Webのようにロードする必要があります。PowerShell Core (.NET Core/.NET 5+) では[System.Web.HttpUtility]::ParseQueryStringの代わりに[System.Net.Http.Json.JsonContent]::Create($data).ReadAsStringAsync().Resultを使うか、単純に文字列操作で構築し、[uri]::EscapeUriString[uri]::EscapeDataStringでエンコードするのが一般的です。または、複雑な場合はUriBuilderを使いますが、クエリ文字列部分の操作は少し変わります。シンプルには、ハッシュテーブルをクエリ文字列に変換する自作関数や、PowerShell 7以降のUri`オブジェクトの静的メソッドなどを使う方がモダンかもしれません。ここでは最も基本的な文字列指定の例を覚えておけば十分です。

フォームパラメータ(ボディパラメータ)

フォームパラメータは、主にPOSTリクエストのボディに含まれるデータです。HTMLフォームからの送信や、APIへのデータ送信に使われます。前述のように、ContentTypeapplication/x-www-form-urlencoded の場合は Body パラメータにハッシュテーブルを指定することで、キーと値のペアが自動的にエンコードされて送信されます。

“`powershell

例:フォームパラメータをボディとしてPOST

$bodyParams = @{
name = “Alice”
email = “[email protected]
}
Invoke-WebRequest -Uri “https://www.example.com/signup” -Method POST -Body $bodyParams

ContentTypeは指定しなくてもapplication/x-www-form-urlencodedになる

“`

ContentTypeapplication/json など、ハッシュテーブルが自動変換されない形式の場合は、ボディの内容を適切な形式(JSON文字列など)で作成し、それを Body パラメータに文字列として渡します。

どちらのパラメータ形式を使うかは、通信相手のAPIやWebサイトの仕様によって決まります。APIドキュメントなどを確認して、正しい形式でデータを送信することが重要です。

認証:保護されたリソースへのアクセス

多くのWebリソースやAPIは、セキュリティのために認証を要求します。Invoke-WebRequest は、一般的なHTTP認証方法をサポートするためのパラメータを提供しています。

ベーシック認証 (Basic Authentication)

ベーシック認証は、ユーザー名とパスワードをBase64エンコードしてリクエストヘッダーに含めるシンプルな認証方法です。Invoke-WebRequest では、Credential パラメータを使ってベーシック認証を行います。

Credential パラメータには PSCredential オブジェクトを指定します。PSCredential オブジェクトは、ユーザー名とパスワードを含みます。パスワードは平文で指定するのではなく、安全のために ConvertTo-SecureString を使ってセキュア文字列に変換してから New-Object System.Management.Automation.PSCredential でオブジェクトを作成するのが一般的です。

“`powershell

例:ベーシック認証を使ってリクエスト

$username = “myuser”
$password = Read-Host -Prompt “Enter password” -AsSecureString

$credential = New-Object System.Management.Automation.PSCredential($username, $password)

Invoke-WebRequest -Uri “https://api.example.com/protected/resource” -Credential $credential
“`

Read-Host -AsSecureString を使うと、コンソールに入力されたパスワードがアスタリスクで表示され、直接文字列変数に格納されるよりも安全性が高まります。

NTLM認証 (NTLM Authentication)

Windows環境では、統合Windows認証(NTLMやKerberos)が使われることがあります。Invoke-WebRequest は、この認証もサポートしています。

  • 現在のユーザーの資格情報を使用: UseDefaultCredentials スイッチパラメータを指定すると、PowerShellを実行している現在のユーザーのWindows資格情報を使ってNTLM認証やKerberos認証を試みます。
    powershell
    # 例:現在のユーザー資格情報でNTLM認証
    Invoke-WebRequest -Uri "http://intranet-app/resource" -UseDefaultCredentials

    これは、イントラネット上のWebアプリケーションなど、ドメイン環境で統合認証が有効になっている場合に便利です。
  • 特定のユーザーの資格情報を使用: Credential パラメータに別のユーザーの PSCredential オブジェクトを指定することで、そのユーザーとして認証を試みることも可能です。

トークン認証(Bearer Tokenなど)

RESTful APIなどでよく使われるトークン認証(例: OAuth 2.0のBearerトークン)は、通常、リクエストヘッダーの Authorization フィールドにトークンを含める形式をとります。この場合、Headers パラメータを使って認証情報を指定します。

“`powershell

例:BearerトークンをHeadersに含めてリクエスト

$token = “your_access_token_here”
$headers = @{
“Authorization” = “Bearer $token”
}

Invoke-WebRequest -Uri “https://api.example.com/data” -Headers $headers
“`

使用する認証方法は、アクセス先のシステムやAPIの仕様によって異なります。ドキュメントを確認して、適切な認証方法を選択し、Invoke-WebRequest の適切なパラメータを使用してください。

リダイレクトの処理:ページの移動に追従する

Webサーバーは、リクエストされたURIから別のURIにクライアントを誘導するために「リダイレクト」を使用することがあります(例: HTTPからHTTPSへのリダイレクト、ページの移動)。リダイレクトは、HTTPステータスコード3xx(301 Moved Permanently, 302 Found, 307 Temporary Redirectなど)で示されます。

Invoke-WebRequest は、デフォルトでリダイレクトに自動的に追従します。これにより、ユーザーはリダイレクトの存在を意識することなく、最終的な目的のページやリソースを取得できます。

リダイレクトの追従回数を制御する

場合によっては、リダイレクトのループを防いだり、意図しない場所にリダイレクトされるのを避けたりするために、追従する回数を制限したいことがあります。MaximumRedirection パラメータを使うと、リダイレクトの最大追従回数を指定できます。デフォルト値は5です。

“`powershell

例:リダイレクト追従回数を3回に制限

Invoke-WebRequest -Uri “http://old.example.com/page” -MaximumRedirection 3
“`

指定した回数を超えてリダイレクトが発生した場合、Invoke-WebRequest はエラーを発生させます。

リダイレクトの追従を無効にする

リダイレクト先のURIを取得したい場合など、追従を無効にしたい場合は、MaximumRedirection を0に設定します。

“`powershell

例:リダイレクト追従を無効にし、最初のリダイレクト応答を取得

$response = Invoke-WebRequest -Uri “http://old.example.com/page” -MaximumRedirection 0 -ErrorAction SilentlyContinue

if ($response.StatusCode -ge 300 -and $response.StatusCode -lt 400) {
Write-Host “リダイレクトステータスコード: $($response.StatusCode)”
Write-Host “リダイレクト先URI: $($response.Headers[‘Location’])”
} else {
Write-Host “リダイレクトではありませんでした。”
}
“`

ErrorAction SilentlyContinue を指定しているのは、MaximumRedirection 0 でリダイレクトが発生した場合、デフォルトではエラーとなるためです。エラーを抑制し、応答オブジェクトを取得することで、ステータスコードや Location ヘッダーを確認できるようになります。

通常はデフォルトのリダイレクト追従機能で問題ありませんが、特定のリダイレクト処理が必要な場合はこれらのパラメータを活用してください。

セッションの維持:状態を保った連続リクエスト

HTTPは本来ステートレスなプロトコルです。つまり、個々のリクエストは互いに独立しており、サーバーは以前のリクエストの情報を記憶しません。しかし、ログインが必要なサイトや、ショッピングカートのように複数のリクエスト間で状態を維持する必要があるアプリケーションでは、「セッション」という仕組みが使われます。

セッション管理は、主にクッキー(Cookie)を利用して行われます。サーバーは最初のリクエスト応答でクライアントにセッションIDを含むクッキーを渡し、クライアントは以降のリクエストでそのクッキーをサーバーに送り返すことで、サーバーはどのリクエストが同じクライアント(セッション)からのものかを識別します。

Invoke-WebRequest は、SessionVariable パラメータを使うことで、このセッション管理を自動的に行うことができます。

SessionVariable パラメータに変数名を指定すると、Invoke-WebRequest はリクエストと応答の間でやり取りされるクッキーやその他のセッション関連情報を自動的に収集・管理する「セッションオブジェクト」を作成し、指定した変数に格納します。以降のリクエストでこのセッションオブジェクトを使用することで、同じセッションの一部としてリクエストを送信できます。

“`powershell

例:セッションを維持した連続リクエスト

1. ログインページにアクセスし、セッションオブジェクトを作成

$loginUrl = “https://www.example.com/login”
$profileUrl = “https://www.example.com/profile”

SessionVariableでセッションオブジェクト用の変数名を指定

$response = Invoke-WebRequest -Uri $loginUrl -SessionVariable mySession

Write-Host “ログインページにアクセスしました。ステータスコード: $($response.StatusCode)”

2. ログイン情報をPOSTし、セッションオブジェクトを再利用

$loginFormData = @{
username = “myuser”
password = “mypassword”
}

-WebSession パラメータに作成したセッションオブジェクトを指定

$loginResponse = Invoke-WebRequest -Uri $loginUrl -Method POST -Body $loginFormData -WebSession $mySession

Write-Host “ログインリクエストを送信しました。ステータスコード: $($loginResponse.StatusCode)”

3. ログイン後にアクセス可能なプロフィールページに、同じセッションでアクセス

$profileResponse = Invoke-WebRequest -Uri $profileUrl -WebSession $mySession

Write-Host “プロフィールページにアクセスしました。ステータスコード: $($profileResponse.StatusCode)”
Write-Host “プロフィールページの内容 (一部):”
Write-Host $profileResponse.Content.Substring(0, [System.Math]::Min(500, $profileResponse.Content.Length))
“`

この例では、
1. 最初の Invoke-WebRequest-SessionVariable mySession を指定し、mySession という名前のセッションオブジェクトを作成します。この時、ログインページから返されるセッション関連のクッキーなどが $mySession オブジェクトに格納されます。
2. 2番目の Invoke-WebRequest では、-WebSession $mySession を指定しています。これにより、1番目のリクエストで取得したセッション情報(クッキーなど)が自動的にリクエストヘッダーに含められ、ログインPOSTリクエストが送信されます。サーバーは受け取ったクッキーなどを見て、このリクエストが前のステップと同じセッションからのものであると認識します。
3. 3番目の Invoke-WebRequest でも -WebSession $mySession を指定することで、ログイン後のセッション情報(ログイン成功を示すクッキーなど)がリクエストに含まれ、保護されたプロフィールページにアクセスできるようになります。

SessionVariable パラメータで作成されるオブジェクトは Microsoft.PowerShell.Commands.WebRequestSession 型のオブジェクトです。このオブジェクトは、現在のセッションに関連付けられたクッキー (Cookies プロパティ) やヘッダーなどを保持しています。

セッション管理は、複数のリクエストにまたがる一連の操作(例: ログイン → データ取得 → ログアウト)を行う際に非常に重要です。SessionVariable を活用することで、これらの操作を容易にスクリプト化できます。

プロキシ設定:ネットワークの経由点

企業ネットワークなどでは、インターネットへのアクセスがプロキシサーバーを経由するように設定されている場合があります。Invoke-WebRequest もプロキシサーバー経由でのリクエスト送信をサポートしています。

Proxy パラメータにプロキシサーバーのURIを指定します。

“`powershell

例:プロキシ経由でリクエスト

Invoke-WebRequest -Uri “https://www.example.com/” -Proxy “http://myproxy.example.com:8080”
“`

プロキシサーバーが認証を要求する場合、ProxyCredential パラメータにプロキシ認証用の PSCredential オブジェクトを指定します。

“`powershell

例:認証付きプロキシ経由でリクエスト

$proxyUsername = “proxyuser”
$proxyPassword = Read-Host -Prompt “Enter proxy password” -AsSecureString
$proxyCredential = New-Object System.Management.Automation.PSCredential($proxyUsername, $proxyPassword)

Invoke-WebRequest -Uri “https://www.example.com/” -Proxy “http://myproxy.example.com:8080” -ProxyCredential $proxyCredential
“`

システムのインターネットオプションなどでプロキシが設定されている場合、多くの場合 Invoke-WebRequest はそれらの設定を自動的に利用します。ただし、明示的にプロキシを指定したい場合や、システム設定とは異なるプロキシを使用したい場合に Proxy パラメータを使用します。

SSL/TLS 証明書の検証:セキュリティの確保

HTTPS(HTTP Secure)プロトコルは、SSL/TLSを使用して通信を暗号化し、サーバーの身元を証明することで通信のセキュリティを確保します。クライアント(Invoke-WebRequest)は、サーバーから提示されたSSL/TLS証明書が有効であるか、信頼できる証明機関によって発行されているかなどを検証します。

デフォルトでは、Invoke-WebRequest はHTTPSリクエストを送信する際に、サーバー証明書の検証を厳密に行います。証明書が無効である(有効期限切れ、ドメイン名不一致、自己署名証明書など)場合、接続は拒否され、エラーが発生します。これはセキュリティ上の観点から非常に重要な動作です。

証明書検証をスキップする方法(非推奨)

開発環境やテスト環境などで、自己署名証明書を使用しているサーバーにアクセスする必要がある場合など、一時的に証明書の検証をスキップしたい場合があります。しかし、本番環境やセキュリティが重要な場面では絶対に避けるべきです。証明書検証をスキップすると、中間者攻撃(Man-in-the-Middle Attack)などのリスクにさらされる可能性があるためです。

証明書検証をスキップするには、.NETServicePointManager クラスの静的プロパティ ServerCertificateValidationCallback を設定します。これはPowerShellのバージョンに関わらず有効な方法です。

“`powershell

例:一時的に証明書検証をスキップする (非推奨!)

検証を常に成功させるコールバックを設定

[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }

証明書エラーが発生する可能性のあるHTTPSサイトにアクセス

try {
Invoke-WebRequest -Uri “https://self-signed-cert.example.com/”
}
catch {
Write-Host “リクエスト中にエラーが発生しましたが、証明書検証スキップの影響かもしれません。”
Write-Host $_.Exception.Message
}
finally {
# ★★★ 非常に重要 ★★★
# スキップ設定を解除し、デフォルトの検証動作に戻す
# スクリプトの最後に必ず実行すること
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = $null
}
“`

重要: ServerCertificateValidationCallback を設定した場合、そのPowerShellセッション内で以降に行われるすべてのHTTPSリクエスト(Invoke-WebRequestだけでなく、Invoke-RestMethodや.NETのHttpClientなどを含む)に対して設定が有効になります。テストが完了したら、必ず [System.Net.ServicePointManager]::ServerCertificateValidationCallback = $null を実行して設定を解除し、デフォルトの安全な検証動作に戻してください。設定を解除し忘れると、そのPowerShellセッションで行われるすべてのHTTPS通信が危険にさらされます。

PowerShell 6以降では、SkipCertificateCheck というスイッチパラメータが追加されました。これは証明書検証をスキップするより簡単な方法ですが、これも同様にセキュリティリスクを伴うため、使用には十分な注意が必要です。

“`powershell

例:PowerShell 6以降での証明書検証スキップ (非推奨!)

Invoke-WebRequest -Uri “https://self-signed-cert.example.com/” -SkipCertificateCheck
“`

これらの検証スキップ方法は、あくまで開発・テスト目的の一時的な回避策として理解し、本番環境での使用は避けるべきです。正規の証明書を使用するか、自己署名証明書を信頼ストアにインポートするなどの対応を検討してください。

タイムアウト設定:応答がない場合の中断

ネットワークの遅延やサーバーの応答停止などにより、リクエストがいつまでも完了しない状況を避けるため、タイムアウトを設定することは重要です。指定した時間内に応答が得られない場合、リクエストは中断されエラーとなります。

Invoke-WebRequest には、リクエスト全体のタイムアウトを設定するためのパラメータがあります。

PowerShell 7 以降:

PowerShell 7以降では、TimeoutSec パラメータが追加され、より簡単にタイムアウトを秒単位で設定できるようになりました。

“`powershell

例:タイムアウトを30秒に設定 (PowerShell 7+)

Invoke-WebRequest -Uri “https://slow-responding-server.example.com/” -TimeoutSec 30
“`

指定した秒数内にサーバーからの応答がない場合、操作はタイムアウトし、System.Net.WebException または System.TimeoutException などのエラーが発生します。

PowerShell 5.1 (Windows PowerShell) およびそれ以前:

Windows PowerShell 5.1以前には TimeoutSec パラメータがありません。この場合、タイムアウトを設定するには、内部的に使用される.NETのWebRequestクラス(またはHttpWebRequestクラス)を直接操作する必要があります。これは少し複雑になります。

“`powershell

例:タイムアウトをミリ秒単位で設定 (PowerShell 5.1以前、応用)

この方法はWebRequestのPipelineVariable機能などが使えず、より低レベルな操作になります。

$request = [System.Net.WebRequest]::Create(“https://slow-responding-server.example.com/”)
$request.Method = “GET”
$request.Timeout = 30000 # 30秒をミリ秒で指定

必要に応じてHeadersなどを設定することも可能

$request.Headers.Add(“User-Agent”, “…”)

try {
# 応答を取得
$response = $request.GetResponse()

# 応答ストリームからコンテンツを読み取る
$stream = $response.GetResponseStream()
$reader = New-Object System.IO.StreamReader($stream)
$content = $reader.ReadToEnd()

Write-Host "Status Code: $($response.StatusCode)"
Write-Host "Content (first 500 chars): $($content.Substring(0, [System.Math]::Min(500, $content.Length)))"

# リソースを解放
$reader.Close()
$stream.Close()
$response.Close()

}
catch [System.Net.WebException] {
if ($.Exception.Status -eq [System.Net.WebExceptionStatus]::RequestCanceled) {
Write-Host “リクエストがタイムアウトしました。”
} else {
Write-Host “Web Exception: $($
.Exception.Message)”
}
}
catch {
Write-Host “An error occurred: $($_.Exception.Message)”
}
“`

PowerShell 7以降を使用している場合は、TimeoutSec パラメータを使うのが圧倒的に簡単で推奨されます。PowerShell 5.1以前でタイムアウト制御が必要な場合は、上記の.NETクラスを直接使う方法を検討する必要があります。

エラーハンドリング:失敗への対応

HTTPリクエストは様々な理由で失敗する可能性があります。ネットワークの問題、DNSエラー、サーバー側のエラー(5xx)、クライアント側のエラー(4xx)、タイムアウトなどです。スクリプトが予期せず停止しないように、これらのエラーを適切に処理することが重要です。

Invoke-WebRequest でエラーが発生した場合、PowerShellの通常のエラー処理メカニズム(try...catch ブロックなど)で捕捉できます。

HTTPステータスコードによるエラー判定

HTTPリクエストが成功したかどうかは、主に応答の StatusCode プロパティで判断します。一般的に、2xxのステータスコード(例: 200 OK, 201 Created, 204 No Content)は成功を示します。4xx(クライアントエラー)や5xx(サーバーエラー)は失敗を示します。

“`powershell
$response = Invoke-WebRequest -Uri “https://api.example.com/nonexistent” -ErrorAction SilentlyContinue

if ($response.StatusCode -ge 200 -and $response.StatusCode -lt 300) {
Write-Host “リクエスト成功!”
Write-Host “ステータスコード: $($response.StatusCode)”
# 成功時の処理…
} elseif ($response.StatusCode -ge 400 -and $response.StatusCode -lt 500) {
Write-Host “クライアントエラー発生!”
Write-Host “ステータスコード: $($response.StatusCode)”
Write-Host “エラー内容: $($response.Content)” # サーバーがエラー内容をボディに含めている場合
# クライアントエラー時の処理…
} elseif ($response.StatusCode -ge 500 -and $response.StatusCode -lt 600) {
Write-Host “サーバーエラー発生!”
Write-Host “ステータスコード: $($response.StatusCode)”
Write-Host “エラー内容: $($response.Content)”
# サーバーエラー時の処理…
} else {
Write-Host “予期しないステータスコード: $($response.StatusCode)”
}
“`

デフォルトでは、Invoke-WebRequest は4xxや5xxのステータスコードをエラーと見なして、スクリプトを中断する非終端エラーを発生させます。ステータスコードを確認して自身でエラー処理を行うには、ErrorAction SilentlyContinue または ErrorAction Continue などの値を指定して、エラーとして処理されないようにする必要があります。

try…catch ブロックによるエラー捕捉

DNS解決の失敗、ネットワーク接続の確立に失敗、タイムアウトなど、HTTP応答自体が得られないような深刻なエラーが発生した場合、Invoke-WebRequest は終端エラーを発生させ、スクリプトの実行を停止します。このようなエラーは try...catch ブロックで捕捉できます。

powershell
try {
$response = Invoke-WebRequest -Uri "http://nonexistent-domain-or-server/" -TimeoutSec 10
Write-Host "リクエスト成功(到達不能なURLのはずですが...)"
}
catch [System.Net.WebException] {
Write-Host "WebExceptionが発生しました:"
Write-Host " Status: $($_.Exception.Status)"
Write-Host " Message: $($_.Exception.Message)"
# 具体的なWebExceptionStatus値によって、ネットワークの問題か、タイムアウトかなどを判定可能
}
catch {
Write-Host "予期しないエラーが発生しました:"
Write-Host " Exception Type: $($_.Exception.GetType().FullName)"
Write-Host " Message: $($_.Exception.Message)"
}

try ブロック内でエラーが発生した場合、そのエラーに対応する catch ブロックが実行されます。[System.Net.WebException] は、HTTP関連のネットワークエラーやタイムアウトなどで発生することが多い例外です。具体的なエラー情報は $_.Exception オブジェクトから取得できます。

堅牢なスクリプトを作成するには、ステータスコードによる成功/失敗判定と、try...catch によるネットワークレベルのエラー捕捉の両方を適切に組み合わせることが重要です。

応用:JSON/XMLのパース、ファイルのダウンロード

Invoke-WebRequest は生の応答ボディを Content プロパティとして返しますが、このコンテンツが構造化データ(JSONやXML)である場合、PowerShellの他のコマンドレットと組み合わせて簡単にパース(解析)できます。

JSONデータのパース

RESTful APIの多くは、応答ボディとしてJSON形式のデータを返します。PowerShell 3.0以降では、ConvertFrom-Json コマンドレットを使ってJSON文字列をPowerShellのオブジェクト(PSCustomObjectや配列、ハッシュテーブルなど)に変換できます。

“`powershell

例:JSON応答をパースしてPowerShellオブジェクトとして扱う

ダミーのJSON応答を返すサービスを想定

$apiUrl = “https://jsonplaceholder.typicode.com/users/1”

$response = Invoke-WebRequest -Uri $apiUrl
$userObject = $response.Content | ConvertFrom-Json

Write-Host “ユーザー名: $($userObject.name)”
Write-Host “メールアドレス: $($userObject.email)”
Write-Host “都市: $($userObject.address.city)”
“`

$response.Content はJSON文字列なので、それをパイプラインで ConvertFrom-Json に渡すことで、PowerShellで扱いやすいオブジェクト構造に変換されます。

XMLデータのパース

同様に、XML形式の応答は ConvertFrom-Xml コマンドレット(PowerShell 3.0以降)を使ってPowerShellオブジェクトとして扱うことができます。

“`powershell

例:XML応答をパース

ダミーのXML応答を返すサービスを想定

$xmlUrl = “https://www.w3schools.com/xml/simple.xml” # これはダミーURL、実際にはXMLを返すURLを指定

$response = Invoke-WebRequest -Uri $xmlUrl
$xmlObject = $response.Content | ConvertFrom-Xml

Write-Host “最初のフードの名前: $($xmlObject.breakfast_menu.food[0].name)”
Write-Host “最初のフードの価格: $($xmlObject.breakfast_menu.food[0].price)”
“`

ConvertFrom-Xml はXML構造を反映したオブジェクトを作成します。要素名がオブジェクトのプロパティ名になります。

ファイルのダウンロード

Web上のファイルをダウンロードしたい場合も Invoke-WebRequest を使えます。応答の Content プロパティはファイルの内容ですが、バイナリファイルの場合はテキストとして扱うと内容が壊れてしまいます。バイナリコンテンツをそのままファイルに保存するには、OutFile パラメータを使います。

“`powershell

例:ファイルをダウンロードしてローカルに保存

$fileUrl = “https://www.example.com/downloads/myfile.zip”
$outputPath = “C:\Temp\downloaded_file.zip”

Invoke-WebRequest -Uri $fileUrl -OutFile $outputPath

Write-Host “ファイルが $($outputPath) にダウンロードされました。”
“`

OutFile パラメータを使用すると、Invoke-WebRequest は応答ボディを直接指定されたファイルに書き込みます。この場合、コマンドレットの出力オブジェクトは通常のリクエストとは異なり、ダウンロードされたファイルに関する情報などを含むオブジェクトになります。

Invoke-WebRequest vs Invoke-RestMethod:使い分け

PowerShellには、Invoke-WebRequest と非常によく似たコマンドレットに Invoke-RestMethod があります。どちらもHTTPリクエストを送信しますが、応答の扱い方が異なります。この違いを理解することが、適切なコマンドレットを選択する上で重要です。

Invoke-WebRequest:

  • 応答全体(ステータスコード、ヘッダー、コンテンツ、HTML要素など)を詳細なオブジェクトとして返します。
  • Webページの取得、HTML解析(Links, Formsプロパティ)、ファイルのダウンロードなど、HTTP通信のあらゆる側面を制御・調査したい場合に適しています。
  • 応答ボディは基本的に生データ(テキストまたはバイナリ)として Content プロパティに格納されます。JSONやXMLなどの構造化データは、必要に応じて別途 ConvertFrom-JsonConvertFrom-Xml でパースする必要があります。

Invoke-RestMethod:

  • 応答ボディの内容を、可能な限りPowerShellオブジェクトに自動的に変換(パース)して返します。例えば、JSON応答はPSCustomObjectや配列に、XML応答はXMLドキュメントオブジェクトに変換されます。
  • RESTful APIへのアクセスに特化しており、APIから返される構造化データをPowerShell内で直接操作したい場合に非常に便利です。
  • ステータスコードやヘッダーなどのメタデータも取得できますが、Invoke-WebRequest の出力オブジェクトほど詳細なプロパティは提供されません(StatusCodeHeaders は取得可能)。

使い分けの目安:

  • Webページから情報を取得したい(スクレイピングの初歩、リンクやフォームの調査)Invoke-WebRequest が適しています。HTML構造を詳細に分析できるプロパティが役立ちます。
  • APIからデータを取得またはAPIにデータを送信したい(JSONやXMLでのやり取りが多い)Invoke-RestMethod が適しています。応答データの自動パースにより、スクリプトが簡潔になります。
  • ファイル全体をダウンロードしたいInvoke-WebRequestOutFile パラメータが便利です。
  • HTTP通信の詳細な挙動(ヘッダー、リダイレクトプロセス、クッキーのやり取りなど)を厳密に制御・デバッグしたいInvoke-WebRequest がより詳細な情報を提供するため適しています。

多くの場合、API連携には Invoke-RestMethod が使われることが多いですが、Invoke-WebRequest の方が低レベルな詳細にアクセスできるため、より柔軟な制御やデバッグが可能になります。両方のコマンドレットの特性を理解し、目的に応じて使い分けることが重要です。

この記事は Invoke-WebRequest に焦点を当てていますが、RESTful APIを頻繁に扱う場合は Invoke-RestMethod もぜひ学習してください。

実践的な例:外部 API へのアクセス

これまでに学んだ知識を活かして、実際の外部APIにアクセスする例を見てみましょう。ここでは、認証不要で公開されているダミーAPIであるJSONPlaceholder(https://jsonplaceholder.typicode.com/)を使用します。

例1:ユーザー一覧を取得 (GET)

JSONPlaceholderの/usersエンドポイントにGETリクエストを送信し、ユーザー一覧を取得します。応答はJSON形式です。Invoke-WebRequest を使って応答を取得し、ConvertFrom-Json でパースします。

“`powershell
$apiUrl = “https://jsonplaceholder.typicode.com/users”

try {
$response = Invoke-WebRequest -Uri $apiUrl -Method GET

if ($response.StatusCode -eq 200) {
    Write-Host "ユーザー一覧の取得に成功しました。"

    # JSON応答をPowerShellオブジェクトに変換
    $users = $response.Content | ConvertFrom-Json

    Write-Host "取得したユーザー数: $($users.Count)"

    # 各ユーザーの情報を表示
    $users | ForEach-Object {
        Write-Host "ID: $($_.id), 名前: $($_.name), メール: $($_.email)"
    }
} else {
    Write-Host "エラー応答: ステータスコード $($response.StatusCode)"
}

}
catch {
Write-Host “リクエスト中にエラーが発生しました:”
Write-Host $_.Exception.Message
}
“`

例2:新しい投稿を作成 (POST)

JSONPlaceholderの/postsエンドポイントにPOSTリクエストを送信し、新しい投稿を作成します。リクエストボディには、投稿のタイトル、本文、ユーザーIDをJSON形式で含めます。

“`powershell
$apiUrl = “https://jsonplaceholder.typicode.com/posts”

送信するデータ(ハッシュテーブルとして定義)

$postData = @{
title = “My New Post from PowerShell”
body = “This post was created using Invoke-WebRequest in PowerShell.”
userId = 1
}

ハッシュテーブルをJSON文字列に変換

$jsonBody = $postData | ConvertTo-Json

リクエストヘッダーでContent-Typeをapplication/jsonに指定

$headers = @{
“Content-Type” = “application/json”
}

try {
$response = Invoke-WebRequest -Uri $apiUrl -Method POST -Body $jsonBody -Headers $headers

# POSTでリソースが作成された場合、通常201 Createdが返される
if ($response.StatusCode -eq 201) {
    Write-Host "投稿の作成に成功しました。"

    # 作成されたリソースの情報がJSONで返されることが多い
    $createdPost = $response.Content | ConvertFrom-Json

    Write-Host "作成された投稿ID: $($createdPost.id)"
    Write-Host "タイトル: $($createdPost.title)"
} elseif ($response.StatusCode -ge 400) {
     Write-Host "エラー応答: ステータスコード $($response.StatusCode)"
     Write-Host "応答内容: $($response.Content)"
}
else {
    Write-Host "予期しないステータスコード: $($response.StatusCode)"
}

}
catch {
Write-Host “リクエスト中にエラーが発生しました:”
Write-Host $_.Exception.Message
}
“`

これらの例は、Invoke-WebRequest を使って外部サービスと連携する基本的な流れを示しています。実際のAPI連携では、認証、より複雑なデータ構造、エラーレスポンスの詳細なパースなどが必要になりますが、これらの基本を応用することで対応できます。

まとめ:Invoke-WebRequest の強力さと可能性

この記事では、PowerShellの Invoke-WebRequest コマンドレットを使ったHTTPリクエストの基本的な送信から、ヘッダー/ボディの操作、認証、セッション管理、エラーハンドリング、そしてJSON/XMLパースやファイルダウンロードといった応用まで、詳細に解説しました。

Invoke-WebRequest は単にWebページを取得するだけでなく、HTTPプロトコルの様々な要素を細かく制御し、WebサービスやAPIと柔軟に連携するための強力なツールです。Webスクレイピングの初歩、RESTful APIの呼び出し、サービスの死活監視、自動化されたデータ連携など、システム管理や自動化の多くの場面でその能力を発揮します。

HTTPプロトコルの仕様(メソッド、ヘッダー、ステータスコードなど)を理解することで、Invoke-WebRequest の各パラメータがどのように機能するのかが明確になり、より効果的にコマンドレットを使いこなせるようになります。また、PowerShellの他のコマンドレット(ConvertFrom-Json, ConvertFrom-Xml, Out-File など)や、必要に応じて.NET Framework/.NET Coreのクラスと組み合わせることで、さらに高度な処理も実現できます。

この記事で紹介した内容は、Invoke-WebRequest の機能の全てではありませんが、その中核となる部分を網羅しています。これらの知識を基盤として、必要に応じてPowerShellの公式ドキュメントやオンラインリソースを参照しながら、具体的なタスクに合わせて Invoke-WebRequest を活用してみてください。

Webの世界は広大で変化が激しいですが、PowerShellと Invoke-WebRequest を手にすれば、その世界と効果的に対話し、自動化の可能性を大きく広げることができるでしょう。

参考資料:

この記事が、あなたのPowerShellスクリプトにおけるHTTP通信の実装の一助となれば幸いです。


コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

上部へスクロール