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-Type
や Accept
ヘッダーで指定したりすることが一般的です。
リクエストボディの送信:データをサーバーに渡す
HTTPリクエストのボディは、クライアントがサーバーに送る実際のデータを含みます。主にPOSTやPUTメソッドで使用され、Webフォームの入力データ、APIへのJSONペイロード、ファイルのアップロードなどがボディに含まれます。
Invoke-WebRequest
では、Body
パラメータを使ってリクエストボディを指定します。Body
パラメータには、いくつかの異なる形式でデータを渡すことができます。
-
文字列: シンプルなテキストデータや、JSON/XMLなどの構造化データを文字列として渡します。
“`powershell
# 例:JSON文字列をボディとしてPOST
$jsonBody = @{
name = “John Doe”
age = 30
} | ConvertTo-JsonInvoke-WebRequest -Uri “https://api.example.com/users” -Method POST -Body $jsonBody -ContentType “application/json”
``
ConvertTo-Json
この例では、PowerShellのハッシュテーブルをコマンドレットを使ってJSON文字列に変換し、それを
Bodyパラメータに指定しています。また、
ContentType` ヘッダーを “application/json” に設定することで、サーバーにボディがJSON形式であることを伝えています。 -
ハッシュテーブル:
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と見なされることが多い
“`
ハッシュテーブルを使うと、各フィールドを個別に定義できるため便利です。 -
ファイルパス: ファイルの内容をリクエストボディとして送信したい場合、
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-WebRequest
でmultipart/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へのデータ送信に使われます。前述のように、ContentType
が application/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になる
“`
ContentType
が application/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)などのリスクにさらされる可能性があるためです。
証明書検証をスキップするには、.NET
の ServicePointManager
クラスの静的プロパティ 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-Json
やConvertFrom-Xml
でパースする必要があります。
Invoke-RestMethod:
- 応答ボディの内容を、可能な限りPowerShellオブジェクトに自動的に変換(パース)して返します。例えば、JSON応答はPSCustomObjectや配列に、XML応答はXMLドキュメントオブジェクトに変換されます。
- RESTful APIへのアクセスに特化しており、APIから返される構造化データをPowerShell内で直接操作したい場合に非常に便利です。
- ステータスコードやヘッダーなどのメタデータも取得できますが、
Invoke-WebRequest
の出力オブジェクトほど詳細なプロパティは提供されません(StatusCode
やHeaders
は取得可能)。
使い分けの目安:
- Webページから情報を取得したい(スクレイピングの初歩、リンクやフォームの調査):
Invoke-WebRequest
が適しています。HTML構造を詳細に分析できるプロパティが役立ちます。 - APIからデータを取得またはAPIにデータを送信したい(JSONやXMLでのやり取りが多い):
Invoke-RestMethod
が適しています。応答データの自動パースにより、スクリプトが簡潔になります。 - ファイル全体をダウンロードしたい:
Invoke-WebRequest
のOutFile
パラメータが便利です。 - 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
を手にすれば、その世界と効果的に対話し、自動化の可能性を大きく広げることができるでしょう。
参考資料:
- Invoke-WebRequest (Microsoft Docs): https://docs.microsoft.com/ja-jp/powershell/module/microsoft.powershell.utility/invoke-webrequest
- Invoke-RestMethod (Microsoft Docs): https://docs.microsoft.com/ja-jp/powershell/module/microsoft.powershell.utility/invoke-restmethod
- HTTP Messages (MDN Web Docs): https://developer.mozilla.org/ja/docs/Web/HTTP/Messages
この記事が、あなたのPowerShellスクリプトにおけるHTTP通信の実装の一助となれば幸いです。