]> git.tdb.fi Git - libs/net.git/blobdiff - source/message.cpp
Add Server class
[libs/net.git] / source / message.cpp
index e0a5e7e171bf8afad01cf8932e4ca01acfb720b1..93937c90a71dff3ee8fa65a2fdf973f37e515525 100644 (file)
@@ -12,21 +12,25 @@ Distributed under the LGPL
 
 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;
 }
@@ -34,9 +38,9 @@ const string &Message::get_header(const string &hdr) const
 void Message::add_content(const string &d)
 {
        content+=d;
-       if(headers.count("content-type")==0)
-               set_header("content-type", "text/plain");
-       set_header("content-length", lexical_cast(content.size()));
+       if(headers.count("Content-Type")==0)
+               set_header("Content-Type", "text/plain");
+       set_header("Content-Length", lexical_cast(content.size()));
 }
 
 void Message::set_user_data(const Variant &d)
@@ -49,7 +53,7 @@ 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)-content.size();
@@ -63,7 +67,7 @@ unsigned Message::parse_content(const string &d)
                return len;
        }
 
-       i=headers.find("transfer-encoding");
+       i=headers.find("Transfer-Encoding");
        if(i!=headers.end() && strcasecmp(i->second, "chunked")==0)
        {
                unsigned pos=0;
@@ -92,26 +96,62 @@ unsigned Message::parse_content(const string &d)
                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+=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