【初心者向け】curlのリダイレクト紹介と使い方

はい、承知いたしました。curlコマンドのリダイレクト機能について、初心者の方でも理解できるよう、詳細な説明を含む約5000語の記事を作成します。記事の内容を直接表示します。


【初心者向け】curlのリダイレクト紹介と使い方:Web通信の迷子を追跡する秘訣

Webサイトにアクセスしようとしたとき、「あれ?別のページに飛ばされたぞ?」という経験はありませんか?これは「リダイレクト」という仕組みが働いている証拠です。

コマンドラインツールであるcurlを使ってWebサイトの情報を取得する際も、このリダイレクトは非常に重要になります。特に、Webサイトの構造を調べたり、APIの動作を確認したりする場合、リダイレクトを正しく理解し、curlで適切に扱うことが不可欠です。

この記事では、初心者の方に向けて、HTTPリダイレクトの仕組みから、curlコマンドでリダイレクトを扱うための基本的な使い方、そしてさまざまな応用テクニックまでを、ステップバイステップで徹底的に解説します。約5000語にわたる詳細な解説を通じて、curlを使ったWeb通信の理解を深め、リダイレクトという「迷子」を正確に追跡できるようになりましょう。

1. はじめに:Web通信とリダイレクトの重要性

インターネット上のWebサイトは、URL(Uniform Resource Locator)と呼ばれる住所を持っています。ブラウザでURLを入力したり、リンクをクリックしたりすると、そのURLに対応するWebサーバーにアクセスし、ページの情報を取得して表示します。

curlは、このようなWebサーバーとの通信をコマンドラインから行うための非常に強力なツールです。WebページのHTMLを取得したり、ファイルをダウンロードしたり、APIにデータを送信したりと、様々なことができます。

しかし、Webサイトの世界は常に変化しています。ページのURLが変わったり、一時的に別のページに誘導されたりすることがよくあります。このような「別の場所へ案内する」仕組みがリダイレクトです。

リダイレクトがなぜ必要か?

リダイレクトは、Webサイトの運用において様々な目的で利用されます。

  • URLの変更: ページのURLを変更した場合でも、古いURLにアクセスしたユーザーを新しいURLへ自動的に誘導するため。これにより、ブックマークや検索エンジンのリンク切れを防ぎます。
  • サイト移転: Webサイト全体を別のドメインやサーバーに移転した場合に、古いドメインへのアクセスを新しいドメインへ誘導するため。
  • PC版とスマホ版の切り替え: スマートフォンでアクセスしたユーザーを、自動的にスマートフォン向けサイトのURLへ誘導するため。
  • 一時的なページの閉鎖: メンテナンス中など、一時的にページを閉鎖している場合に、告知ページなど別のページへ誘導するため。
  • 負荷分散: アクセスが集中した場合に、複数のサーバーのうち空いているサーバーへ誘導するため。
  • 短縮URL: 長いURLを短くするために、短縮URLサービスが元の長いURLへリダイレクトを利用します。

このように、リダイレクトはWebサイトの利便性やメンテナンス性、そしてユーザー体験を守る上で欠かせない技術です。

curlとリダイレクト

あなたがcurlを使って特定のURLにアクセスしようとしたとき、そのURLが実はリダイレクトの設定がされている場所だったとしたら?

デフォルトのcurlは、リダイレクトが発生しても、自動的にそのリダイレクト先へ追跡してくれません。最初のURLへのリクエストに対する応答(レスポンス)を受け取った時点で処理を終えてしまいます。

しかし、Webサイトの最終的なコンテンツを取得したい場合や、リダイレクトがどのように行われているかを確認したい場合は、リダイレクト先へ自動的に移動して追跡する必要があります。ここで、curlのリダイレクトを扱うためのオプションが登場します。

この記事では、まずリダイレクトの仕組みを理解し、次にcurlでどのようにリダイレクトを「追跡」したり、「制御」したりするのかを詳しく見ていきます。

2. HTTPリダイレクトの仕組み:ステータスコードが鍵

リダイレクトは、HTTP(Hypertext Transfer Protocol)というプロトコルの仕組みを使って行われます。Webサーバーは、クライアント(ブラウザやcurlなど)からのリクエストに対して応答(レスポンス)を返しますが、この応答の中に「ここにアクセスする代わりに、こっちに行ってください」という指示を含めることができます。

この指示は、HTTPのステータスコードLocationヘッダーによって伝えられます。

HTTPステータスコードとは?

HTTPステータスコードは、サーバーからの応答がどのような状態であるかを示す3桁の数字です。例えば、最もよく見る「200 OK」は、「リクエストは成功し、要求された情報が含まれています」という意味です。「404 Not Found」は、「要求されたページは見つかりませんでした」という意味ですね。

リダイレクトを示すステータスコードは、主に「3xx」の範囲のコードが使われます。代表的なものをいくつか見てみましょう。

  • 301 Moved Permanently:
    • 完全に移動しました」。
    • リクエストされたリソース(Webページなど)が、新しい恒久的なURLに完全に移動したことを示します。
    • 検索エンジンは、古いURLの評価やSEOパワーを新しいURLに引き継ぐ傾向があります。
    • クライアント(ブラウザなど)は、次回以降はこの新しいURLに直接アクセスすべきであることを「記憶」する場合があります。
    • 通常、GETリクエストは新しいURLへのGETリクエストとして追跡されます。POSTリクエストも慣例的にGETに変更されることが多いですが、仕様上は元のメソッドを維持することも可能です。
  • 302 Found (以前は Moved Temporarily):
    • 見つかりました」(かつては「一時的に移動しました」と解釈されていました)。
    • リクエストされたリソースが一時的に別のURLにあることを示します。
    • クライアントは、次回も元のURLにアクセスし、再度リダイレクト指示を受けるべきです(ただし、実際にはブラウザによっては301のようにキャッシュすることもあります)。
    • GETリクエスト、POSTリクエストともに、新しいURLへのGETリクエストとして追跡されるのが一般的です。これは歴史的なブラウザの実装に由来します。この挙動は後述の303とは異なります。
  • 303 See Other:
    • 他を参照せよ」。
    • リクエストに対する応答は、別のURLにGETリクエストでアクセスすることで見つかることを示します。
    • 主に、POSTリクエストの直後に使われます。例えば、フォームを送信(POST)した後に、その結果を表示するページ(GET)にリダイレクトする場合などに使われます。これにより、ユーザーがページを再読み込みしても、フォームの再送信を防ぐことができます(Post/Redirect/Getパターン)。
    • リクエストメソッドが何であっても、新しいURLへのリクエストは必ずGETメソッドで行われます。
  • 307 Temporary Redirect:
    • 一時的なリダイレクト」。
    • リクエストされたリソースが一時的に別のURLにあることを示します。302と似ていますが、重要な違いがあります。
    • クライアントは、次回も元のURLにアクセスし、再度リダイレクト指示を受けるべきです。
    • リダイレクト先のURLへのリクエストは、元のリクエストと同じメソッド(GETならGET、POSTならPOSTなど)で行われなければなりません。302のようにPOSTがGETに変更されることはありません。
  • 308 Permanent Redirect:
    • 恒久的なリダイレクト」。
    • リクエストされたリソースが新しい恒久的なURLに完全に移動したことを示します。301と似ていますが、重要な違いがあります。
    • クライアントは、次回以降はこの新しいURLに直接アクセスすべきであることを記憶します。
    • リダイレクト先のURLへのリクエストは、元のリクエストと同じメソッドで行われなければなりません。301のようにPOSTがGETに変更されることはありません。

まとめると、301と308は「恒久的」、302と307は「一時的」なリダイレクトを示します。また、302と303は(特にPOSTからのリダイレクトで)メソッドをGETに変更する傾向がありますが、307と308は元のメソッドを維持します。303は特にPOST後のGETリダイレクトに使われることが多いです。

Locationヘッダーとは?

リダイレクトを示すステータスコード(3xx)が返される場合、サーバーからのレスポンスには必ずLocationヘッダーが含まれています。このヘッダーの値が、リダイレクト先の新しいURLを示しています。

例えば、curlで以下のようなレスポンスを受け取ったとします。

“`
HTTP/1.1 301 Moved Permanently
Server: nginx
Date: Thu, 01 Jan 2023 00:00:00 GMT
Content-Type: text/html
Content-Length: 162
Connection: keep-alive
Location: https://www.example.com/new-page/


301 Moved Permanently

301 Moved Permanently


nginx


“`

このレスポンスを見ると、
* ステータスコードは301 Moved Permanentlyです。
* Locationヘッダーの値はhttps://www.example.com/new-page/です。

これは、「あなたがアクセスしようとしたページは、完全にhttps://www.example.com/new-page/というURLに移動しましたよ」というサーバーからの指示です。

ブラウザは、この301ステータスコードとLocationヘッダーを見ると、自動的に新しいURLへアクセスし直します。しかし、curlのデフォルトの挙動では、このレスポンスを受け取った時点で通信を終了します。レスポンスボディ(上の例の下部HTML)は表示されるかもしれませんが、自動的にhttps://www.example.com/new-page/への通信は行われません。

次章では、このデフォルトの挙動と、それを変更してリダイレクトを追跡する方法を解説します。

3. curlコマンドの基本とデフォルトの挙動

まずは、簡単なcurlコマンドの使い方をおさらいしておきましょう。

最も基本的な使い方は、単にURLを指定して実行するだけです。

bash
curl https://www.example.com/

このコマンドは、https://www.example.com/に対してGETリクエストを送信し、サーバーから返ってきた応答(HTMLなど)を標準出力に表示します。

デフォルトでは、curlは非常にシンプルです。指定されたURLにリクエストを送信し、応答を受け取り、表示する、それだけです。

リダイレクト発生時のデフォルトの挙動

先ほど説明したように、curlはデフォルトではリダイレクトを追跡しません。これは、サーバーがリダイレクトを示す3xx系のステータスコードとLocationヘッダーを返した場合でも同じです。

具体的に見てみましょう。リダイレクトを設定している(または一時的に利用できない)可能性のあるURLに対してcurlを実行してみます。ここでは例として、存在しないパスにアクセスしたり、HTTPからHTTPSへのリダイレクトが設定されているURLなどを想定します。

“`bash

例: HTTPからHTTPSへのリダイレクトが多いサイトのHTTP版URL

curl http://www.example.com/
“`

実行すると、次のような出力が得られるかもしれません(サイトの設定によります)。

“`


Moved

Moved


The document has moved here.

“`

これはHTMLの出力だけですが、実際にはその前にHTTPヘッダーが返されています。ヘッダーを含めて表示するには、-i または --include オプションを使います。

bash
curl -i http://www.example.com/

出力例:

“`
HTTP/1.1 301 Moved Permanently # <– ステータスコードが301
Date: Thu, 01 Jan 2023 00:00:00 GMT
Server: Apache
Location: https://www.example.com/ # <– リダイレクト先のURL
Content-Length: 231
Content-Type: text/html; charset=iso-8859-1



301 Moved Permanently

Moved Permanently

The document has moved to https://www.example.com/.

“`

-i オプションを付けることで、HTTPヘッダーが表示されました。

  • HTTP/1.1 301 Moved Permanently:ステータスコードが301であることがわかります。
  • Location: https://www.example.com/:リダイレクト先がhttps://www.example.com/であることがわかります。

curlは確かにこの301応答を受け取り、ヘッダーとボディを表示していますが、自動的にhttps://www.example.com/へ再度リクエストを送ることはしていません。 これがcurlのデフォルトの挙動です。

つまり、デフォルトのcurlは「サーバーがリダイレクト指示を出したよ」という情報を教えてくれるだけで、その指示に従って別の場所へ移動することはしないのです。

もしあなたがWebサイトの最終的なコンテンツを取得したいのであれば、このままでは目的を達成できません。次のセクションで、この挙動を変え、リダイレクトを追跡する方法を見ていきましょう。

4. curlでリダイレクトを追跡する:-Lオプション

curlにリダイレクトを自動的に追跡させるための最も重要なオプションが、-L または --location オプションです。

このオプションを付けてcurlを実行すると、サーバーから3xx系のステータスコード(301, 302, 303, 307, 308など)とLocationヘッダーを受け取った場合に、curlは自動的にそのLocationヘッダーで指定されたURLに対して再度リクエストを送信します。この処理は、最終的に3xx以外のステータスコード(通常は200 OK)が返されるまで繰り返されます。

-Lオプションの基本的な使い方

先ほどの例に-Lオプションを追加してみましょう。

bash
curl -L http://www.example.com/

このコマンドを実行すると、curlはまずhttp://www.example.com/にアクセスします。サーバーから301レスポンスとLocation: https://www.example.com/というヘッダーが返されると、curl -Lはこれを受け取り、次に自動的にhttps://www.example.com/に対してリクエストを送信します。そして、https://www.example.com/からの最終的な応答(例えば200 OKとHTMLコンテンツ)を受け取って、それを標準出力に表示します。

つまり、-Lオプションを使うことで、ユーザーはリダイレクトの途中のURLを意識することなく、最終的な目的地のコンテンツを取得できるようになります。

-Lオプション使用時の詳細な挙動(重要!)

-Lオプションは便利ですが、その内部的な挙動にはいくつか注意点があります。特に、リダイレクト先のURLへのリクエスト時に、元のリクエストのメソッド(GET, POSTなど)やボディ、ヘッダーがどのように引き継がれるかは、理解しておくべき重要なポイントです。

リダイレクト時の挙動は、返された3xxステータスコードの種類によって異なります。

  1. 301 (Moved Permanently) および 302 (Found):

    • これらのステータスコードを受け取った場合、curl -Lはリダイレクト先のURLにGETメソッドでリクエストを送信します。
    • これは、元のリクエストがGETであろうとPOSTであろうと、DELETEであろうと関係なく、常にGETになります。
    • 元のリクエストのボディ(POSTで送信したデータなど)は、リダイレクト先のGETリクエストには引き継がれません。
    • 元のリクエストのヘッダー(CookieAuthorizationなど)は、通常、新しいリクエストにも引き継がれます。ただし、セキュリティ上の理由から、プロトコル(HTTP/HTTPS間など)やホストが変わる場合に一部のヘッダーが引き継がれない設定もあります(後述の--location-trustedで制御可能)。
  2. 303 (See Other):

    • このステータスコードを受け取った場合、curl -Lはリダイレクト先のURLに常にGETメソッドでリクエストを送信します。
    • これは仕様通りの挙動であり、元のリクエストがGET以外(特にPOST)であっても、リダイレクト先は必ずGETになります。
    • ボディは引き継がれません。ヘッダーの引き継ぎ挙動は301/302と同様です。
  3. 307 (Temporary Redirect) および 308 (Permanent Redirect):

    • これらのステータスコードを受け取った場合、curl -Lはリダイレクト先のURLに元のリクエストと同じメソッドでリクエストを送信します。
    • 元のリクエストがPOSTであれば、リダイレクト先へのリクエストもPOSTになります。PUTならPUT、DELETEならDELETEとなります。
    • 元のリクエストのボディも、リダイレクト先の同じメソッドのリクエストに引き継がれます。
    • ヘッダーの引き継ぎ挙動は301/302/303と同様です。

まとめると:

  • 301, 302, 303 でのリダイレクト追跡時は、次のリクエストメソッドはGETになるのが標準的な挙動です。
  • 307, 308 でのリダイレクト追跡時は、次のリクエストメソッドは元のメソッドと同じになります。

この違いは、特にPOSTリクエストを送信した後にリダイレクトが発生する場合に重要です。

  • POST -> 301/302/303 -> GET (新しいURLへGETで再アクセス)
  • POST -> 307/308 -> POST (新しいURLへPOSTで再アクセス、元のボディも送信される)

WebサイトやAPIによっては、POST後のリダイレクトでPOSTメソッドとボディを引き継いで欲しい場合(307/308)、またはPOSTは完了して結果をGETで表示するページに遷移して欲しい場合(303)があります。curl -Lがどのステータスコードでどのように振る舞うかを理解しておくことは、意図通りの通信を行う上で不可欠です。

もし、301や302でリダイレクトされた場合でも、POSTリクエストとそのボディを維持したままリダイレクトを追跡させたい場合は、後述する--post301などのオプションを使う必要があります。しかし、これは標準的な挙動ではないため、注意が必要です。基本的には、Webサーバーが307または308を返すことで、POSTメソッド維持のリダイレクトを指示します。

最大リダイレクト回数を制限する:--max-redirs

Webサイトの設定ミスなどにより、リダイレクトが無限ループしてしまうことがあります(例: A → B → A → B …)。curl -Lは、このような無限ループに陥ると、いつまでもリダイレクトを追跡し続けてしまい、コマンドが終了しなくなってしまいます。

これを防ぐために、curlはデフォルトでリダイレクトの追跡回数に上限を設けています。この上限はデフォルトで50回です。もし50回を超えてもリダイレクトが続く場合、curlはエラー(”Maximum (50) redirects followed”のようなメッセージ)を出力して終了します。

この上限値を変更したい場合は、--max-redirs <回数> オプションを使用します。

“`bash

最大10回の追跡に制限する

curl -L –max-redirs 10 http://www.example.com/
“`

リダイレクトの多いサイトで、デフォルトの50回では足りない場合や、逆に意図しない無限ループの可能性を考慮して、もっと少ない回数で制限したい場合などに便利です。

リダイレクト情報を表示する:-vオプション

-Lオプションでリダイレクトを追跡しているとき、実際にはどのようなリクエストが送られ、どのようなレスポンスが返されているのか、途中の過程を確認したい場合があります。

このようなデバッグや調査に役立つのが、-v または --verbose オプションです。このオプションを付けると、curlが行っている通信の非常に詳細な情報が表示されます。これには、送信しているリクエストヘッダー、受信したレスポンスヘッダー、接続情報などが含まれます。

-L-vを組み合わせて実行してみましょう。

bash
curl -L -v http://www.example.com/

出力例(一部抜粋、実際の出力はより詳細で長くなります):

“`
* Trying 93.184.216.34:80…
* Connected to www.example.com (93.184.216.34) port 80 (#0)

GET / HTTP/1.1
Host: www.example.com
User-Agent: curl/7.81.0
Accept: /

  • Mark bundle as not supporting multiuse
    < HTTP/1.1 301 Moved Permanently # <– 最初のレスポンス (301)
    < Date: Thu, 01 Jan 2023 00:00:00 GMT
    < Server: Apache
    < Location: https://www.example.com/ # <– リダイレクト先URL
    < Content-Length: 231
    < Content-Type: text/html; charset=iso-8859-1
    <
  • Issue another request to this URL: ‘https://www.example.com/’ # <– curlがリダイレクトを追跡している!
  • Closing connection 0
  • Trying 93.184.216.34:443…
  • Connected to www.example.com (93.184.216.34) port 443 (#1)
  • ALPN: offers h2
  • ALPN: offers http/1.1
  • TLSv1.3 (OUT), TLS handshake, Client hello (1):
    … (TLS/SSL handshake details) …
  • TLSv1.3 (IN), TLS handshake, Server hello (2):
  • TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
  • TLSv1.3 (IN), TLS handshake, Certificate (11):
  • TLSv1.3 (IN), TLS handshake, CERT verify (15):
  • TLSv1.3 (IN), TLS handshake, Finished (20):
  • TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
  • TLSv1.3 (OUT), TLS handshake, Finished (20):
  • SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
  • ALPN: server accepted h2
  • Server certificate:
    … (Certificate details) …
    GET / HTTP/2 # <– 2回目のリクエスト (HTTPS, HTTP/2)
    Host: www.example.com
    user-agent: curl/7.81.0
    accept: /

  • using HTTP/2
    < HTTP/2 200 # <– 2回目のレスポンス (200 OK)
    < date: Thu, 01 Jan 2023 00:00:00 GMT
    < server: Apache
    < last-modified: Tue, 01 Jan 2019 00:00:00 GMT
    < etag: “2d-504b9f34950c0”
    < accept-ranges: bytes
    < content-length: 45
    < content-type: text/html
    <

  • Connection #1 to host www.example.com left intact
    “`

-vオプションの出力を見ると、以下のことがわかります。

  • 最初のhttp://www.example.com/へのリクエスト(> GET / HTTP/1.1)と、その応答(HTTP/1.1 301 Moved Permanently)。
  • 応答に含まれるLocation: https://www.example.com/ヘッダー。
  • curlが「Issue another request to this URL: ‘https://www.example.com/’」というメッセージを出力し、リダイレクト先へ追跡を開始したこと。
  • 新しい接続が確立され(Connected to www.example.com (...) port 443 (#1))、TLS/SSLハンドシェイクが行われたこと。
  • リダイレクト先のhttps://www.example.com/へのリクエスト(> GET / HTTP/2)と、その応答(HTTP/2 200)。
  • 最終的に200 OKを受け取って通信が終了したこと。

このように、-vオプションはcurl -Lがどのようにリダイレクトを追跡しているかを「見える化」するのに非常に役立ちます。どのURLにリダイレクトされ、どのステータスコードが返され、メソッドがどうなっているかなどが詳細に確認できます。

リダイレクト先のURLだけを知る方法

最終的なコンテンツではなく、単にリダイレクトチェーンの最終的なURLだけを知りたい場合もあります。例えば、短縮URLが展開されてどのURLになるかを確認したい場合などです。

これを行うには、-Lオプションに加えて、以下のオプションを組み合わせます。

  • -I または --head: レスポンスのヘッダーのみを取得し、ボディを取得しません。
  • -s または --silent: 進行状況メーターやエラーメッセージ以外の出力を抑制します(通常のリダイレクト追跡時の途中経過メッセージなども抑制されます)。

“`bash

例: goo.glの短縮URL (現在はサービス終了していますが、概念として)

curl -L -s -I http://goo.gl/XXXXX
“`

このコマンドは、まずhttp://goo.gl/XXXXXにアクセスし、-Lオプションでリダイレクトを追跡します。-sオプションで余計な出力を抑制しつつ、-Iオプションで最終的なURLのヘッダーのみを取得します。

最終的なレスポンスのヘッダーには、そのページの最終的なURLは含まれていません。最終的なURLを知るには、追跡の過程でcurlがアクセスした最後のURLを表示させる必要があります。これには、後述の-wオプションが非常に便利です。

5. リダイレクト情報を抽出する:-wオプション

curl-w または --write-out オプションは、通信完了後に、事前に定義された変数を使って情報を整形して出力するための強力な機能です。リダイレクトに関する様々な情報を取得するのに非常に役立ちます。

-wオプションには、出力したい情報を定義する文字列を指定します。この文字列の中に、特定の情報に対応する変数を埋め込みます。

リダイレクトに関連する主な変数を見てみましょう。

  • %{url_effective}: リクエストが最終的にアクセスしたURL。リダイレクトを追跡した場合、これはリダイレクトチェーンの最後のURLになります。
  • %{num_redirects}: リダイレクトが発生した回数。
  • %{redirect_url}: 最後にサーバーから返されたLocationヘッダーの値。リダイレクトチェーンの最後のURL ではありません。もし最後のレスポンスがリダイレクトでなかった場合(例: 200 OK)、この変数は空になります。複数のリダイレクトがあった場合、これは最後の3xx応答のLocationです。%{url_effective}と混同しやすいので注意が必要です。
  • %{http_code}: 最後の応答のHTTPステータスコード。
  • %{size_download}: ダウンロードされたボディの合計サイズ(バイト)。リダイレクト先のボディサイズも含まれます。
  • %{time_total}: リクエスト開始から完了までの合計時間(秒)。リダイレクト中の全ての通信時間を含みます。

これらの変数を組み合わせて、リダイレクトの様子をレポートとして出力できます。

%{url_effective}を使って最終的なURLを取得する

短縮URLを展開したり、リダイレクト先のURLだけを知りたい場合に最もよく使うのが%{url_effective}変数です。

-Lオプションでリダイレクトを追跡し、-sオプションで通常出力を抑制し、-wオプションで%{url_effective}だけを出力するように指定します。出力の最後に改行を入れるために\nも追加するのが一般的です。

“`bash

例: 短縮URLを展開して最終URLを表示

curl -L -s -w “%{url_effective}\n” http://goo.gl/XXXXX
“`

このコマンドは、リダイレクトを追跡した結果、最終的にアクセスしたURLだけを表示します。ボディの内容は表示されません。短縮URLサービスやリダイレクト設定されたURLの「中身」を知りたい場合に非常に役立ちます。

リダイレクトの回数や最終ステータスコードなどをまとめて表示する

複数の変数を使って、リダイレクトの状況を詳しく確認することもできます。

bash
curl -L -s -w "Effective URL: %{url_effective}\nRedirects: %{num_redirects}\nFinal HTTP Code: %{http_code}\nLast Redirect URL: %{redirect_url}\nTotal Time: %{time_total}s\n" http://www.example.com/

出力例(http://www.example.com/https://www.example.com/に301リダイレクトされる場合):

Effective URL: https://www.example.com/
Redirects: 1
Final HTTP Code: 200
Last Redirect URL: https://www.example.com/
Total Time: 0.123456s

この出力から、以下のことがわかります。

  • 最終的にアクセスしたURLはhttps://www.example.com/です。
  • リダイレクトは1回発生しました。
  • 最終的なレスポンスのステータスコードは200です。
  • 最後の(そして今回の唯一の)リダイレクト指示のLocationヘッダーはhttps://www.example.com/でした。
  • コマンドの実行にかかった合計時間は約0.12秒でした。

もしリダイレクトが複数回発生する場合、%{num_redirects}は増加し、%{url_effective}はリダイレクトチェーンの最後のURLになります。%{redirect_url}は、リダイレクトチェーンの中で最後に返された3xx応答のLocationヘッダーの値です。

例えば、http://siteAhttp://siteB (302) → https://siteC (301) → https://siteC/final (200) というリダイレクトチェーンがあった場合、%{num_redirects}は2となり、%{url_effective}https://siteC/final%{redirect_url}https://siteC/finalhttps://siteCからの301応答に含まれるLocationヘッダーの値)になるでしょう。

-wオプションと各種変数を活用することで、リダイレクトの追跡結果をプログラムで処理しやすい形式で取得したり、レポートとして確認したりすることが可能になります。

-wオプションには、他にも様々な変数があります(%{speed_download}, %{time_connect}, %{local_ip}, %{remote_ip}など)。詳細については、curlのmanページや公式ドキュメントを参照してください。

6. POSTリクエストとリダイレクトの高度な制御

先ほど、-Lオプション使用時のリダイレクト追跡におけるメソッドの挙動(301/302/303はGETへ変更、307/308はメソッド維持)について説明しました。通常はこの挙動で問題ありませんが、特殊なケースでこのデフォルト挙動を変更したい場合があります。

これは少し上級者向けの内容になりますが、詳細な説明のため、関連するオプションを紹介します。

301/302リダイレクト時にPOSTメソッドを維持する

HTTP/1.1の仕様では、301と302リダイレクトが発生した場合、クライアントはリダイレクト先のURLにGETメソッドでリクエストを再送信するのが一般的です。しかし、古いHTTP/1.0のクライアントや一部のサーバー実装では、302リダイレクト時にPOSTメソッドを維持してリダイレクト先へ再送信するケースもありました。この挙動は曖昧さを生んだため、HTTP/1.1では303 (GETへ変更) と307 (メソッド維持) が導入されました。

しかし、互換性や特定のサーバーの挙動に対応するために、curlでは301や302でリダイレクトされた場合でも、元のPOSTメソッドを維持してリダイレクト先へリクエストを送信させるオプションが用意されています。

  • --post301: 301リダイレクト時に、POSTメソッドを維持して追跡します。
  • --post302: 302リダイレクト時に、POSTメソッドを維持して追跡します。
  • --post303: 303リダイレクト時に、POSTメソッドを維持して追跡します。これは303の本来の仕様(GETへ変更)とは異なる挙動です。

これらのオプションは-Lまたは--locationと一緒に使用します。

“`bash

301リダイレクト時でもPOSTを維持

curl -L –post301 -X POST -d “data=…” http://www.example.com/post-target

302リダイレクト時でもPOSTを維持

curl -L –post302 -X POST -d “data=…” http://www.example.com/post-target

303リダイレクト時でもPOSTを維持 (非推奨)

curl -L –post303 -X POST -d “data=…” http://www.example.com/post-target
“`

これらのオプションを使う場合は、サーバーがその挙動を想定しているか確認が必要です。通常、POSTメソッドの維持を意図したリダイレクトには307または308が使われるべきです。これらの--postXXXオプションは、非標準的な挙動をするサーバーへの対応など、特定の状況下でのみ利用を検討してください。

プロトコルやホストを跨ぐリダイレクトでのヘッダー引き継ぎ:--location-trusted

デフォルトでは、curl -Lはリダイレクトを追跡する際に、元のリクエストのヘッダー(特に認証情報を含むもの、例: Authorization, Cookie)を新しいリクエストに引き継ぎます。しかし、セキュリティ上の考慮から、リダイレクトによってプロトコル(HTTPからHTTPS、またはその逆)やホスト名が変わる場合、curlは一部のヘッダーを引き継がないことがあります。これは、信頼できないサイトへ認証情報が漏洩するリスクを減らすための措置です。

もし、プロトコルやホストが変わるリダイレクトの場合でも、すべてのヘッダーを無条件に引き継ぎたい場合は、--location-trustedオプションを使用します。

“`bash

プロトコル/ホストを跨ぐリダイレクトでもヘッダーを引き継ぐ

curl -L –location-trusted -H “Authorization: Bearer xxx” http://old-domain.com/secure-resource
“`

このオプションは、リダイレクト先のURLが完全に信頼できる場合にのみ使用してください。例えば、自社のWebサイト内でドメインが異なるサブシステム間をリダイレクトする場合などです。信頼できない外部サイトへのリダイレクトでこのオプションを使うと、機密情報(認証トークンなど)が漏洩するリスクがあります。

7. 具体的な使用例

これまでに学んだことを活かして、いくつかの具体的な使用例を見てみましょう。

例1:短縮URLがどこへ行くか調べる

Twitterなどで見かける短縮URLが、最終的にどのサイトのどのページに繋がっているのか確認したい場合。

bash
curl -L -s -w "%{url_effective}\n" https://bit.ly/XXXXX # 実際のbit.lyの短縮URLに置き換えてください

-Lで追跡し、-sで標準出力を抑制、-wで最終的なURLだけを出力します。

例2:リダイレクトチェーンと最終ステータスを確認する

あるURLがどのようにリダイレクトされているか、そして最終的なステータスコードは何になっているかを確認したい場合。

bash
curl -L -v -s -w "Final URL: %{url_effective}\nRedirects: %{num_redirects}\nFinal Status: %{http_code}\n" http://some-url-that-redirects.com/

-Lで追跡、-vで詳細な通信過程を表示、-sで通常のコンテンツ出力を抑制、-wで最終情報サマリーを表示します。-v-sを同時に使うと、冗長な出力は抑制しつつ、リクエスト/レスポンスのヘッダーなどの詳細情報のみがstderrに表示されるため、デバッグに便利です。

例3:POSTリクエスト後のリダイレクト挙動を確認する

ユーザー登録フォームなど、POSTリクエストを送信した後のリダイレクトがどのように処理されるかを確認したい場合。

bash
curl -L -v -X POST -d "username=testuser&password=testpass" http://example.com/register

-Lで追跡、-vで詳細表示、-X POSTでPOSTメソッド指定、-d "..."でPOSTデータを送信します。出力される-v情報を見て、リダイレクト時のステータスコード(301, 302, 303, 307, 308など)と、それに続くリクエストのメソッド(GETかPOSTか)を確認します。

例4:リダイレクトの回数に上限を設けてテストする

リダイレクトが多いサイトや、無限ループの可能性があるサイトをテストする際に、意図的にリダイレクト回数を制限したい場合。

“`bash

最大3回まで追跡

curl -L –max-redirs 3 http://long-redirect-chain.com/
“`

リダイレクトが4回以上発生すると、curlはエラーで終了します。

例5:HTTPSリダイレクトと証明書検証の確認

HTTPからHTTPSへのリダイレクトが正しく行われるか、そしてHTTPS接続時の証明書検証が成功するかを確認したい場合。

bash
curl -L -v http://www.secure-site.com/

-LでHTTPからHTTPSへのリダイレクトを追跡し、-v出力でTLS/SSLハンドシェイクの過程や証明書情報、検証結果を確認します。もし証明書エラーが発生する場合は、-v出力にその旨が表示されます。

8. 注意点とトラブルシューティング

curl -Lは非常に便利な機能ですが、使う上でいくつか注意すべき点や、トラブルシューティングの際に知っておくと良いことがあります。

無限リダイレクトループ

Webサイトの設定ミスにより、リダイレクトが無限に繰り返されることがあります(例: http://example.com/pagehttps://example.com/pagehttp://example.com/page …)。

curl -Lはデフォルトで50回のリダイレクトまで追跡しますが、これを超えると同じURLが繰り返されている場合などに無限ループ状態となり、CPUリソースを消費したり、タイムアウトしたりする可能性があります。

対策:

  • -vオプションを使って、リダイレクトチェーンがどのように繰り返されているか確認する。
  • --max-redirsオプションで、リダイレクトの最大追跡回数を明示的に、必要最低限の回数に制限する。
  • 対象のWebサイト管理者に設定ミスの可能性を報告する。

HTTPSリダイレクト時の証明書エラー

HTTPからHTTPSへのリダイレクトが発生し、リダイレクト先のHTTPS接続でSSL/TLS証明書の問題(期限切れ、ホスト名不一致、自己署名証明書など)があると、curlはデフォルトでエラーを出力して接続を中断します。

“`
curl: (60) SSL certificate problem: certificate has expired
More details here: https://curl.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the above URL.
“`

これはセキュリティのためにデフォルトで有効になっている重要な機能です。

対策:

  • 推奨: サーバー側の証明書の問題であれば、サイト管理者に修正を依頼する。
  • 一時的な回避策(非推奨): 検証を一時的に無効にする場合は、-k または --insecure オプションを使用します。ただし、これによりセキュリティリスクが発生するため、本番環境での利用や機密情報のやり取りには絶対に使用しないでください。あくまでデバッグや自己署名証明書のテスト目的などに限定すべきです。

    “`bash

    WARNING: セキュリティリスクがあります!

    curl -L -k https://untrusted-cert-site.com/
    “`

リダイレクト先での認証(クッキーなど)

リダイレクトを追跡する際に、元のリクエストで取得したセッションクッキーや認証情報がリダイレクト先でも必要になる場合があります。

デフォルトでは、curl -Lはクッキーを次のリクエストに引き継ぎます。しかし、ドメインが変更になる場合や、特定のヘッダー(例えばAuthorizationヘッダー)を必ず引き継ぎたい場合は、前述の--location-trustedオプションが役立つことがあります(ただしセキュリティに注意)。

ログインが必要なサイトの場合、最初にログインリクエストを送信し、取得したセッションクッキーを保存しておき、その後のリダイレクト追跡を含むリクエストでそのクッキーを使用する必要があります。

対策:

  • -c <ファイル> または --cookie-jar <ファイル> オプションを使って、セッション中にサーバーから送られてきたクッキーをファイルに保存します。
  • -b <ファイル> または --cookie <ファイル> オプションを使って、保存したクッキーファイルを次のリクエストで送信します。

“`bash

ログインしてクッキーを保存

curl -c cookies.txt -d “user=…” http://example.com/login

保存したクッキーを使ってリダイレクトを追跡

curl -L -b cookies.txt http://example.com/protected-page
“`

リダイレクトとキャッシュ

ブラウザは301リダイレクトを一度経験すると、そのリダイレクト情報をキャッシュし、次回から古いURLではなく新しいURLに直接アクセスすることがあります。

しかし、curlはデフォルトではリダイレクト情報をキャッシュしません。curl -Lを実行するたびに、最初のリクエストからリダイレクト追跡が開始されます。

これは通常期待される挙動ですが、もし意図的にキャッシュされたリダイレクト挙動をシミュレートしたい場合は、curl自体では困難であり、ブラウザを使うか、リダイレクト先のURLを直接指定する必要があります。

リダイレクトとタイムアウト

リダイレクトが多すぎる、あるいはリダイレクト先のサーバー応答が遅い場合、curlコマンド全体の実行時間が長くなり、タイムアウトする可能性があります。

対策:

  • --connect-timeout <秒>: サーバーへの接続確立のタイムアウト時間を設定します。
  • --max-time <秒>: コマンド全体の最大実行時間を設定します。リダイレクト追跡中の全ての通信時間を含みます。

“`bash

接続タイムアウトを5秒、合計実行時間を30秒に設定

curl -L –connect-timeout 5 –max-time 30 http://slow-redirect-site.com/
“`

これらのオプションを適切に設定することで、応答が遅いサイトや不安定なネットワーク環境でのcurlの使い勝手を向上させることができます。

9. まとめ:curlとリダイレクト機能を使いこなす

この記事では、curlコマンドの最も強力でよく使われる機能の一つであるリダイレクト追跡について、詳細に解説しました。

  • HTTPリダイレクトは、WebサイトのURL変更や構成変更において不可欠な仕組みであり、3xx系のステータスコードとLocationヘッダーで指示されることを理解しました。
  • curlはデフォルトではリダイレクトを追跡せず、最初の応答で処理を終えることを確認しました。
  • リダイレクトを自動的に追跡するには、-Lまたは--locationオプションを使用することが最も重要であることを学びました。
  • -Lオプション使用時のリダイレクト追跡挙動は、3xxステータスコードの種類(301, 302, 303, 307, 308)によって、特にリクエストメソッドの引き継ぎ方(GETへの変更 vs. メソッド維持)が異なることを詳しく見ました。
  • リダイレクトの最大追跡回数を制限する--max-redirsオプション、通信の詳細を表示する-vオプション、最終的なURLや回数などを整形して取得する-wオプションの使い方を習得しました。
  • 短縮URLの展開、リダイレクトチェーンの確認、POSTリクエスト後の挙動調査など、具体的な使用例を通じて理解を深めました。
  • 無限リダイレクト、HTTPS証明書エラー、認証、タイムアウトといった、リダイレクト追跡時に遭遇しうる問題とその対策についても触れました。

curl -Lは、Webサイトの動作確認、APIテスト、データ収集など、様々な場面で役立つ非常に強力な機能です。この記事で学んだ知識を活用することで、リダイレクトによって通信が途中で終わってしまうことなく、目的の情報を正しく取得できるようになるでしょう。

最初は少し複雑に感じるかもしれませんが、実際に様々なURLに対して-Lオプションや-vオプションを付けてcurlを実行し、出力される情報を観察することで、リダイレクトの仕組みとcurlの挙動に対する理解が深まります。

ぜひ、この記事を参考に、curlのリダイレクト機能を自信を持って使いこなしてください。Web通信の「迷子」を正確に追跡し、あなたのコマンドライン作業の効率を向上させましょう!

これで、curlのリダイレクト機能に関する約5000語の詳細な説明を含む記事の完成です。


コメントする

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

上部へスクロール