Windows.Web.Http を使って HTTP サーバーに接続する方法 (HTML)

[ この記事は、Windows ランタイム アプリを作成する Windows 8.x および Windows Phone 8.x 開発者を対象としています。Windows 10 向けの開発を行っている場合は、「最新のドキュメント」をご覧ください]

Windows.Web.Http 名前空間の Windows.Web.Http.HttpClient クラスを使って、Web サービスに GET 要求を送信したり、応答を取得したりします。

[HTTPClient のサンプルを今すぐ入手する]

Windows.Web.Http 名前空間のクラスでは、新しい HTTP クライアント アプリ用のプログラミング インターフェイスが提供されます。Windows.Web.Http 名前空間とそれに関連する Windows.Web.Http.Headers および Windows.Web.Http.Filters 名前空間には、ユーザーが HTTP 要求を行い、HTTP 経由で最新の Web サービスから HTTP 応答を受信する HTTP クライアント コンポーネントが用意されています。

Windows 8.1 では、Windows ランタイム名前空間である Windows.Web.Http が導入されています。この名前空間は、HTTP および Representational State Transfer (REST) の Web サービスに接続する Windows アプリに使います。 この新しい API は、元は Windows 8 用にリリースされた HTTP API を置き換えるものであり、サポートされているすべての言語にわたるフル機能サポートを提供します。

この新しい API は、以前に Windows 8 の各言語プロジェクションに必要であったさまざまな機能を提供した 3 つの異なる API に代わるものです。

新しい API では、基本的な要求操作を対象として特に一般的なタスクを処理するシンプルなインターフェイスが用意されており、ほとんどのシナリオに適用される認証 (AUTH) に妥当な既定値が提供されます。より複雑な HTTP 操作を対象として、次のような追加機能が用意されています。

  • 一般的な動詞 (DELETEGETPUTPOST) に対応するメソッド

  • 一般的な認証設定とパターンのサポート

  • トランスポートに関する Secure Sockets Layer (SSL) 詳細へのアクセス

  • カスタマイズされたフィルターを高度なアプリに含める機能

  • Cookie を取得、設定、削除する機能

  • 非同期メソッドで使用できる HTTP 要求の進行状況情報

Windows.Web.Http.HttpClient クラスを使って、HTTP 経由で基本的な要求を送受信します。このクラスには、HTTP 要求を送り、URI で識別されるリソースから HTTP 応答を受け取るためのメイン クラスが用意されています。このクラスを使って、Web サービスに GET、PUT、POST、DELETE などの要求を送れます。これらの各要求は、非同期操作として送られます。

Windows.Web.Http.HttpRequestMessage クラスは、Windows.Web.Http.HttpClient から送られた HTTP 要求メッセージを表します。Windows.Web.Http.HttpResponseMessage クラスは、HTTP 要求から受け取った HTTP 応答メッセージを表します。HTTP メッセージは、IETF によって RFC 2616 で規定されています。

Windows.Web.Http 名前空間は、HTTP 要求または HTTP 応答に関連付けられた HTTP コンテンツ (HTTP エンティティ ボディおよびクッキーを含むコンテンツ ヘッダー) を表すさまざまな異なるクラスを提供しています。 これらの異なるクラスにより、バッファー、文字列、ストリーム、さらに application/x-www-form-urlencoded MIME タイプ、multipart/* MIME タイプ、および multipart/form-data MIME タイプによりエンコードされた名前/値データをコンテンツで使うことができます。 また、カスタム コンテンツを定義できます。

この例では、文字列として HTTP 応答を表すために HttpStringContent クラスを使っています。

Windows.Web.Http.Headers 名前空間では、HTTP ヘッダーおよび Cookie の作成がサポートされます。これらはプロパティとして、HttpRequestMessage オブジェクトおよび HttpResponseMessage オブジェクトと関連付けられます。

必要条件

このトピックのコード例は、JavaScript と HTML で記述されています。RFC 2616 で規定されている HTTP 要求に関する基本的な知識が必要です。

また、WinJS.xhrXMLHttpRequest によって、JavaScript と HTML を使ったアプリ内で HTTP 要求を行うことができます。詳しくは、「Web サービスへの接続 (JavaScript を使った Windows ランタイム アプリ)」をご覧ください。

手順

ステップ 1: 新しいプロジェクトを作る

  1. Microsoft Visual Studio 2013 を開き、[ファイル] メニューの [新しいプロジェクト] をクリックします。
  2. テンプレートの一覧で、[JavaScript] を選びます。
  3. そのセクションで、[Store apps] を選びます。
  4. そのセクションで、[Universal Apps]、[Windows apps]、[Windows Phone apps] のいずれか (対象のプラットフォームに応じて異なります) を選び、[新しいアプリケーション] を選びます。
  5. アプリケーションに HttpClientGet という名前を付け、[OK] をクリックします。

ステップ 2: ネットワーク アクセスを有効にする機能を設定する

アプリがプライベート ホーム ネットワーク、社内ネットワーク、インターネットにアクセスできるように、ネットワーク機能を設定する必要があります。このアプリでは、クライアントが Web サービスに接続するため、ネットワーク機能を有効にする必要があります。

Windows.Web.Http.HttpClient を使って別のコンピューター上の Web サービスに接続するアプリでは、ネットワーク機能を設定する必要があります。アプリがクライアントとしてインターネット上の Web サービスに接続するには、インターネット (クライアント) 機能が必要です。アプリがクライアントとしてホーム ネットワークまたは社内ネットワーク上の Web サービスに接続するには、プライベート ネットワーク (クライアントとサーバー) 機能が必要です。

  Windows Phone では、アプリに対してすべてのネットワーク アクセスを有効にするネットワーク機能は [インターネット (クライアントとサーバー)] だけです。

 

Web サービスがアプリと同じコンピューター上で実行されている場合は、ループバック アクセスが必要になります。Visual Studio 2013 で開発および実行されたアプリは、ループバックの制限から除外済みとして自動的に登録されます。詳しくは、「ループバックを有効にする方法とネットワーク分離のトラブルシューティングを行う方法」をご覧ください。

ネットワーク アクセスについて詳しくは、「ネットワーク分離機能を構成する方法」をご覧ください。

アプリからインターネット、プライベート ネットワーク、または社内ネットワーク上の Web サービスにアクセスする場合は、アプリを展開する前に、これらの手順に従ってネットワーク機能を設定する必要があります。

  1. Visual Studio 2013 を使って、package.appxmanifest ファイルを開きます。

  2. [機能] タブをクリックします。

  3. Windows バージョンのサンプルをビルドするには、[インターネット (クライアント)] 機能か [プライベート ネットワーク (クライアントとサーバー)] 機能を選びます。

    Windows Phone バージョンのサンプルをビルドするには、[インターネット (クライアントとサーバー)] 機能を選びます。

  4. マニフェスト ファイルを保存して閉じます。

ステップ 3: HTML UI を追加する

  • このセクションでは、XAML でアプリのレイアウトを定義して、アプリ内の各オブジェクトの適切なサイズと位置を指定します。 データを表示するためにコントロールとコンテンツを追加して、アプリの UI を完成させます。

    このサンプルでは、次を含む簡単な HTML UI 要素を使います。

    • 非同期要求を開始するための入力 URI アドレス用のテキスト ラベルと入力フィールド、button に使われる class を含むコントロール。

    • 現在の状態を表示するためのテキスト ラベルとテキスト フィールドを含む class を持つコントロール。この TextBox に、状態やエラー メッセージが表示されます。このコントロールにはまた、Web サービスから受け取った出力を表示する class が含まれます。このサンプルでは、HTTP GET 操作の結果は、HTML マークアップを含むプレーンテキストとして表示されます。

    js フォルダーを開いて、さらに既存の default.js ファイルを開き、このファイルに次の UI 要素を追加します。

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>HttpClientGet</title>
    
        <!-- WinJS references - Windows -->
        <link href="//Microsoft.WinJS.2.0/css/ui-dark.css" rel="stylesheet" />
        <script src="//Microsoft.WinJS.2.0/js/base.js"></script>
        <script src="//Microsoft.WinJS.2.0/js/ui.js"></script>
    
        <!-- WinJS references - Phone -->
        <link href="/css/ui-themed.css" rel="stylesheet" />
        <script src="//Microsoft.Phone.WinJS.2.1/js/base.js"></script>
        <script src="//Microsoft.Phone.WinJS.2.1/js/ui.js"></script>
    
        <!-- HttpClientGet references -->
        <link href="/css/default.css" rel="stylesheet" />
        <script src="/js/default.js"></script>
        <script src="/js/mainpage.js"></script>
    </head>
    
    <body>
        <div data-win-control="SampleInput">
            <p> Download the contents of a page and display it. </p>
            <p class="clear">
                <label for="inputAddress">URI Address:</label>
                <input type="text" id="inputAddress" value="https://www.contoso.com" />
            </p>
            <p>
                <button id="startButton">Start</button>
            </p>
        </div>
        <div data-win-control="SampleOutput">
            <p class="clear">
                <label for="statusText">Status:</label>
                <input type="text" id="statusText" value="" />
            </p>
            <textarea id="outputView"></textarea>
        </div>
    </body>
    </html>
    

ステップ 4: HttpClient を作る

  • まず、Windows.Web.Http.HttpClient オブジェクトを作成し、ユーザー エージェント ヘッダーを追加します。

    既定では、HttpClient オブジェクトによって、ユーザー エージェント ヘッダーが HTTP 要求と共に Web サービスに送られることはありません。Microsoft Web サーバーなど、一部の HTTP サーバーでは、クライアントから送られた HTTP 要求にユーザー エージェント ヘッダーが含まれている必要があります。ヘッダーが存在しない場合、HTTP サーバーはエラーを返します。Windows.Web.Http.Headers 名前空間のクラスを使って、ユーザー エージェント ヘッダーを追加する必要があります。そうしたエラーが発生しないように、HttpClient.DefaultRequestHeaders プロパティにこのヘッダーを追加します。

    js フォルダーを開き、新しい mainpage.js ファイルを追加して、次のコードをファイルに追加します。

    (function () {
        "use strict";
    
        var httpClient;
        var httpPromise;
    
        var page = WinJS.UI.Pages.define("/html/mainpage.html", {
            ready: function (element, options) {
                document.getElementById("startButton").addEventListener("click", start, false);
    
                httpClient = new Windows.Web.Http.HttpClient();
    
                // Add a user-agent header
                headers = httpClient.defaultRequestHeaders;
    
                // UserAgent is a HttpProductInfoHeaderValueCollection
                // A collection of HttpProductInfoHeaderValue items
    
                // The safe way to check a header value from the user is the TryParseAdd method
                // Since we know this header is okay, we use ParseAdd with will throw an exception
                // with a bad value 
    
                headers.userAgent.parseAdd("ie");
                headers.userAgent.parseAdd("Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)");
            }
        });
    })();
    

    js フォルダーと default.js ファイルを開き、次のコードをファイルに追加します。

    (// For an introduction to the Blank template, see the following documentation:
    // https://go.microsoft.com/fwlink/p/?LinkID=232509
    (function () {
        "use strict";
    
        var app = WinJS.Application;
        var activation = Windows.ApplicationModel.Activation;
    
        app.onactivated = function (args) {
            if (args.detail.kind === activation.ActivationKind.launch) {
                if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
                    startButton.onclick = start;
    
                } else {
                    startButton.onclick = start;
                }
                args.setPromise(WinJS.UI.processAll());
            }
        };
    
        app.oncheckpoint = function (args) {
            // This application is about to be suspended. Save any state
            // that needs to persist across suspensions here. You might use the
            // WinJS.Application.sessionState object, which is automatically
            // saved and restored across suspension. If you need to complete an
            // asynchronous operation before your application is suspended, call
            // args.setPromise().
        };
    
        app.start();
    })();
    

ステップ 5: GET 要求を送り、応答を取得します。

  • [スタート] ボタンがクリックされると、まず inputAddress で指定された URI が有効であるかどうかを検証します。次に、URI を使って GET 要求を送り、HTTP サーバーからの応答を受け取るまで待機します。

    ほとんどの処理は、Start Button のクリック ハンドラーで行います。このボタンがクリックされると、statusText および outputView の UI 要素内のテキストが更新されます。入力 URI アドレスでは、まずユーザーが有効な URI アドレスを渡したかどうかが確認されます。ユーザーからの有効な URI を待機している場合、アプリは指定の URI に HTTP GET 要求を送信して、HTTP 応答を待機します。エラーや例外が発生した場合は、その結果が statusText UI 要素に表示されます。エラーが発生しなかった場合は、Web サービスからの応答が outputView UI 要素に表示されます。

    Uniform Resource Identifier (URI) として無効な文字列が、Windows.Foundation.Uri オブジェクトのコンストラクターに渡されると、例外がスローされます。

    JavaScript では、URI として渡される文字列を試行して解析するメソッドはありません。この場合、こうした例外をキャッチするために、URI を構築するコードを try/catch ブロックで囲みます。

    このサンプルではまた、URI 内の HTTP スキーマが HTTP または HTTPS であることを確認しています。これらは、Windows.Web.Http.HttpClient によってサポートされる唯一のスキーマであるためです。

    JavaScript で then および done キーワードを使った場合、非同期的に GET 要求を送って応答を取得するコードは、この操作を同期的に行うコードと似ています。

    ネットワークのエラーによる例外 (たとえば、接続の切断、接続エラー、HTTP サーバー エラーなど) は、いつでも発生する場合があります。これらのエラーが起きると、例外がスローされます。例外がアプリによって処理されない場合、ランタイムによってアプリ全体が終了されることがあります。 非同期ネットワーク メソッドの多くは、呼び出す場合、例外を処理するようにコードを記述する必要があります。例外の発生時に、場合によっては、問題を解決するためにネットワーク メソッドが再試行されることがあります。また、ネットワーク接続なしで、以前にキャッシュされたデータを使ってアプリを継続するように計画しなければならない場合もあります。ネットワーク例外の処理について詳しくは、「ネットワーク アプリでの例外の処理」をご覧ください。

    Web サーバーから HTTP エラー状態コード (Successful の要求範囲 (200 ~ 299) にない HttpResponse.StatusCode) が返された場合、HttpResponse.EnsureSuccessStatusCode メソッドは例外をスローします。すべての例外に対して try/catch ブロックを使い、エラーが発生した場合は statusText UI 要素に例外メッセージを出力します。

    HttpResponse.Content プロパティは、HTTP 応答の内容を表します。HttpClient.GetAsync(Uri) メソッドによって、非同期操作として HTTP の内容を文字列に読み取ります。 表示するために、返された HTML テキスト内のすべての <br> タグを改行に置き換えます。このメソッドが成功すると、statusText UI 要素に HttpResponse.StatusCode が表示され、outputView UI 要素に Web サービスによって返された HttpResponse.Content が表示されます。

    [js] フォルダーを開き、mainpage.js ファイルに次のコードを追加します。

        function start()
        {
    
            var response = new Windows.Web.Http.HttpResponseMessage();
    
            var statusText = document.getElementById("statusText");
            var outputView = document.getElementById("outputView");
    
            // The value of 'inputAddress' is set by the user 
            // and is therefore untrusted input. 
            // If we can't create a valid absolute URI, 
            // We notify the user about the incorrect input.
    
            statusText.Text = "Testing URI is valid.";
    
            var uriString = document.getElementById("inputAddress").value.trim();
            if (!uriString) {
                return;
            }
    
            var resourceUri;
            try {
               resourceUri = new Windows.Foundation.Uri(uriString);
            }
            catch (Exception) {
                statusText.Text = "Invalid URI, please re-enter a valid URI.";
                return;
            }
    
            if (resourceUri.schemeName != "http" && resourceUri.schemeName != "https") {
                statusText.Text = "Only 'http' and 'https' schemes supported. Please re-enter URI";
                return;
            }
    
            var responseBodyAsText="";
            outputView.Text = "";
            statusText.Text = "Waiting for response ...";
    
            httpPromise = httpClient.getAsync(resourceUri).then(function (response) {
                outputStatus = response.statusCode + " " + response.reasonPhrase;
    
                response.EnsureSuccessStatusCode();
    
                response.content.readAsStringAsync().then(function (responseBodyAsText) {
                // Format the HTTP response to display better
                responseBodyAsText = responseBodyAsText.replace(/<br>/g, "\r\n");
                outputView.value = responseBodyAsText;
                return response;
            });
        )};
    
        httpPromise.done(function (response) {
            statusText.value = response.StatusCode + " " + response.ReasonPhrase + "\r\n";
        }, onError);
    
        function onError(error) {
            statusText.value = "Error = " + error.number + "  Message: " + error.message;
        }
    
    })();
    

    Windows.Web.Http.HttpClient では WinInet を使って、HTTP サービス要求と Web サービス要求を送り、応答を受け取ります。WinInet によって HTTP 接続操作で使われる既定のタイムアウト値は 60 秒です。HTTP サーバーまたは Web サービスが一時的にダウンしているか、ファイアウォールによってブロックされていて、サーバーが Windows.Web.Http.HttpClient 要求に応答できない場合、WinInet は既定で 60 秒待機してからエラーを返します。このエラーにより、アプリ内では例外がスローされます。HTTP サーバー名に対する名前クエリから該当名に対して複数の IP アドレスが返された場合、WinInet はサイトに対して複数の IP アドレスを試み、そのたびに失敗までのタイムアウト時間として既定で 60 秒を使います。WinInet によってエラーが返され、例外がスローされる前に、HTTP 要求または Web サービス要求を行うアプリが複数の IP アドレスについて再試行するまで数分間待機することがありました。この動作は、まるでアプリが停止しているかのようにユーザーからは見えることがありました。接続が確立された後、WinInet によって送受信操作に使われる既定のタイムアウト値は 30 秒です。

    アプリの応答性を高め、こうした問題の影響を最小化するために、既定の WinInet 設定ではなくタイムアウトにより操作が早期に失敗するように、Windows.Web.Http.HttpClient 操作のタイムアウトをより短く設定して、アプリの機能を向上できることがあります。タイムアウトの設定方法について詳しくは、「WinJS.xhr または HttpClient によるタイムアウト値の設定」または「ソケット操作にタイムアウトを設定する方法」をご覧ください。

注釈

このトピックでは、Web サービスに GET 要求を送信し、Windows.Web.Http.HttpClient および Windows.Web.Http.HttpResponseMessage 名前空間の関連するクラスを使って応答を取得するために、Windows.Web.Http.Headers クラスを使う方法について説明しました。

関連トピック

その他のリソース

Web サービスへの接続

ネットワーク アプリでの例外の処理

ネットワーク分離機能を構成する方法

ループバックを有効にする方法とネットワーク分離のトラブルシューティングを行う方法

WinJS.xhr または HttpClient によるタイムアウト値の設定

辞書/リファレンス

Windows.Foundation.Uri

Windows.Web.Http

Windows.Web.Http.Filters

Windows.Web.Http.Headers

サンプル

HttpClient のサンプルに関するページ

Web 認証のサンプル