669 lines
23 KiB
C++
669 lines
23 KiB
C++
/***
|
|
* ==++==
|
|
*
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
* ==--==
|
|
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
|
*
|
|
* Tests cases for authentication with http_clients.
|
|
*
|
|
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
****/
|
|
|
|
#include "stdafx.h"
|
|
#include <stdexcept>
|
|
|
|
#ifdef _WIN32
|
|
#ifdef __cplusplus_winrt
|
|
#if !defined(__WRL_NO_DEFAULT_LIB__)
|
|
#define __WRL_NO_DEFAULT_LIB__
|
|
#endif
|
|
#include <wrl.h>
|
|
#include <msxml6.h>
|
|
#else
|
|
#include <windows.h>
|
|
#include <winhttp.h>
|
|
#endif
|
|
#endif
|
|
|
|
#if !defined(_WIN32)
|
|
#include <boost/asio.hpp>
|
|
#include <boost/asio/ssl.hpp>
|
|
#endif
|
|
|
|
using namespace web;
|
|
using namespace utility;
|
|
using namespace concurrency;
|
|
using namespace web::http;
|
|
using namespace web::http::client;
|
|
|
|
using namespace tests::functional::http::utilities;
|
|
|
|
namespace tests { namespace functional { namespace http { namespace client {
|
|
|
|
SUITE(authentication_tests)
|
|
{
|
|
|
|
TEST_FIXTURE(uri_address, auth_no_data, "Ignore:Linux", "89", "Ignore:Apple", "89")
|
|
{
|
|
test_http_server::scoped_server scoped(m_uri);
|
|
http_client_config client_config;
|
|
web::credentials cred(U("some_user"), U("some_password")); // WinHTTP requires non-empty password
|
|
client_config.set_credentials(cred);
|
|
http_client client(m_uri, client_config);
|
|
const method mtd = methods::POST;
|
|
|
|
http_request msg(mtd);
|
|
|
|
auto replyFunc = [&](test_request *p_request)
|
|
{
|
|
http_asserts::assert_test_request_equals(p_request, methods::POST, U("/"));
|
|
p_request->reply(200);
|
|
};
|
|
|
|
scoped.server()->next_request().then([&](test_request *p_request)
|
|
{
|
|
http_asserts::assert_test_request_equals(p_request, mtd, U("/"));
|
|
|
|
// Auth header
|
|
std::map<utility::string_t, utility::string_t> headers;
|
|
headers[U("WWW-Authenticate")] = U("Basic realm = \"WallyWorld\"");
|
|
|
|
// unauthorized
|
|
p_request->reply(status_codes::Unauthorized, U("Authentication Failed"), headers);
|
|
|
|
}).then([&scoped, replyFunc]()
|
|
{
|
|
// Client resent the request
|
|
scoped.server()->next_request().then(replyFunc);
|
|
});
|
|
|
|
http_asserts::assert_response_equals(client.request(msg).get(), status_codes::OK);
|
|
}
|
|
|
|
// TFS 648783
|
|
#ifndef __cplusplus_winrt
|
|
TEST_FIXTURE(uri_address, proxy_auth_known_contentlength, "Ignore:Linux", "88", "Ignore:Apple", "88")
|
|
{
|
|
test_http_server::scoped_server scoped(m_uri);
|
|
http_client_config client_config;
|
|
web::credentials cred(U("some_user"), U("some_password")); // WinHTTP requires non-empty password
|
|
client_config.set_credentials(cred);
|
|
http_client client(m_uri, client_config);
|
|
const method mtd = methods::POST;
|
|
utility::string_t contents(U("Hello World"));
|
|
|
|
http_request msg(mtd);
|
|
msg.set_body(contents);
|
|
|
|
auto replyFunc = [&](test_request *p_request)
|
|
{
|
|
http_asserts::assert_test_request_equals(p_request, methods::POST, U("/"), U("text/plain; charset=utf-8"), contents);
|
|
|
|
p_request->reply(200);
|
|
};
|
|
|
|
scoped.server()->next_request().then([&](test_request *p_request)
|
|
{
|
|
http_asserts::assert_test_request_equals(p_request, mtd, U("/"));
|
|
|
|
// Auth header
|
|
std::map<utility::string_t, utility::string_t> headers;
|
|
headers[U("WWW-Authenticate")] = U("Basic realm = \"WallyWorld\"");
|
|
|
|
// unauthorized
|
|
p_request->reply(status_codes::Unauthorized, U("Authentication Failed"), headers);
|
|
|
|
}).then([&scoped, replyFunc]()
|
|
{
|
|
// Client resent the request
|
|
scoped.server()->next_request().then(replyFunc);
|
|
});
|
|
|
|
http_asserts::assert_response_equals(client.request(msg).get(), status_codes::OK);
|
|
}
|
|
#endif
|
|
|
|
TEST_FIXTURE(uri_address, proxy_auth_noseek, "Ignore:Linux", "88", "Ignore:Apple", "88")
|
|
{
|
|
web::http::uri uri(U("http://localhost:34567/"));
|
|
test_http_server::scoped_server scoped(uri);
|
|
http_client client(uri); // In this test, the request cannot be resent, so the username and password are not required
|
|
const method mtd = methods::POST;
|
|
|
|
auto buf = streams::producer_consumer_buffer<unsigned char>();
|
|
buf.putc('a').get();
|
|
buf.close(std::ios_base::out).get();
|
|
|
|
http_request msg(mtd);
|
|
msg.set_body(buf.create_istream(), 1);
|
|
|
|
scoped.server()->next_request().then([&](test_request *p_request)
|
|
{
|
|
http_asserts::assert_test_request_equals(p_request, mtd, U("/"));
|
|
|
|
// Auth header
|
|
std::map<utility::string_t, utility::string_t> headers;
|
|
headers[U("WWW-Authenticate")] = U("Basic realm = \"WallyWorld\"");
|
|
|
|
// unauthorized
|
|
p_request->reply(status_codes::Unauthorized, U("Authentication Failed"), headers);
|
|
|
|
});
|
|
|
|
http_asserts::assert_response_equals(client.request(msg).get(), status_codes::Unauthorized);
|
|
}
|
|
|
|
// Must specify content length with winrt client, so this test case isn't possible.
|
|
#ifndef __cplusplus_winrt
|
|
TEST_FIXTURE(uri_address, proxy_auth_unknown_contentlength, "Ignore:Linux", "88", "Ignore:Apple", "88")
|
|
{
|
|
test_http_server::scoped_server scoped(m_uri);
|
|
http_client_config client_config;
|
|
web::credentials cred(U("some_user"), U("some_password")); // WinHTTP requires non-empty password
|
|
client_config.set_credentials(cred);
|
|
http_client client(m_uri, client_config);
|
|
const method mtd = methods::POST;
|
|
|
|
std::vector<uint8_t> msg_body;
|
|
msg_body.push_back('a');
|
|
|
|
http_request msg(mtd);
|
|
msg.set_body(streams::container_stream<std::vector<uint8_t>>::open_istream(std::move(msg_body)));
|
|
|
|
auto replyFunc = [&](test_request *p_request)
|
|
{
|
|
utility::string_t contents(U("a"));
|
|
http_asserts::assert_test_request_equals(p_request, methods::POST, U("/"), U("application/octet-stream"), contents);
|
|
|
|
p_request->reply(200);
|
|
};
|
|
|
|
scoped.server()->next_request().then([&](test_request *p_request)
|
|
{
|
|
http_asserts::assert_test_request_equals(p_request, mtd, U("/"));
|
|
|
|
// Auth header
|
|
std::map<utility::string_t, utility::string_t> headers;
|
|
headers[U("WWW-Authenticate")] = U("Basic realm = \"WallyWorld\"");
|
|
|
|
// unauthorized
|
|
p_request->reply(status_codes::Unauthorized, U("Authentication Failed"), headers);
|
|
|
|
}).then([&scoped, replyFunc]()
|
|
{
|
|
// Client resent the request
|
|
scoped.server()->next_request().then(replyFunc);
|
|
});
|
|
|
|
http_asserts::assert_response_equals(client.request(msg).get(), status_codes::OK);
|
|
}
|
|
|
|
// Accessing a server that returns 401 with an empty user name should not resend the request with an empty password
|
|
TEST_FIXTURE(uri_address, empty_username_password)
|
|
{
|
|
test_http_server::scoped_server scoped(m_uri);
|
|
http_client client(m_uri);
|
|
|
|
scoped.server()->next_request().then([&](test_request *p_request)
|
|
{
|
|
std::map<utility::string_t, utility::string_t> headers;
|
|
headers[U("h1")] = U("data1");
|
|
// Auth header
|
|
headers[U("WWW-Authenticate")] = U("Basic realm = \"myRealm\"");
|
|
// unauthorized
|
|
p_request->reply(status_codes::Unauthorized, U("Authentication Failed"), headers, "a" );
|
|
});
|
|
|
|
http_response response = client.request(methods::GET).get();
|
|
auto str_body = response.extract_vector().get();
|
|
auto h1 = response.headers()[U("h1")];
|
|
VERIFY_ARE_EQUAL(status_codes::Unauthorized, response.status_code());
|
|
VERIFY_ARE_EQUAL(str_body[0], 'a');
|
|
VERIFY_ARE_EQUAL(h1, U("data1"));
|
|
}
|
|
#endif
|
|
|
|
// Fails on WinRT due to TFS 648278
|
|
// Accessing a server that supports auth, but returns 401, even after the user has provided valid creds
|
|
// We're making sure the error is reported properly, and the response data from the second response is received
|
|
TEST_FIXTURE(uri_address, error_after_valid_credentials, "Ignore:Linux", "89", "Ignore:Apple", "89")
|
|
{
|
|
web::http::uri uri(U("http://localhost:34569/"));
|
|
test_http_server::scoped_server scoped(uri);
|
|
http_client_config client_config;
|
|
web::credentials cred(U("some_user"), U("some_password"));
|
|
client_config.set_credentials(cred);
|
|
http_client client(uri, client_config);
|
|
|
|
auto replyFunc = [&](test_request *p_request)
|
|
{
|
|
std::map<utility::string_t, utility::string_t> headers;
|
|
// Auth header
|
|
headers[U("WWW-Authenticate")] = U("Basic realm = \"WallyWorld\"");
|
|
headers[U("h1")] = U("data2");
|
|
// still unauthorized after the user has resent the request with the credentials
|
|
p_request->reply(status_codes::Unauthorized, U("Authentication Failed"), headers, "def" );
|
|
};
|
|
|
|
scoped.server()->next_request().then([&](test_request *p_request)
|
|
{
|
|
std::map<utility::string_t, utility::string_t> headers;
|
|
headers[U("h1")] = U("data1");
|
|
// Auth header
|
|
headers[U("WWW-Authenticate")] = U("Basic realm = \"myRealm\"");
|
|
// unauthorized
|
|
p_request->reply(status_codes::Unauthorized, U("Authentication Failed"), headers, "abc" );
|
|
}).then([&scoped, &replyFunc]()
|
|
{
|
|
// Client resent the request
|
|
scoped.server()->next_request().then(replyFunc);
|
|
})
|
|
#ifdef __cplusplus_winrt
|
|
.then([&scoped, &replyFunc]()
|
|
{
|
|
// in winrt, client resent the request again
|
|
scoped.server()->next_request().then(replyFunc);
|
|
})
|
|
#endif
|
|
;
|
|
|
|
http_response response = client.request(methods::GET).get();
|
|
auto str_body = response.extract_vector().get();
|
|
auto h1 = response.headers()[U("h1")];
|
|
VERIFY_ARE_EQUAL(status_codes::Unauthorized, response.status_code());
|
|
VERIFY_ARE_EQUAL(str_body[0], 'd');
|
|
VERIFY_ARE_EQUAL(str_body[1], 'e');
|
|
VERIFY_ARE_EQUAL(str_body[2], 'f');
|
|
VERIFY_ARE_EQUAL(h1, U("data2"));
|
|
}
|
|
|
|
|
|
// These tests are disabled since they require a server with authentication running.
|
|
// The server portion to use is the C# AuthenticationListener.
|
|
|
|
class server_properties
|
|
{
|
|
public:
|
|
server_properties() {}
|
|
|
|
// Helper function to retrieve all parameters necessary for setup tests.
|
|
void load_parameters()
|
|
{
|
|
m_uri = uri(utility::conversions::to_string_t(UnitTest::GlobalSettings::Get("Server")));
|
|
if(UnitTest::GlobalSettings::Has("UserName"))
|
|
{
|
|
m_username = utility::conversions::to_string_t(UnitTest::GlobalSettings::Get("UserName"));
|
|
}
|
|
if(UnitTest::GlobalSettings::Has("Password"))
|
|
{
|
|
m_password = utility::conversions::to_string_t(UnitTest::GlobalSettings::Get("Password"));
|
|
}
|
|
}
|
|
|
|
web::http::uri m_uri;
|
|
string_t m_username;
|
|
string_t m_password;
|
|
};
|
|
|
|
// This test should be executed for NTLM, Negotiate, IntegratedWindowsAuth, and Anonymous.
|
|
TEST_FIXTURE(server_properties, successful_auth_no_cred, "Requires", "Server")
|
|
{
|
|
load_parameters();
|
|
|
|
http_client client(m_uri);
|
|
http_response response = client.request(methods::GET).get();
|
|
VERIFY_ARE_EQUAL(status_codes::OK, response.status_code());
|
|
}
|
|
|
|
TEST_FIXTURE(server_properties, digest_basic_auth_no_cred, "Requires", "Server")
|
|
{
|
|
load_parameters();
|
|
|
|
http_client client(m_uri);
|
|
http_response response = client.request(methods::GET).get();
|
|
VERIFY_ARE_EQUAL(status_codes::Unauthorized, response.status_code());
|
|
}
|
|
|
|
TEST_FIXTURE(server_properties, none_auth_no_cred, "Requires", "Server")
|
|
{
|
|
load_parameters();
|
|
|
|
http_client client(m_uri);
|
|
http_response response = client.request(methods::GET).get();
|
|
VERIFY_ARE_EQUAL(status_codes::Forbidden, response.status_code());
|
|
}
|
|
|
|
// This test should be executed for NTLM, Negotiate, IntegratedWindowsAuth, and Digest.
|
|
TEST_FIXTURE(server_properties, unsuccessful_auth_with_basic_cred, "Requires", "Server;UserName;Password")
|
|
{
|
|
load_parameters();
|
|
|
|
http_client_config config;
|
|
config.set_credentials(web::credentials(m_username, m_password));
|
|
|
|
http_client client(m_uri, config);
|
|
http_response response = client.request(methods::GET).get();
|
|
VERIFY_ARE_EQUAL(status_codes::Unauthorized, response.status_code());
|
|
}
|
|
|
|
TEST_FIXTURE(server_properties, basic_anonymous_auth_with_basic_cred, "Requires", "Server;UserName;Password")
|
|
{
|
|
load_parameters();
|
|
|
|
http_client_config config;
|
|
config.set_credentials(web::credentials(m_username, m_password));
|
|
http_client client(m_uri, config);
|
|
http_request req(methods::GET);
|
|
req.headers().add(U("UserName"), m_username);
|
|
req.headers().add(U("Password"), m_password);
|
|
http_response response = client.request(req).get();
|
|
VERIFY_ARE_EQUAL(status_codes::OK, response.status_code());
|
|
}
|
|
|
|
TEST_FIXTURE(server_properties, none_auth_with_cred, "Requires", "Server;UserName;Password")
|
|
{
|
|
load_parameters();
|
|
|
|
http_client_config config;
|
|
config.set_credentials(web::credentials(m_username, m_password));
|
|
http_client client(m_uri, config);
|
|
http_response response = client.request(methods::GET).get();
|
|
VERIFY_ARE_EQUAL(status_codes::Forbidden, response.status_code());
|
|
}
|
|
|
|
// This test should be executed for all authentication schemes except None.
|
|
TEST_FIXTURE(server_properties, successful_auth_with_domain_cred, "Requires", "Server;UserName;Password")
|
|
{
|
|
load_parameters();
|
|
|
|
http_client_config config;
|
|
config.set_credentials(web::credentials(m_username, m_password));
|
|
http_client client(m_uri, config);
|
|
http_request req(methods::GET);
|
|
req.headers().add(U("UserName"), m_username);
|
|
req.headers().add(U("Password"), m_password);
|
|
http_response response = client.request(req).get();
|
|
VERIFY_ARE_EQUAL(status_codes::OK, response.status_code());
|
|
}
|
|
|
|
#ifndef __cplusplus_winrt // WinRT implementation doesn't support request buffer caching.
|
|
TEST_FIXTURE(server_properties, failed_authentication_resend_request_error, "Requires", "Server;UserName;Password")
|
|
{
|
|
load_parameters();
|
|
|
|
http_client_config config;
|
|
config.set_credentials(web::credentials(m_username, m_password));
|
|
http_client client(m_uri, config);
|
|
|
|
const size_t rawDataSize = 8;
|
|
|
|
std::vector<unsigned char> data(rawDataSize);
|
|
memcpy(&data[0], "raw data", rawDataSize);
|
|
|
|
http_request request;
|
|
request.set_method(methods::POST);
|
|
request.set_body(data);
|
|
http_response response = client.request(request).get();
|
|
|
|
VERIFY_ARE_EQUAL(200, response.status_code());
|
|
}
|
|
#endif
|
|
|
|
#ifdef __cplusplus_winrt
|
|
TEST_FIXTURE(uri_address, set_user_options_winrt)
|
|
{
|
|
test_http_server::scoped_server scoped(m_uri);
|
|
scoped.server()->next_request().then([](test_request *p_request)
|
|
{
|
|
p_request->reply(status_codes::OK);
|
|
});
|
|
|
|
http_client_config config;
|
|
config.set_nativehandle_options([](native_handle handle)->void{
|
|
auto hr = handle->SetProperty(XHR_PROP_TIMEOUT, 1000);
|
|
if(!SUCCEEDED(hr))
|
|
throw std::runtime_error("The Test Exception");
|
|
});
|
|
http_client client(m_uri, config);
|
|
auto response = client.request(methods::GET).get();
|
|
VERIFY_ARE_EQUAL(200, response.status_code());
|
|
}
|
|
#endif // __cplusplus_winrt
|
|
|
|
#ifdef _WIN32
|
|
#if !defined(__cplusplus_winrt)
|
|
TEST_FIXTURE(server_properties, set_user_options, "Requires", "Server;UserName;Password")
|
|
{
|
|
load_parameters();
|
|
|
|
http_client_config config;
|
|
config.set_credentials(web::credentials(m_username, m_password));
|
|
|
|
config.set_nativehandle_options([&](native_handle handle)->void{
|
|
DWORD policy = WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW;
|
|
if (!WinHttpSetOption(handle,
|
|
WINHTTP_OPTION_AUTOLOGON_POLICY,
|
|
&policy,
|
|
sizeof(policy)))
|
|
{
|
|
throw std::runtime_error("The Test Error");
|
|
}
|
|
});
|
|
|
|
http_client client(m_uri, config);
|
|
|
|
const size_t rawDataSize = 8;
|
|
|
|
std::vector<unsigned char> data(rawDataSize);
|
|
memcpy(&data[0], "raw data", rawDataSize);
|
|
|
|
http_request request;
|
|
request.set_method(methods::POST);
|
|
request.set_body(data);
|
|
|
|
VERIFY_ARE_EQUAL(200, client.request(request).get().status_code());
|
|
}
|
|
|
|
TEST_FIXTURE(uri_address, auth_producer_comsumer_buffer)
|
|
{
|
|
auto buf = streams::producer_consumer_buffer<unsigned char>();
|
|
buf.putc('a').get();
|
|
buf.putc('a').get();
|
|
buf.putc('a').get();
|
|
buf.putc('a').get();
|
|
buf.close(std::ios_base::out).get();
|
|
http_request msg(methods::POST);
|
|
msg.set_body(buf.create_istream());
|
|
|
|
http_client_config config;
|
|
VERIFY_IS_FALSE(config.buffer_request());
|
|
config.set_buffer_request(true);
|
|
VERIFY_IS_TRUE(config.buffer_request());
|
|
config.set_credentials(web::credentials(U("USERNAME"), U("PASSWORD")));
|
|
|
|
http_client client(m_uri, config);
|
|
|
|
test_http_server::scoped_server scoped(m_uri);
|
|
|
|
auto replyFunc = [&](test_request *p_request)
|
|
{
|
|
http_asserts::assert_test_request_equals(p_request, methods::POST, U("/"), U("application/octet-stream"), U("aaaa"));
|
|
p_request->reply(200);
|
|
};
|
|
|
|
scoped.server()->next_request().then([&](test_request *p_request)
|
|
{
|
|
http_asserts::assert_test_request_equals(p_request, methods::POST, U("/"), U("application/octet-stream"), U("aaaa"));
|
|
std::map<utility::string_t, utility::string_t> headers;
|
|
headers[U("WWW-Authenticate")] = U("Basic realm = \"WallyWorld\"");
|
|
|
|
p_request->reply(status_codes::Unauthorized, U("Authentication Failed"), headers);
|
|
})
|
|
.then([&scoped, replyFunc](){
|
|
scoped.server()->next_request().then(replyFunc);
|
|
});
|
|
|
|
http_asserts::assert_response_equals(client.request(msg).get(), status_codes::OK);
|
|
}
|
|
|
|
TEST_FIXTURE(uri_address, auth_producer_comsumer_buffer_fail_no_cred)
|
|
{
|
|
auto buf = streams::producer_consumer_buffer<unsigned char>();
|
|
buf.putc('a').get();
|
|
buf.putc('a').get();
|
|
buf.putc('a').get();
|
|
buf.putc('a').get();
|
|
buf.close(std::ios_base::out).get();
|
|
http_request msg(methods::POST);
|
|
msg.set_body(buf.create_istream());
|
|
|
|
http_client client(m_uri);
|
|
|
|
test_http_server::scoped_server scoped(m_uri);
|
|
|
|
scoped.server()->next_request().then([&](test_request *p_request)
|
|
{
|
|
http_asserts::assert_test_request_equals(p_request, methods::POST, U("/"), U("application/octet-stream"), U("aaaa"));
|
|
std::map<utility::string_t, utility::string_t> headers;
|
|
headers[U("WWW-Authenticate")] = U("Basic realm = \"WallyWorld\"");
|
|
|
|
p_request->reply(status_codes::Unauthorized, U("Authentication Failed"), headers);
|
|
});
|
|
|
|
http_asserts::assert_response_equals(client.request(msg).get(), status_codes::Unauthorized);
|
|
}
|
|
|
|
TEST_FIXTURE(uri_address, auth_producer_comsumer_buffer_fail)
|
|
{
|
|
auto buf = streams::producer_consumer_buffer<unsigned char>();
|
|
buf.putc('a').get();
|
|
buf.close(std::ios_base::out).get();
|
|
http_request msg(methods::POST);
|
|
msg.set_body(buf.create_istream());
|
|
|
|
http_client_config config;
|
|
config.set_buffer_request(true);
|
|
config.set_credentials(web::credentials(U("USERNAME"), U("PASSWORD")));
|
|
|
|
http_client client(m_uri, config);
|
|
|
|
test_http_server::scoped_server scoped(m_uri);
|
|
|
|
auto replyFunc = [&](test_request *p_request)
|
|
{
|
|
http_asserts::assert_test_request_equals(p_request, methods::POST, U("/"), U("application/octet-stream"), U("a"));
|
|
std::map<utility::string_t, utility::string_t> headers;
|
|
headers[U("WWW-Authenticate")] = U("Basic realm = \"WallyWorld2\"");
|
|
|
|
p_request->reply(status_codes::Unauthorized, U("Authentication Failed"), headers);
|
|
};
|
|
|
|
scoped.server()->next_request().then([&](test_request *p_request)
|
|
{
|
|
http_asserts::assert_test_request_equals(p_request, methods::POST, U("/"), U("application/octet-stream"), U("a"));
|
|
std::map<utility::string_t, utility::string_t> headers;
|
|
headers[U("WWW-Authenticate")] = U("Basic realm = \"WallyWorld\"");
|
|
|
|
p_request->reply(status_codes::Unauthorized, U("Authentication Failed"), headers);
|
|
})
|
|
.then([&scoped, replyFunc](){
|
|
scoped.server()->next_request().then(replyFunc);
|
|
});
|
|
|
|
http_asserts::assert_response_equals(client.request(msg).get(), status_codes::Unauthorized);
|
|
}
|
|
#endif
|
|
|
|
TEST_FIXTURE(uri_address, set_user_options_exceptions)
|
|
{
|
|
test_http_server::scoped_server scoped(m_uri);
|
|
http_client_config config;
|
|
class TestException;
|
|
config.set_nativehandle_options([](native_handle)
|
|
{
|
|
throw std::runtime_error("The Test exception");
|
|
});
|
|
http_client client(m_uri, config);
|
|
VERIFY_THROWS(client.request(methods::GET).get(), std::runtime_error);
|
|
}
|
|
#endif // _WIN32
|
|
|
|
// Fix for 522831 AV after failed authentication attempt
|
|
TEST_FIXTURE(uri_address, failed_authentication_attempt, "Ignore:Linux", "89", "Ignore:Apple", "89")
|
|
{
|
|
handle_timeout([]
|
|
{
|
|
http_client_config config;
|
|
web::credentials cred(U("user"), U("schmuser"));
|
|
config.set_credentials(cred);
|
|
http_client client(U("https://apis.live.net"), config);
|
|
http_response response = client.request(methods::GET, U("V5.0/me/skydrive/files")).get();
|
|
VERIFY_ARE_EQUAL(status_codes::Unauthorized, response.status_code());
|
|
auto v = response.extract_vector().get();
|
|
std::string s(v.begin(), v.end());
|
|
// The resulting data must be non-empty (an error about missing access token)
|
|
VERIFY_IS_FALSE(s.empty());
|
|
});
|
|
}
|
|
|
|
#if !defined(_WIN32)
|
|
|
|
TEST_FIXTURE(uri_address, set_user_options_asio_http)
|
|
{
|
|
test_http_server::scoped_server scoped(m_uri);
|
|
scoped.server()->next_request().then([](test_request *p_request)
|
|
{
|
|
p_request->reply(status_codes::OK);
|
|
});
|
|
|
|
http_client_config config;
|
|
config.set_nativehandle_options([](native_handle handle)
|
|
{
|
|
boost::asio::ip::tcp::socket* socket = static_cast<boost::asio::ip::tcp::socket*>(handle);
|
|
// Socket shouldn't be open yet since no requests have gone out.
|
|
VERIFY_ARE_EQUAL(false, socket->is_open());
|
|
});
|
|
http_client client(m_uri, config);
|
|
auto response = client.request(methods::GET).get();
|
|
VERIFY_ARE_EQUAL(200, response.status_code());
|
|
}
|
|
|
|
TEST_FIXTURE(uri_address, set_user_options_asio_https)
|
|
{
|
|
handle_timeout([]
|
|
{
|
|
http_client_config config;
|
|
config.set_nativehandle_options([](native_handle handle)
|
|
{
|
|
boost::asio::ssl::stream<boost::asio::ip::tcp::socket &>* streamobj =
|
|
static_cast<boost::asio::ssl::stream<boost::asio::ip::tcp::socket &>*>(handle);
|
|
const auto &tcpLayer = streamobj->lowest_layer();
|
|
VERIFY_ARE_EQUAL(false, tcpLayer.is_open());
|
|
});
|
|
|
|
http_client client(U("https://apis.live.net"), config);
|
|
http_response response = client.request(methods::GET, U("V5.0/me/skydrive/files")).get();
|
|
VERIFY_ARE_EQUAL(status_codes::Unauthorized, response.status_code());
|
|
auto v = response.extract_vector().get();
|
|
// The resulting data must be non-empty (an error about missing access token)
|
|
VERIFY_IS_FALSE(v.empty());
|
|
});
|
|
}
|
|
|
|
#endif
|
|
|
|
} // SUITE(authentication_tests)
|
|
|
|
}}}}
|