using namespace std;
-#include <iostream>
-
namespace Msp {
namespace Http {
+Message::Message():
+ http_version(0x11),
+ chunk_length(0),
+ complete(false)
+{ }
+
void Message::set_header(const string &hdr, const string &val)
{
- headers[tolower(hdr)]=val;
+ headers[normalize_header_name(hdr)]=val;
}
const string &Message::get_header(const string &hdr) const
{
- HeaderMap::const_iterator i=headers.find(hdr);
+ HeaderMap::const_iterator i=headers.find(normalize_header_name(hdr));
if(i==headers.end())
- throw KeyError(format("Header %s is not defined", hdr));
+ throw KeyError("Undefined header", hdr);
return i->second;
}
-void Message::add_data(const string &d)
+void Message::add_content(const string &d)
{
- data+=d;
- if(headers.count("content-type")==0)
- set_header("content-type", "text/plain");
- set_header("content-length", lexical_cast(data.size()));
+ content+=d;
+ if(headers.count("Content-Type")==0)
+ set_header("Content-Type", "text/plain");
+ set_header("Content-Length", lexical_cast(content.size()));
}
-unsigned Message::parse_data(const string &d)
+void Message::set_user_data(const Variant &d)
+{
+ user_data=d;
+}
+
+unsigned Message::parse_content(const string &d)
{
if(complete)
return 0;
- HeaderMap::const_iterator i=headers.find("content-length");
+ HeaderMap::const_iterator i=headers.find("Content-Length");
if(i!=headers.end())
{
- unsigned needed=lexical_cast<unsigned>(i->second)-data.size();
+ unsigned needed=lexical_cast<unsigned>(i->second)-content.size();
unsigned len=min(needed, d.size());
- data.append(d, 0, len);
+ content.append(d, 0, len);
if(len==needed)
complete=true;
return len;
}
- i=headers.find("transfer-encoding");
+ i=headers.find("Transfer-Encoding");
if(i!=headers.end() && strcasecmp(i->second, "chunked")==0)
{
unsigned pos=0;
unsigned lf=d.find('\n', pos);
if(lf==string::npos)
return pos;
- // XXX strtoul
- chunk_length=strtoul(strip(d.substr(pos, lf-pos)).c_str(), 0, 16);
+ chunk_length=lexical_cast<unsigned>(strip(d.substr(pos, lf-pos)), "x");
if(chunk_length==0)
complete=true;
pos=lf+1;
else
{
unsigned len=min(chunk_length, d.size()-pos);
- data.append(d, pos, len);
+ content.append(d, pos, len);
chunk_length-=len;
if((pos=d.find('\n', pos+len))!=string::npos)
++pos;
return pos;
}
+ complete=true;
return 0;
}
-Message::Message():
- http_version(0x11),
- chunk_length(0),
- complete(false)
-{ }
+unsigned Message::parse_headers(const string &d)
+{
+ unsigned start=0;
+ while(1)
+ {
+ unsigned lf=d.find('\n', start);
+ if(lf==string::npos)
+ throw InvalidParameterValue("Incomplete response");
+ if(lf==start || (d[start]=='\r' && lf==start+1))
+ return lf+1;
+
+ unsigned colon=d.find(':', start);
+ if(colon>lf)
+ throw InvalidParameterValue("No colon in header");
+
+ set_header(d.substr(start, colon-start), strip(d.substr(colon+1, lf-colon-1)));
+
+ start=lf+1;
+ }
+}
string Message::str_common() const
{
string result;
for(HeaderMap::const_iterator i=headers.begin(); i!=headers.end(); ++i)
- result+=format("%s: %s\r\n", i->first, i->second);
+ if(i->first[0]!='-')
+ result+=format("%s: %s\r\n", i->first, i->second);
result+="\r\n";
- result+=data;
+ result+=content;
return result;
}
+string Message::normalize_header_name(const string &hdr) const
+{
+ string result=hdr;
+ bool upper=true;
+ for(string::iterator i=result.begin(); i!=result.end(); ++i)
+ {
+ if(upper)
+ {
+ *i=toupper(*i);
+ upper=false;
+ }
+ else if(*i=='-')
+ upper=true;
+ else
+ *i=tolower(*i);
+ }
+ return result;
+}
+
} // namespace Http
} // namespace Msp