[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/pearsonca/rstudio/master/src/cpp/core/http/Message.cpp [Back]  [Original]

/*
 * Message.cpp
 *
 * Copyright (C) 2009-12 by RStudio, PBC
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include 

#include 

#include 
#include 
#include 
#include 

#include 

namespace rstudio {
namespace core {
namespace http {
  
// encodings
const char * const kGzipEncoding = "gzip";
const char * const kDeflateEncoding = "deflate";

// transfer encodings
const char * const kTransferEncoding = "Transfer-Encoding";
const char * const kChunkedTransferEncoding = "chunked";

void Message::setHttpVersion(int httpVersionMajor, int httpVersionMinor) 
{
   httpVersionMajor_ = httpVersionMajor ;
   httpVersionMinor_ = httpVersionMinor ;
}

void Message::setContentType(const std::string& contentType) 
{
   setHeader("Content-Type", contentType) ;
}

std::string Message::contentType() const 
{
   return headerValue("Content-Type") ;
}

uintmax_t Message::contentLength() const
{
   std::string value = headerValue("Content-Length");
   if (value.empty())
      return 0;

   return safe_convert::stringTo(value, 0);
}

void Message::setContentLength(uintmax_t contentLength)
{
   setHeader("Content-Length", contentLength);
}
   
void Message::addHeader(const std::string& name, const std::string& value) 
{
   Header header ;
   header.name = name ;
   header.value = value ;
   addHeader(header);
}
   
void Message::addHeader(const Header& header)
{
   headers_.push_back(header);
}
   
void Message::addHeaders(const std::vector& headers)
{
   std::copy(headers.begin(), headers.end(), std::back_inserter(headers_));
}

std::string Message::headerValue(const std::string& name) const
{
   return http::headerValue(headers_, name);
}

bool Message::containsHeader(const std::string& name) const
{
   return http::containsHeader(headers_, name);
}
   
void Message::setHeaderLine(const std::string& line)
{
   Header header;
   if (http::parseHeader(line, &header))
      setHeader(header);
}
   
void Message::setHeader(const Header& header)
{
   setHeader(header.name, header.value);
}

void Message::setHeader(const std::string& name, const std::string& value) 
{
   Headers::iterator it = std::find_if(headers_.begin(), 
                                       headers_.end(),
                                       HeaderNamePredicate(name));
   if ( it != headers_.end() )
   {
      Header hdr ;
      hdr.name = name ;
      hdr.value = value ;
      *it = hdr ;
   }
   else
   {
      addHeader(name, value) ;
   }
}
   
void Message::setHeader(const std::string& name, int value)
{
   setHeader(name, safe_convert::numberToString(value));
}

void Message::setHeader(const std::string& name, uintmax_t value)
{
   setHeader(name, safe_convert::numberToString(value));
}

void Message::replaceHeader(const std::string& name, const std::string& value) 
{
   Header hdr ;
   hdr.name = name ;
   hdr.value = value ; 
   std::replace_if(headers_.begin(), 
                   headers_.end(), 
                   HeaderNamePredicate(name), 
                   hdr) ;
}


void Message::removeHeader(const std::string& name) 
{
   headers_.erase(std::remove_if(headers_.begin(), 
                                 headers_.end(),
                                 HeaderNamePredicate(name)), 
                  headers_.end())  ;
}
 
   
void Message::reset() 
{
   setHttpVersion(1,1) ;
   httpVersion_.clear() ;
   headers_.clear() ;
   body_.clear() ;
   
   // allow additional reseting by subclasses
   resetMembers() ;
}

namespace { 
const char Space[] = { ' ' } ;
const char HeaderSeparator[] = { ':', ' ' } ;
const char CrLf[] = { '\r', '\n' } ;
   
void appendHeader(const Header& header,
                  std::vector* pBuffers)
{
   pBuffers->push_back(boost::asio::buffer(header.name)) ;
   pBuffers->push_back(boost::asio::buffer(HeaderSeparator)) ;
   pBuffers->push_back(boost::asio::buffer(header.value)) ;
   pBuffers->push_back(boost::asio::buffer(CrLf)) ;   
}

}

std::vector Message::toBuffers(
                                          const Header& overrideHeader) const
{  
   // buffers to return
   std::vector buffers ;

   // headers
   std::vector headerBuffs =
         headerBuffers(overrideHeader);
   buffers.insert(buffers.end(), headerBuffs.begin(), headerBuffs.end());

   // body
   buffers.push_back(boost::asio::buffer(body_)) ;

   // return the buffers
   return buffers ;
}

std::vector Message::headerBuffers(
                                          const Header& overrideHeader) const
{
   // buffers to return
   std::vector buffers ;

   // call subclass to append first line
   appendFirstLineBuffers(buffers) ;
   buffers.push_back(boost::asio::buffer(CrLf)) ;

   // copy override header (for stable storage)
   overrideHeader_ = overrideHeader;

   // headers
   for (Headers::const_iterator
        it = headers_.begin(); it != headers_.end(); ++it)
   {
      // add the header if it isn't being overriden
      if (it->name != overrideHeader_.name)
         appendHeader(*it, &buffers);
   }

   // add override header
   if (!overrideHeader_.empty())
      appendHeader(overrideHeader_, &buffers);

   // empty line
   buffers.push_back(boost::asio::buffer(CrLf)) ;

   // return the buffers
   return buffers ;
}

   
void Message::appendSpaceBuffer(
                     std::vector& buffers) const
{
   buffers.push_back(boost::asio::buffer(Space)) ;
}

void Message::appendHttpVersionBuffers(
      std::vector& buffers) const
{
   std::ostringstream httpVersionStream;
   httpVersionStream 

Web Proxy Viewer  |  New URL  |  Original Page