32 m_callback(callback) ,
45 G_DEBUG(
"HttpClientProtocol::apply: " << n <<
" bytes\n" << G::hexdump<16>(p,p+n) ) ;
46 m_parser.apply( p , n ) ;
50 void GNet::HttpClientProtocol::processData()
52 G_DEBUG(
"HttpClientProtocol::apply: "
53 <<
"have=" << m_parser.bodySize() <<
" "
54 <<
"want=" << m_parser.headerContentLength() <<
" "
55 <<
"multipart=" << m_parser.headerMultipart() <<
" "
56 <<
"ok=" << m_parser.responseOk() <<
" "
57 <<
"got-headers=" << m_parser.gotHeaders() <<
" "
58 <<
"got-body=" << m_parser.gotBody() <<
" "
61 if( !m_parser.gotHeaders() )
65 else if( m_parser.responseUnauthorised() && m_url.authorisation().empty() )
67 throw Auth(
"authorisation required" ) ;
69 else if( m_parser.responseUnauthorised() && m_parser.gotBody() && m_tried_auth )
71 throw Fail(
"authorisation failed" ) ;
73 else if( m_parser.responseUnauthorised() && m_parser.gotBody() )
79 else if( m_parser.responseRetry() )
81 throw Retry(
"service unavailable" ) ;
83 else if( m_parser.responseOk() && m_parser.headerMultipart() && m_parser.gotPart() )
86 m_parser.clearPart() ;
88 else if( m_parser.responseOk() && m_parser.headerMultipart() )
92 else if( m_parser.responseOk() && m_parser.gotBody() )
97 else if( m_parser.responseOk() )
103 throw Fail(
"unexpected http response: [" +
G::Str::printable(m_parser.responseSummary()) +
"]" ) ;
107 void GNet::HttpClientProtocol::sendGet()
109 std::string
get =
"GET " + m_url.request() +
" HTTP/1.1\r\n" +
"\r\n" ;
110 G_LOG(
"GNet::HttpClientProtocol::sendGet: sending [" <<
G::Str::printable(
get) <<
"]" ) ;
111 m_callback.sendHttpRequest(
get ) ;
115 const G::Url & url , std::string command ,
bool long_uri )
117 if( command.empty() ) command =
"GET" ;
120 std::string::size_type pos = auth.find(
":") ;
125 typedef std::vector<size_t> List ;
126 List hlist = parser.
headers(
"WWW-Authenticate" ) ;
127 for( List::iterator p = hlist.begin() ; p != hlist.end() ; ++p )
130 std::string auth_type = parser.
headerWord( index ) ;
134 if( auth_type ==
"Basic" )
139 else if( auth_type ==
"Digest" )
143 std::string ha1 = hash( user +
":" + realm +
":" + pwd ) ;
144 std::string ha2 = hash( command +
":" + uri ) ;
145 std::string auth_response = hash( ha1 +
":" + nonce +
":" + ha2 ) ;
146 result = std::string() +
147 "Authorization: Digest " +
148 "username=\"" + user +
"\", " +
149 "realm=\"" + realm +
"\", " +
150 "nonce=\"" + nonce +
"\", " +
151 "uri=\"" + uri +
"\", " +
152 "response=\"" + auth_response +
"\"" +
153 (opaque.empty()?
"":
", opaque=\"") + opaque + (opaque.empty()?
"":
"\"") ;
158 throw Fail(
"no supported authentication mechanism" ) ;
162 void GNet::HttpClientProtocol::sendGetWithAuth()
164 std::string
get =
"GET " + m_url.request() +
" HTTP/1.1\r\n" +
165 authorisation(m_parser,m_url) +
168 G_LOG(
"GNet::HttpClientProtocol::sendGetWithAuth: sending [" <<
G::Str::printable(
get) <<
"]" ) ;
169 m_callback.sendHttpRequest(
get ) ;
172 std::string GNet::HttpClientProtocol::hash(
const std::string & s )
177 void GNet::HttpClientProtocol::processBody()
179 m_callback.onHttpBody( std::string() , m_parser.header(
"Content-Type") , m_parser.bodyData() , m_parser.bodySize() ) ;
182 void GNet::HttpClientProtocol::processPart()
184 m_callback.onHttpBody( m_parser.header(
"Content-Type") , m_parser.partType() , m_parser.partData() , m_parser.partSize() ) ;
static std::string printable(const std::string &in, char escape= '\\')
Returns a printable represention of the given input string.
void apply(const char *, size_t)
To be called on receipt of data.
std::vector< size_t > headers(const std::string &header_key) const
Returns the indexes for the headers with the given key.
HttpClientProtocol(Callback &, const G::Url &url)
Constructor.
A simple parser for URLs.
std::string headerWord(const std::string &header_key, const std::string &default_=std::string()) const
Returns the first part of the header with the given key.
A callback interface for GNet::HttpClientProtocol to send data and deliver content.
static std::string tail(const std::string &in, std::string::size_type pos, const std::string &default_=std::string())
Returns the last part of the string after the given position.
A parser for HTTP responses received from a remote server.
std::string path() const
Returns the path part, including the leading slash.
void start()
Assembles a GET request (based on the constructor url) and asks the callback interface to send it...
static std::string head(const std::string &in, std::string::size_type pos, const std::string &default_=std::string())
Returns the first part of the string up to just before the given position.
std::string protocol() const
Returns the protocol part eg. "http".
static std::string digest(const std::string &input)
Creates an MD5 digest.
std::string headerAttribute(const std::string &header_key, const std::string &attribute_key, const std::string &default_=std::string()) const
Returns a named attribute of the specified header.
std::string authorisation() const
Returns the "user:pwd" part.
static std::string authorisation(const GNet::HttpClientParser &, const G::Url &, std::string get=std::string(), bool=false)
Returns an "Authorization" header for adding to a "GET" request.
virtual ~Callback()
Destructor.
static std::string encode(const std::string &s, const std::string &line_break)
Encodes the given string.
std::string address() const
Returns the address part, which might include the port, and which might use ipv6 square brackets...
static std::string printable(const std::string &input)
Converts a binary string into a printable form, using a lowercase hexadecimal encoding.