133
138

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

curl/PowerShellでHTTPアクセスいろいろ

Last updated at Posted at 2018-09-26

よくわからなくなるのでメモ

  • curl
    • 主に7.3で確認
  • PowerShell
    • 主にversion5(Windows10)で確認 (Windows7標準のver2はInvoke-WebRequestはない)

更新履歴

  • 2019.02.13: リダイレクトについて追加
  • 2019.02.08: 暗号化プロトコルの指定について追記
  • 2018.09.26: HTTPS通信時の証明書の検証を無視する場合を追加

GETする(基本)

  • curl
    • curl https://www.google.com
  • PowerShell
    • Invoke-WebRequest https://www.google.com

GETの結果をファイル出力

  • curl
    • curl https://www.google.com -o output.log
    • ファイル名まであるURLで、保存するファイル名も同じでよければ-Oも使える
      • curl -O https://ftp.gnu.org/gnu/wget/wget-1.19.5.tar.gz
  • PowerShell
    • Invoke-WebRequest https://www.google.com -OutFile output.txt

Invoke-WebRequesthttps://ftp.gnu.org への接続がエラーになる件は後述

リダイレクト制御

  • curl

    • curlはデフォルトではリダイレクトせずにレスポンス302等が返って終了する
    • ファイルのダウンロードなどでリダイレクトも処理してほしい場合は-Lを使う
    • curl -LO https://github.com/zaki-lknr/javaee-memoapp2/archive/v1.0.0.tar.gz
  • PowerShell

    • curlと違ってPowerShellではリダイレクトは勝手に処理される
    • リダイレクトを制限したい場合は-MaximumRedirectionに最大リダイレクト数をセットする(禁止するには0・デフォルトは5)
    • Invoke-WebRequest http://www.jp-z.jp/perlmemo -MaximumRedirection 0
    • ただし「既定の数を超えたリダイレクトのレスポンスがあった」という状態になるため、エラー表示となる
  • powershell curl and WebRequest both follow redirects - Stack Overflow

進捗の非表示

  • curl

    • curl -s http://www.example.org/
    • -s(--silent)を使うとエラーの表示も出なくなるため-S(--show-error)を併用すると良い
      • curl -sS http://www.example.org/
  • PowerShell

    • オプションとしてはない

      $progressPreference = 'silentlyContinue' # progress表示のoff
      Invoke-WebRequest http://www.example.org/
      $progressPreference = 'Continue'         # progress表示のon
      
  • powershell - Invoke-WebRequestの進行を非表示

HTTPのリクエストヘッダとレスポンスヘッダを確認する

  • curl
    • curl -i https://www.example.org
    • curl -v https://www.example.org でも見れる
  • PowerShell
    • Invoke-WebRequestの戻り値がオブジェクトなのでHeadersメンバを参照する

      $resp = Invoke-WebRequest https://www.example.org
      $resp.Headers
      
    • リクエストヘッダはないかも

エラー応答の確認・ハンドリング

  • curl

    • -f(--fail)を使う

      % curl -sSf -O https://ftp.gnu.org/gnu/wget/wget-1.19.5.tar.g 
      curl: (22) The requested URL returned error: 404 Not Found
      % echo $?
      22
      
    • -f無しだとHTTP上のエラーが発生してもcurlコマンド自体は正しく動作しているということで戻り値0になってしまう

  • PowerShell

    • HTTPエラーが発生すると例外がthrowされる

    • catchしていなくても、直近の例外は$error[0]にセットされる

      PS > Invoke-WebRequest http://ftp.gnu.org/gnu/wget/wget-1.19.5.tar.g
      Invoke-WebRequest : Not Found
      The requested URL /gnu/wget/wget-1.19.5.tar.g was not found on this server.
      Apache/2.4.7 (Trisquel_GNU/Linux) Server at ftp.gnu.org Port 80
      発生場所 :1 文字:1
      + Invoke-WebRequest http://ftp.gnu.org/gnu/wget/wget-1.19.5.tar.g
      + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest]WebException
          + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
      PS> $error[0].Exception.Message
      リモート サーバーがエラーを返しました: (404) 見つかりません
      PS> $error[0].Exception.Response.StatusCode.value__
      404
      PS> $error[0].Exception.Response.StatusDescription
      Not Found
      
    • サーバの応答によってはレスポンスを参照できる

      PS > Invoke-WebRequest https://api.chatwork.com/v2/rooms
      Invoke-WebRequest : {"errors":["Invalid API Token"]}
      発生場所 行:1 文字:1
      + Invoke-WebRequest https://api.chatwork.com/v2/rooms
      + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest]、WebException
          + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
      PS > $error[0].ErrorDetails.Message
      {"errors":["Invalid API Token"]}
      PS > $error[0].Exception.Response.StatusCode.value__
      401
      

任意のHTTPリクエストヘッダを付加

  • curl
    • -H "HeaderKey: HeaderValue"を付加
    • 複数ある場合は-Hを複数回付加する
    • curl -H "Authorization: Bearer foobar" -H "X-Header: hogehoge" http://www.example.org
  • PowerShell
    • 連想配列にしたヘッダ情報を引数に-Headers $hashTableを付加
    • Invoke-WebRequest http://www.example.org -Headers @{Authorization: "Bearer foobar"; X-Header: "hogehoge"}

POSTする

key=valueなパラメタでPOST

  • curl
    • -d(--data)を使う
      • curl -XPOST -d 'key1=value1&key2=value2' http://www.example.org
    • -dを複数回使っても良い
      • curl -XPOST -d 'key1=value1' -d 'key2=value2' http://www.example.org
    • -d(--data)の替わりに--data-urlencodeを使えば、パラメタ文字列のURLエンコードをcurlがやってくれる
      • curl -XPOST -d 'key1=value1' --data-urlencode 'key2=/e/' http://www.example.or
        • サーバにはkey1=value1&key2=%2Fe%2Fが送られる
        • --data-urlencode 'key1=value1&key2=/e/'と書くと、&もエンコードされてkey1=value1%26key2%3D%2Fe%2Fになるので注意
  • PowerShell
    • Invoke-WebRequest -Method Post -Body 'key1=value1&key2=value2' http://www.example.org
    • 連想配列にしても可
      • Invoke-WebRequest -Method Post -Body @{key1="value1"; key2="value2"} http://www.example.org
    • 文字列を指定する場合はURLエンコードは自前で処理する必要があるが、連想配列の場合は勝手にやってくれる
      • Invoke-WebRequest -Method Post -Body @{key1="value1"; key2="/e/"} http://www.example.org
        • サーバへはkey1=value1&key2=%2Fe%2FがPOSTされる

JSONなどの任意のBody用文字列丸ごとPOST

前述のkey=valueの場合とやることは同じ

  • curl
    • curl -XPOST -d '{ "key": { "subkey":"value" } }' http://www.example.org
  • PowerShell
    • Invoke-WebRequest -Method Post -Body '{ "album": { "title":"create by api" } }' http://www.example.org

外部ファイルをBodyとして丸ごとPOST

バイナリファイルを送信する場合など。
ファイル指定できるのでそれでPOSTする。
以下、カレントディレクトリから見てPictures/photo.jpgにPostしたいファイルがあるとする。

  • curl
    • curl -XPOST --data-binary @Pictures/photo.jpg http://www.example.org
  • PowerShell
    • Invoke-WebRequest -Method Post -InFile Pictures\photo.jpg http://www.example.org

HTTPS

証明書の検証(エラー)を無視する

テスト環境などでちゃんとした証明書を使ってなかったりDNS設定がない場合など

  • curl
    • -kオプションを使う
    • curl -k https://192.168.0.11
  • PowerShell
    • オプションだけでは実現できなさげ

    • .NET内の検証処理をオーバーライドするコードを追加すれば通る

    • PowershellのInvoke-RestMethodをhttpsに実施すると失敗する - suusan2号の戯れを参照

      add-type @"
          using System.Net;
          using System.Security.Cryptography.X509Certificates;
          public class TrustAllCertsPolicy : ICertificatePolicy {
              public bool CheckValidationResult(
                  ServicePoint srvPoint, X509Certificate certificate,
                  WebRequest request, int certificateProblem) {
                  return true;
              }
          }
      "@
      [System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
      
      Invoke-WebRequest https://192.168.0.11
      

暗号化プロトコルを指定してTLS1.2でアクセス

冒頭の例の https://ftp.gnu.org とか、あと https://qiita.com/ とかも、TLS1.2対応しており、Win10標準のPowerShell 5.1だと(デフォルトでは)対応していない。

PS C:\Users\zaki> Invoke-WebRequest https://ftp.gnu.org/
Invoke-WebRequest : 要求は中止されました: SSL/TLS のセキュリティで保護されているチャネルを作成できませんでした
発生場所 :1 文字:1
+ Invoke-WebRequest https://ftp.gnu.org/
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest]WebExce
    ption
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

PS C:\Users\zaki> Invoke-WebRequest http://qiita.com/
Invoke-WebRequest : 接続が切断されました: 送信時に、予期しないエラーが発生しました。。
発生場所 :1 文字:1
+ Invoke-WebRequest http://qiita.com/
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest]WebExce
    ption
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

現在の暗号化プロトコルの対応状態を表示(SSL3とTLSしか使えない)

PS C:\Users\zaki> [Net.ServicePointManager]::SecurityProtocol
Ssl3, Tls

ただし、設定で追加はできる。追加できるプロトコルはこの通り。

PS C:\Users\zaki> [enum]::GetNames([Net.SecurityProtocolType])
SystemDefault
Ssl3
Tls
Tls11
Tls12

TLS1.2を追加するには「既存設定にTLS1.2の項目を追加」してやる

PS C:\Users\zaki> [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12

これでInvoke-WebRequest https://ftp.gnu.org/Invoke-WebRequest http://qiita.com/すればHTTPアクセスできる。

サイトの暗号化プロトコルの種類を確認するには、Chromeならデベロッパーツールで。

image.png

参考: Windows PowerShellとTLS 1.2 - しばたテックブログ

ちなみにGitHubはTLS1.2を加えてもアクセスできない(反応がない)。
ただしGitHubは-UseBasicParsingを付加して「HTTPアクセスして得られたレスポンスを IEコンポーネントを使って DOM解析を行う」オプションをオフにすればOKだった。

PS C:\Users\zaki> Invoke-WebRequest https://github.com/ -UseBasicParsing


StatusCode        : 200
StatusDescription : OK
Content           :
:
:

ただしこのオプションは、PowerShell 6でdeprecatedになっている。

curlの場合はcurl本体のバージョンやOpenSSLに依存する模様。
超古いサーバーからhttpsにcurlする時 - yamaguchi.txt

オプションとしては次のようなものがある。(curl -hで確認できる)

  • --sslv2
  • --sslv3
  • --tlsv1.2
  • --tlsv1.3
133
138
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
133
138

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?