4

CPPREST http_client を使用して URL にアクセスしようとしています:

http://www.20min.ch/rss/rss.tmpl?type=channel&get=68

URL リダイレクトの応答コード 302 を受け取りました。

しかし、CURL を使用して同じ URL にアクセスしようとすると、CURLE_OK が表示されます。

以下は2つのコードです:

カールを使用:

CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
if(curl){
    curl_easy_setopt(curl, CURLOPT_URL, "http://www.20min.ch/rss/rss.tmpl?type=channel&get=68");
    res = curl_easy_perform(curl);
    if(res != CURLE_OK)     {
        cout<<"failed";
    }
    else  {
        cout<<"success";
    }
    curl_easy_cleanup(curl);
}
curl_global_cleanup();

出力は次のとおりです。成功

CPPREST を使用:

std::string url_= "http://www.20min.ch/rss/rss.tmpl?type=channel&get=68";
try
{
     http_client client1(U(url_));
     uri_builder builder1(U(""));
     client1.request(methods::GET, builder1.to_string()).then([=](http_response response)
     {
        cout<<"Response code is : "<<response.status_code();
     });
}
catch(std::exception& e)
{
    cout<<"response :"<<e.what();
}

出力は:: 応答コードは: 302

同じ URL に対して 2 つのライブラリの動作が異なる理由がわかりません。

アップデート :

私も試しました:

http_client client1(utility::conversions::to_string_t(url_));

http_client client1(U("http://www.20min.ch/rss/rss.tmpl?type=channel&get=68"));

http_client client1(U("http://www.20min.ch/"));

しかし、レスポンスは cpp rest と同じ 302 です。[ クロスチェックの場合 bing の例

正常に動作しています]

更新 2:

@Matt Weber で説明されている方法は非常に役に立ち、正当に思えますが、エラー コード : 400 を継続的に取得しているため、以下のことを試しました: uri_builder で URL のホストとポートを設定しようとしました。

http_client client(U("http://www.20min.ch/rss/"));
uri_builder builder(U("/rss.tmpl"));
builder.append_query(U("type"), U("channel"));
builder.append_query(U("get"), U("68"));
builder.set_host(U("www.20min.ch"));
builder.set_port(U("80"));
client.request(methods::GET, builder.to_string()).then([=](http_response response)
{
     cout<<"Received response status code: "<<response.status_code();
});

それでも同じ 302 です。

4

1 に答える 1

8

Rest SDK コードの問題はhttp_client初期化です。

    http_client client1(U(url_));

このUマクロは、文字列リテラルで使用して、auriを構築できるものを生成します。Windows を使用している場合、これはコンパイルされません。マクロ展開の結果がLurl_. どうやら、これがシステムにもたらす結果が何であれ、302 で応答する何かの要求につながるようです。

いくつかのオプションがあります。1 つは、単純にリテラルを直接使用することです。

    http_client client1(U("http://www.20min.ch/rss/rss.tmpl?type=channel&get=68"));

std::stringを保持し、そこからクライアントを初期化したい場合は、utility::string_turi構築できる に変換できます。

    std::string url_= "http://www.20min.ch/rss/rss.tmpl?type=channel&get=68";
    http_client client1(utility::conversions::to_string_t(url_));

それが完了すると、予想される出力を実際に確認するためにwait、継続で関数を呼び出す必要があることがわかるでしょう。request

     client1.request(methods::GET, builder1.to_string()).then([](http_response response)
     {
        cout<<"Response code is : "<<response.status_code();
     }).wait(); // ensure that the response gets processed

編集:

上記は Windows でのビルドに関連していますが、302 応答とは関係ありません。

Linux では、要求は一貫して 302 になります。ネットワーク上の要求と応答を見ると、Windows ホストからの要求は 200 を取得し、Linux ホストからの要求は 302 を取得します。その理由は、Linux バージョンでは、ホスト ヘッダーにポート番号が含まれているためです。サーバーが 302 で応答するようにトリガーします。

Windows リクエスト:

GET /rss/rss.tmpl?type=channel&get=68 HTTP/1.1\r\n
Connection: Keep-Alive\r\n
User-Agent: cpprestsdk/2.8.0\r\n
Host: www.20min.ch\r\n
\r\n

Linux リクエスト:

GET /rss/rss.tmpl?type=channel&get=68 HTTP/1.1\r\n
Host: www.20min.ch:80\r\n
User-Agent:cpprestsdk/2.8.0\r\n
Connection: Keep-Alive\r\n
\r\n

これが原因であることを wget で確認できます。

$ wget --header="Host: www.20min.ch" -S "http://www.20min.ch/rss/rss.tmpl?type=channel&get=68"

HTTP/1.1 200 OK

$ wget --header="Host: www.20min.ch:80" -S "http://www.20min.ch/rss/rss.tmpl?type=channel&get=68" --max-redirect 0

HTTP/1.1 302 見つかりました

ヘッダーの違いは、実装の違いによるものです。WinHTTP クライアントの実装は、Host ヘッダーを明示的に追加しません。これはおそらく、内部的にそれを行うために WinHTTP に依存しているためです。ただし、asio クライアントの実装はそれを追加します。

        // Add the Host header if user has not specified it explicitly
        if (!ctx->m_request.headers().has(header_names::host))
        {
            request_stream << "Host: " << host << ":" << port << CRLF;
        }

したがって、期待される動作を得るために、ポート情報を追加しないようにヘッダーを明示的に設定できます。

std::string url_= "http://www.20min.ch/rss/rss.tmpl?type=channel&get=68";
http_client client1(utility::conversions::to_string_t(url_));
http_request request;
request.set_method(methods::GET);
request.headers().add(U("Host"), U("www.20min.ch"));
client1.request(request).then([](http_response response)
{
    std::cout<<"Response code is : "<<response.status_code();
}).wait();

この変更により、Windows と Linux の両方で 200 OK が得られます。

于 2016-03-15T05:51:14.200 に答える