Merge with dev

--HG--
branch : dev-css
This commit is contained in:
Martín Lucas Golini
2019-04-23 00:14:47 -03:00
5 changed files with 80 additions and 28 deletions

View File

@@ -45,8 +45,10 @@ class EE_API Http : NonCopyable {
** @param method Method to use for the request
** @param body Content of the request's body
** @param validateCertificate Enables certificate validation for https request
** @param validateHostname Enables hostname validation for https request */
Request(const std::string& uri = "/", Method method = Get, const std::string& body = "", bool validateCertificate = true, bool validateHostname = true );
** @param validateHostname Enables hostname validation for https request
** @param followRedirect Allow follor redirects to the request.
*/
Request(const std::string& uri = "/", Method method = Get, const std::string& body = "", bool validateCertificate = true, bool validateHostname = true, bool followRedirect = true);
/** @brief Set the value of a field
** The field is created if it doesn't exist. The name of
@@ -99,6 +101,12 @@ class EE_API Http : NonCopyable {
/** Enable/disable SSL hostname validation */
void setValidateHostname( bool enable );
/** @return If requests follow redirects */
const bool& getFollowRedirect() const;
/** Enables/Disables follow redirects */
void setFollowRedirect( bool follow );
private:
friend class Http;
@@ -126,6 +134,8 @@ class EE_API Http : NonCopyable {
std::string mBody; ///< Body of the request
bool mValidateCertificate; ///< Validates the SSL certificate in case of an HTTPS request
bool mValidateHostname; ///< Validates the hostname in case of an HTTPS request
bool mFollowRedirect; ///< Follows redirect response codes
unsigned int mRedirectionCount; ///< Number of redirections followed by the request
};
/** @brief Define a HTTP response */

View File

@@ -127,7 +127,7 @@ namespace Private {
struct ThreadFunc
{
virtual ~ThreadFunc() {}
virtual void Run() = 0;
virtual void run() = 0;
};
// Specialization using a functor (including free functions) with no argument
@@ -135,7 +135,7 @@ template <typename T>
struct ThreadFunctor : ThreadFunc
{
ThreadFunctor(T functor) : mFunctor(functor) {}
virtual void Run() {mFunctor();}
virtual void run() {mFunctor();}
T mFunctor;
};
@@ -144,7 +144,7 @@ template <typename F, typename A>
struct ThreadFunctorWithArg : ThreadFunc
{
ThreadFunctorWithArg(F function, A arg) : mFunction(function), mArg(arg) {}
virtual void Run() {mFunction(mArg);}
virtual void run() {mFunction(mArg);}
F mFunction;
A mArg;
};
@@ -154,7 +154,7 @@ template <typename C>
struct ThreadMemberFunc : ThreadFunc
{
ThreadMemberFunc(void(C::*function)(), C* object) : mFunction(function), mObject(object) {}
virtual void Run() {(mObject->*mFunction)();}
virtual void run() {(mObject->*mFunction)();}
void(C::*mFunction)();
C* mObject;
};

View File

@@ -1,5 +1,6 @@
#include <eepp/network/http.hpp>
#include <eepp/network/ssl/sslsocket.hpp>
#include <eepp/network/uri.hpp>
#include <eepp/system/iostream.hpp>
#include <eepp/system/iostreamfile.hpp>
#include <cctype>
@@ -12,9 +13,11 @@ using namespace EE::Network::SSL;
namespace EE { namespace Network {
Http::Request::Request(const std::string& uri, Method method, const std::string& body, bool validateCertificate, bool validateHostname ) :
Http::Request::Request(const std::string& uri, Method method, const std::string& body, bool validateCertificate, bool validateHostname , bool followRedirect) :
mValidateCertificate( validateCertificate ),
mValidateHostname( validateHostname )
mValidateHostname( validateHostname ),
mFollowRedirect( followRedirect ),
mRedirectionCount( 0 )
{
setMethod(method);
setUri(uri);
@@ -67,6 +70,14 @@ void Http::Request::setValidateHostname(bool enable) {
mValidateHostname = enable;
}
const bool &Http::Request::getFollowRedirect() const {
return mFollowRedirect;
}
void Http::Request::setFollowRedirect(bool follow) {
mFollowRedirect = follow;
}
std::string Http::Request::prepare() const {
std::ostringstream out;
@@ -261,6 +272,8 @@ Http::~Http() {
}
void Http::setHost(const std::string& host, unsigned short port, bool useSSL) {
bool sameHost( host == mHostName && port == mPort && useSSL == mIsSSL );
// Check the protocol
if (String::toLower(host.substr(0, 7)) == "http://") {
// HTTP protocol
@@ -292,6 +305,15 @@ void Http::setHost(const std::string& host, unsigned short port, bool useSSL) {
mHostName.erase(mHostName.size() - 1);
mHost = IpAddress(mHostName);
// If the new host is different to the last set host
// and there's an open connection to the host, we close
// the old connection to prepare a new one.
if ( !sameHost && NULL != mConnection ) {
TcpSocket * tcp = mConnection;
eeSAFE_DELETE( tcp );
mConnection = NULL;
}
}
Http::Response Http::sendRequest(const Http::Request& request, Time timeout) {
@@ -336,6 +358,26 @@ Http::Response Http::sendRequest(const Http::Request& request, Time timeout) {
mConnection->disconnect();
}
// If a redirection is requested, and requests follows redirections,
// send a new request to the redirection location.
if ( ( received.getStatus() == Response::MovedPermanently || received.getStatus() == Response::MovedTemporarily ) &&
request.getFollowRedirect() ) {
const_cast<Http::Request&>( request ).mRedirectionCount++;
// Only continue redirecting if less than 10 redirections were done
if ( request.mRedirectionCount < 10 ) {
std::string location(received.getField("location"));
URI uri(location);
setHost( uri.getHost(), uri.getPort(), uri.getScheme() == "https" ? true : false );
Http::Request newRequest(request);
newRequest.setUri( uri.getPathEtc() );
return sendRequest( request, timeout );
}
}
return received;
}
@@ -576,8 +618,8 @@ void Http::sendAsyncRequest( AsyncResponseCallback cb, const Http::Request& requ
mThreads.push_back( thread );
}
void Http::downloadAsyncRequest(Http::AsyncResponseCallback cb, const Http::Request & request, IOStream & writeTo, Time timeout) {
AsyncRequest * thread = eeNew( AsyncRequest, ( this, cb, request, timeout ) );
void Http::downloadAsyncRequest(Http::AsyncResponseCallback cb, const Http::Request& request, IOStream& writeTo, Time timeout) {
AsyncRequest * thread = eeNew( AsyncRequest, ( this, cb, request, writeTo, timeout ) );
thread->launch();

View File

@@ -47,7 +47,7 @@ Uint32 Thread::getId() {
}
void Thread::run() {
mEntryPoint->Run();
mEntryPoint->run();
}
}}

View File

@@ -40,29 +40,29 @@ EE_MAIN_FUNC int main (int argc, char * argv []) {
http.setHost( uri.getHost(), uri.getPort() );
// Set the path and query parts for the request
request.setUri( uri.getPathAndQuery() );
}
request.setUri( uri.getPathEtc() );
// Send the request
Http::Response response = http.sendRequest(request);
// Send the request
Http::Response response = http.sendRequest(request);
// Check the status code and display the result
Http::Response::Status status = response.getStatus();
// Check the status code and display the result
Http::Response::Status status = response.getStatus();
if ( status == Http::Response::Ok ) {
Http::Response::FieldTable headers = response.getHeaders();
if ( status == Http::Response::Ok ) {
Http::Response::FieldTable headers = response.getHeaders();
std::cout << "Headers: " << std::endl;
std::cout << "Headers: " << std::endl;
for ( auto head = headers.begin(); head != headers.end(); ++head ) {
std::cout << "\t" << head->first << ": " << head->second << std::endl;
for ( auto head = headers.begin(); head != headers.end(); ++head ) {
std::cout << "\t" << head->first << ": " << head->second << std::endl;
}
std::cout << std::endl << "Body: " << std::endl;
std::cout << response.getBody() << std::endl;
} else {
std::cout << "Error " << status << std::endl;
}
std::cout << std::endl << "Body: " << std::endl;
std::cout << response.getBody() << std::endl;
} else {
std::cout << "Error " << status << std::endl;
}
}