asio 0.3.8rc3 | Home | Reference | Tutorial | Examples | Design

Examples |

# http/server/request_handler.cpp

Go to the documentation of this file.

    00001 //
    00002 // request_handler.cpp
    00003 // ~~~~~~~~~~~~~~~~~~~
    00004 //
    00005 // Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
    00006 //
    00007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
    00008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
    00009 //
    00010
    00011 #include "request_handler.hpp"
    00012 #include <fstream>
    00013 #include <sstream>
    00014 #include <string>
    00015 #include <boost/lexical_cast.hpp>
    00016 #include "mime_types.hpp"
    00017 #include "reply.hpp"
    00018 #include "request.hpp"
    00019
    00020 namespace http {
    00021 namespace server {
    00022
    00023 request_handler::request_handler(const std::string& doc_root)
    00024   : doc_root_(doc_root)
    00025 {
    00026 }
    00027
    00028 void request_handler::handle_request(const request& req, reply& rep)
    00029 {
    00030   // Decode url to path.
    00031   std::string request_path;
    00032   if (!url_decode(req.uri, request_path))
    00033   {
    00034     rep = reply::stock_reply(reply::bad_request);
    00035     return;
    00036   }
    00037
    00038   // Request path must be absolute and not contain "..".
    00039   if (request_path.empty() || request_path[0] != '/'
    00040       || request_path.find("..") != std::string::npos)
    00041   {
    00042     rep = reply::stock_reply(reply::bad_request);
    00043     return;
    00044   }
    00045
    00046   // If path ends in slash (i.e. is a directory) then add "index.html".
    00047   if (request_path[request_path.size() - 1] == '/')
    00048   {
    00049     request_path += "index.html";
    00050   }
    00051
    00052   // Determine the file extension.
    00053   std::size_t last_slash_pos = request_path.find_last_of("/");
    00054   std::size_t last_dot_pos = request_path.find_last_of(".");
    00055   std::string extension;
    00056   if (last_dot_pos != std::string::npos && last_dot_pos > last_slash_pos)
    00057   {
    00058     extension = request_path.substr(last_dot_pos + 1);
    00059   }
    00060
    00061   // Open the file to send back.
    00062   std::string full_path = doc_root_ + "/" + request_path;
    00063   std::ifstream is(full_path.c_str(), std::ios::in | std::ios::binary);
    00064   if (!is)
    00065   {
    00066     rep = reply::stock_reply(reply::not_found);
    00067     return;
    00068   }
    00069
    00070   // Fill out the reply to be sent to the client.
    00071   rep.status = reply::ok;
    00072   char buf[512];
    00073   while (is.read(buf, sizeof(buf)).gcount() > 0)
    00074     rep.content.append(buf, is.gcount());
    00075   rep.headers.resize(2);
    00076   rep.headers[0].name = "Content-Length";
    00077   rep.headers[0].value = boost::lexical_cast<std::string>(rep.content.size());
    00078   rep.headers[1].name = "Content-Type";
    00079   rep.headers[1].value = mime_types::extension_to_type(extension);
    00080 }
    00081
    00082 bool request_handler::url_decode(const std::string& in, std::string& out)
    00083 {
    00084   out.clear();
    00085   out.reserve(in.size());
    00086   for (std::size_t i = 0; i < in.size(); ++i)
    00087   {
    00088     if (in[i] == '%')
    00089     {
    00090       if (i + 3 <= in.size())
    00091       {
    00092         int value;
    00093         std::istringstream is(in.substr(i + 1, 2));
    00094         if (is >> std::hex >> value)
    00095         {
    00096           out += static_cast<char>(value);
    00097           i += 2;
    00098         }
    00099         else
    00100         {
    00101           return false;
    00102         }
    00103       }
    00104       else
    00105       {
    00106         return false;
    00107       }
    00108     }
    00109     else
    00110     {
    00111       out += in[i];
    00112     }
    00113   }
    00114   return true;
    00115 }
    00116
    00117 } // namespace server
    00118 } // namespace http

asio 0.3.8rc3 | Home | Reference | Tutorial | Examples | Design