Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

HttpTransport.cpp

Go to the documentation of this file.
00001 /* -*- C++ -*- */
00002 
00003 /*
00004  * The Apache Software License, Version 1.1
00005  *
00006  *
00007  * Copyright (c) 2002 The Apache Software Foundation.  All rights
00008  * reserved.
00009  *
00010  * Redistribution and use in source and binary forms, with or without
00011  * modification, are permitted provided that the following conditions
00012  * are met:
00013  *
00014  * 1. Redistributions of source code must retain the above copyright
00015  *    notice, this list of conditions and the following disclaimer.
00016  *
00017  * 2. Redistributions in binary form must reproduce the above copyright
00018  *    notice, this list of conditions and the following disclaimer in
00019  *    the documentation and/or other materials provided with the
00020  *    distribution.
00021  *
00022  * 3. The end-user documentation included with the redistribution,
00023  *    if any, must include the following acknowledgment:
00024  *       "This product includes software developed by the
00025  *        Apache Software Foundation (http://www.apache.org/)."
00026  *    Alternately, this acknowledgment may appear in the software itself,
00027  *    if and wherever such third-party acknowledgments normally appear.
00028  *
00029  * 4. The names "SOAP" and "Apache Software Foundation" must
00030  *    not be used to endorse or promote products derived from this
00031  *    software without prior written permission. For written
00032  *    permission, please contact apache@apache.org.
00033  *
00034  * 5. Products derived from this software may not be called "Apache",
00035  *    nor may "Apache" appear in their name, without prior written
00036  *    permission of the Apache Software Foundation.
00037  *
00038  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
00039  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00040  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00041  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
00042  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00043  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00044  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
00045  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00046  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00047  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
00048  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00049  * SUCH DAMAGE.
00050  * ====================================================================
00051  *
00052  * This software consists of voluntary contributions made by many
00053  * individuals on behalf of the Apache Software Foundation.  For more
00054  * information on the Apache Software Foundation, please see
00055  * <http://www.apache.org/>.
00056  */
00057 
00058 
00059  
00060 /*
00061  *
00062  *
00063  * @author Lilantha Darshana (lilantha@erunway.com)
00064  *
00065  */
00066 
00067 
00068 #include "Platform.hpp"
00069 #include "HttpTransport.hpp"
00070 #include <iostream>
00071 #include "AxisException.hpp"
00072 
00076 
00077 HttpTransport::~HttpTransport()
00078 {
00079     m_Channel.Close();
00080 }
00081 
00088 
00089 bool HttpTransport::Init()
00090 {
00091     // open a channel for transport
00092     try
00093     {
00094         m_bStatus = true;
00095         std::string host = m_Url.GetHostName();
00096         m_Channel.Open(host, m_Url.GetPort());
00097         m_Channel.SetTransportHandler(this);
00098     }
00099     catch(ChannelException& chEx)
00100     {
00101         std::cerr << chEx.GetErr() << std::endl;
00102         throw;
00103     }
00104     return true;
00105 }
00106 
00107 
00114 
00115 void  HttpTransport::SetProperty(const std::string& p_Property, const std::string& p_Value)
00116 {
00117     m_AdditionalHeader.push_back(std::make_pair(p_Property, p_Value));
00118 }
00119 
00120 
00127 
00128 const Transport& HttpTransport::operator >> (std::string& p_Payload)
00129 {
00130     if(!m_bStatus) 
00131     {
00132         // We have the payload; this is due to Fault request made in earlier call 
00133         // to this method
00134         p_Payload = m_PayLoad;
00135         return *this;
00136     }
00137 
00138     std::string tmpPacket;  // use temporary, need to workout for this
00139     m_Channel >> tmpPacket;
00140 
00141 #ifdef _DEBUG
00142     std::cout << "\n\n\nGot the message:\r\n\r\n" << tmpPacket << "\n\n";
00143 #endif
00144     
00145     // Validate the HTTP packet
00146     if(!m_bStatus) HTTPValidate(tmpPacket);
00147 
00148     // At this point we have the payload at hand so give it out
00149     p_Payload = m_PayLoad;
00150     return *this;
00151 }
00152 
00153 
00158 
00159 const Transport& HttpTransport::operator << (const std::string& p_Payload)
00160 {
00161     HTTPBind(p_Payload);    // Bind the SOAP-Envelop with HTTP headers
00162 
00163 #ifdef _DEBUG
00164     std::cout << "\n\n\n";
00165     std::cout << m_OutMsg.str() << std::endl;
00166 #endif
00167 
00168     // Write to the established channel
00169     m_Channel << m_OutMsg.str();
00170     return *this;
00171 }
00172 
00173 
00181 
00182 void HttpTransport::HTTPBind(const std::string& p_Payload)
00183 {
00184     if(m_Typ == POST)               // only POST is supported for now, wish-list: M-POST??
00185         m_OutMsg << "POST ";
00186 
00187     // Use HTTP 1.1; if HTTP 1.0 is required we have to manage with setting the properties
00188     m_OutMsg << m_Url.GetResource() << " HTTP/1.1\r\n"; // no support for proxy server yet
00189     m_OutMsg << "Host: " << m_Url.GetHostName();
00190 
00191     unsigned short port = m_Url.GetPort();
00192 
00193     if(port != HTTP_PORT)
00194         m_OutMsg << ":" << port;
00195 
00196     m_OutMsg << "\r\n";
00197     m_OutMsg << "Content-Type: text/xml; charset=\"UTF-8\"\r\n";    // We have to support other charsets
00198     m_OutMsg << "Content-Length: " << p_Payload.size() << "\r\n";
00199     
00200     //Set header values for additional prefixes, such as SOAPAction
00201     for(int i=0; i < m_AdditionalHeader.size(); i++)
00202         m_OutMsg << m_AdditionalHeader[i].first << ": \"" 
00203                  << m_AdditionalHeader[i].second << "\"\r\n";
00204 
00205     m_OutMsg << "\r\n";
00206     m_OutMsg << p_Payload;
00207 }
00208 
00209 
00217 
00218 bool HttpTransport::GetStatus(const std::string& p_HttpPacket)
00219 {
00220     HTTPValidate(p_HttpPacket);
00221     return m_bStatus;
00222 }
00223 
00224 
00232 
00233 void HttpTransport::HTTPValidate(const std::string& p_HttpPacket)
00234 {
00235     // for the time being just get the payload. Here we need much work
00236 
00237     m_bStatus = true;
00238     std::string::size_type pos = p_HttpPacket.find('\n'), nxtpos;
00239 
00240     int nHttpSatus;
00241 
00242     if(pos == std::string::npos) return; //unexpected string
00243 
00244     std::string strLine = p_HttpPacket.substr(0, pos + 1);
00245     std::string::size_type offset = pos + 1;
00246 
00247     // Check for HTTP header validity; HTTP 1.0 / HTTP 1.0 is supported.
00248     if((pos = strLine.find("HTTP/1.0")) != std::string::npos
00249         || (pos = strLine.find("HTTP/1.1")) != std::string::npos)
00250     {
00251         if(((pos = strLine.find_first_of("\" ", pos + strlen("HTTP/1.x"))) 
00252             != std::string::npos) &&
00253             (nxtpos = strLine.find_first_of("\" ", pos)) != std::string::npos)
00254         {
00255             pos++;
00256             // Get the HTTP status code of the packet obtained
00257             nHttpSatus = atoi(strLine.substr(pos, nxtpos - pos).c_str())/100;
00258         }
00259         else
00260             return;
00261 
00262 
00263         // Status code is 2xx; so valid packet. hence go ahead and extract the payload.
00264         if(nHttpSatus == 2)
00265         {
00266             GetPayLoad(p_HttpPacket, offset);
00267         }
00268         else if(nHttpSatus == 3)    // Status code is 3xx; some error has occurred
00269         {
00270             // error recovery mechanism should go here
00271             Error(p_HttpPacket.c_str());
00272             throw ChannelException("HTTP Error, cannot process response message...");
00273         }
00274         else if(nHttpSatus == 4)    // Status code is 4xx; some error has occurred
00275         {
00276             // error recovery mechanism should go here
00277             Error(p_HttpPacket.c_str());
00278             throw ChannelException("HTTP Error, cannot process response message...");
00279         }
00280         else if(nHttpSatus == 5)    // Status code is 5xx; some error has occurred
00281         {
00282             // error recovery mechanism should go here
00283             GetPayLoad(p_HttpPacket, offset);
00284             if (!m_bStatus) 
00285             {
00286                 Error(p_HttpPacket.c_str());
00287                 throw AxisFault("HTTP Error, cannot process response message...", 1);
00288             }
00289         }
00290     }
00291     else
00292         throw ChannelException("Unknow HTTP response, cannot process response message...");
00293 
00294 }
00295 
00296 
00301 
00302 void HttpTransport::GetPayLoad(const std::string& p_HttpPacket, std::string::size_type& offset)
00303 {
00304     std::string::size_type pos, nxtpos;
00305     std::string strLine;
00306     int len=0;
00307 
00308     // process rest of the HTTP packet
00309     while (true)
00310     {
00311         if((nxtpos = p_HttpPacket.find('\n', offset)) == std::string::npos) return;
00312         nxtpos++;
00313         strLine = p_HttpPacket.substr(offset, nxtpos - offset);
00314         offset = nxtpos;
00315 
00316         if((strLine == "\r\n") || (strLine == "\n") || strLine.size() <= 1)
00317             break;
00318 
00319         // Get the payload size from the header.
00320         if((pos = strLine.find("Content-Length:")) != std::string::npos) 
00321             len = atoi(strLine.substr(pos + strlen("Content-Length: ")).c_str());
00322     }
00323 
00324     m_PayLoad = p_HttpPacket.substr(offset);
00325 
00326     pos = m_PayLoad.rfind("</soapenv:Envelope>"); //look for end of the message
00327 
00328     if(std::string::npos != pos && m_PayLoad[pos+1] != '\"')
00329     {
00330         m_bStatus = false; // we have the payload
00331 
00332     #ifdef _DEBUG
00333         std::cout << "Payload:\n" 
00334                   << m_PayLoad.substr(m_PayLoad.find('<'), m_PayLoad.rfind('>') + 1) 
00335                   << std::endl;
00336     #endif
00337     
00338     }
00339 }
00340 
00341 
00346 
00347 void HttpTransport::Error(const char * err)
00348 {
00349 #ifdef _DEBUG
00350     std::cerr << err << std::endl;
00351 #endif
00352 }
00353 
Axis C++ Client Lib - User's Guide

Copyright © 2001 SL_OpenSource XML Project. All Rights Reserved