bool HTTPServerConnection::handleRequest(Request* request) {
  // This is a way to remotely shutdown the Server to which this
  // connection belongs.
  TicksClock::Ticks start, end, duration;
  double in_seconds;
  start = TicksClock::getTicks();

  if (request_.address == "quit") {
    LOG(LogMessage::NORMAL) << "Server stop requested!";
    my_service_->stop();
    return false;
  }

  RequestStats* stats = my_service_->stats();
  uint32_t timeToHandleRequest;
  uint32_t timeToParseRequest;
  uint32_t timeToEstablishConn;
  uint32_t reqsLastSec;


  stats->getStats(TicksClock::getTicks(), &reqsLastSec, &timeToHandleRequest, &timeToParseRequest, &timeToEstablishConn);



  if (request_.address == "stats") {
    ostringstream stats_stream;
    stats_stream << reqsLastSec;
    string stats_string = stats_stream.str();

    m_write_.lock();

    out_.write("HTTP/1.1 200 OK\r\n");
    out_.write("Date: Wed, 28 Oct 2009 15:24:11 GMT\r\n");
    out_.write("Server: Lab02a\r\n");
    out_.write("Accept-Ranges: bytes\r\n");

    ostringstream os;
    os << "Content-Length: " << stats_string.size() << "\r\n";
    out_.write(os.str().c_str());
    out_.write("Content-Type: text/html\r\n");
    out_.write("\r\n");
    out_.write(stats_string.c_str());

    m_write_.unlock();
    TicksClock::Ticks end = TicksClock::getTicks();
    TicksClock::Ticks duration = end - start;
    in_seconds = duration / TicksClock::ticksPerSecond();
    stats->updateTimeToHandleRequest(in_seconds);

    TicksClock::Ticks start = TicksClock::getTicks();
    startWrite();
    end = TicksClock::getTicks();
    duration = end - start;
    in_seconds = duration / TicksClock::ticksPerSecond();
    stats->updateTimeToHandleRequest(in_seconds);
    return true;

  }

  // If the request is for the root document, expand the name to
  // 'index.html'
  if (request_.address.empty()) {
    request_.address = "index.html";
  }

  // Grab from or load the file to the cache.
  Buffer* buf;
  int error;
  FileCache::CacheHandle h = file_cache_->pin(request_.address, &buf, & error);

  if (h != 0) {
    m_write_.lock();

    out_.write("HTTP/1.1 200 OK\r\n");
    out_.write("Date: Wed, 28 Oct 2009 15:24:11 GMT\r\n");
    out_.write("Server: Lab02a\r\n");
    out_.write("Accept-Ranges: bytes\r\n");

    ostringstream os;
    os << "Content-Length: " << buf->readSize() << "\r\n";
    out_.write(os.str().c_str());
    out_.write("Content-Type: text/html\r\n");
    out_.write("\r\n");

    // Copy from cache into the connection buffer.
    out_.copyFrom(buf);

    m_write_.unlock();

  } else {

    // TODO
    //
    // differentiate between a server internal error (ie too many
    // sockets open), which should return a 500 and a file not found,
    // which should return a 404.
    perror("Can't serve request");

    m_write_.lock();

    ostringstream html_stream;
    html_stream <<"<HTML>\r\n";
    html_stream <<"<HEAD><TITLE>400 Bad Request</TITLE></HEAD>\r\n";
    html_stream <<"<BODY>Bad Request</BODY>\r\n";
    html_stream <<"</HTML>\r\n";
    html_stream <<"\r\n";

    ostringstream os;
    os << "Content-Length: " << html_stream.str().size() << "\r\n";

    out_.write("HTTP/1.1 503 Bad Request\r\n");
    out_.write("Date: Wed, 28 Oct 2009 15:24:11 GMT\r\n");
    out_.write("Server: MyServer\r\n");
    out_.write("Connection: close\r\n");
    out_.write("Transfer-Encoding: chunked\r\n");
    out_.write(os.str().c_str());
    out_.write("Content-Type: text/html; charset=iso-8859-1\r\n");
    out_.write("\r\n");

    out_.write(html_stream.str().c_str());

    m_write_.unlock();

  }

  end = TicksClock::getTicks();
  duration = end - start;
  in_seconds = duration / TicksClock::ticksPerSecond();
  stats->updateTimeToHandleRequest(in_seconds);

  stats->finishedRequest(ThreadPoolFast::ME(), TicksClock::getTicks());

  start = TicksClock::getTicks();
  startWrite();
  end = TicksClock::getTicks();
  duration = end - start;
  in_seconds = duration / TicksClock::ticksPerSecond();
  stats->updateTimeToHandleRequest(in_seconds);

  return true;
}
コード例 #2
0
bool HTTPServerConnection::handleRequest(Request* request) {
  // This is a way to remotely shutdown the Server to which this
  // connection belongs.
  if (request_.address == "quit") {
    LOG(LogMessage::NORMAL) << "Server stop requested!";
    io_service()->stop();
    return false;
  }

  RequestStats* stats = io_service()->stats();
  if (request_.address == "stats") {
    uint32_t reqsLastSec;
    stats->getStats(TicksClock::getTicks(), &reqsLastSec);
    ostringstream stats_stream;
    stats_stream << reqsLastSec;
    string stats_string = stats_stream.str();

    m_write_.lock();

    out_.write("HTTP/1.1 200 OK\r\n");
    out_.write("Date: Wed, 28 Oct 2009 15:24:11 GMT\r\n");
    out_.write("Server: Lab02a\r\n");
    out_.write("Accept-Ranges: bytes\r\n");

    ostringstream os;
    os << "Content-Length: " << stats_string.size() << "\r\n";
    out_.write(os.str().c_str());
    out_.write("Content-Type: text/html\r\n");
    out_.write("\r\n");
    out_.write(stats_string.c_str());

    m_write_.unlock();

    startWrite();
    return true;
  }

  // If the request is for the root document, expand the name to
  // 'index.html'
  if (request_.address.empty()) {
    request_.address = "index.html";
  }

  int fd = open(request_.address.c_str(), O_RDONLY);
  if (fd != -1) {
    struct stat stat_buf;
    fstat(fd, &stat_buf);

    m_write_.lock();

    out_.write("HTTP/1.1 200 OK\r\n");
    out_.write("Date: Wed, 28 Oct 2009 15:24:11 GMT\r\n");
    out_.write("Server: Lab02a\r\n");
    out_.write("Accept-Ranges: bytes\r\n");

    ostringstream os;
    os << "Content-Length: " << stat_buf.st_size << "\r\n";
    out_.write(os.str().c_str());
    out_.write("Content-Type: text/html\r\n");
    out_.write("\r\n");
    out_.reserve(stat_buf.st_size);

    m_write_.unlock();

    // This is going to break with files bigger than
    // Buffer::Blocksize bytes, But... let's leave it for now.

    int res = read(fd, out_.writePtr(), out_.writeSize());
    if (res < 0) {
      perror("Error reading file");
      exit(1);
    }
    ::close(fd);

    m_write_.lock();
    out_.advance(res);
    m_write_.unlock();

  } else {

    // TODO
    //
    // differentiate between a server internal error (ie too many
    // sockets open), which should return a 500 and a file not found,
    // which should return a 404.
    perror("Can't serve request");

    m_write_.lock();

    ostringstream html_stream;
    html_stream <<"<HTML>\r\n";
    html_stream <<"<HEAD><TITLE>400 Bad Request</TITLE></HEAD>\r\n";
    html_stream <<"<BODY>Bad Request</BODY>\r\n";
    html_stream <<"</HTML>\r\n";
    html_stream <<"\r\n";

    ostringstream os;
    os << "Content-Length: " << html_stream.str().size() << "\r\n";

    out_.write("HTTP/1.1 503 Bad Request\r\n");
    out_.write("Date: Wed, 28 Oct 2009 15:24:11 GMT\r\n");
    out_.write("Server: MyServer\r\n");
    out_.write("Connection: close\r\n");
    out_.write("Transfer-Encoding: chunked\r\n");
    out_.write(os.str().c_str());
    out_.write("Content-Type: text/html; charset=iso-8859-1\r\n");
    out_.write("\r\n");

    out_.write(html_stream.str().c_str());

    m_write_.unlock();

  }

  stats->finishedRequest(ThreadPoolFast::ME(), TicksClock::getTicks());

  startWrite();
  return true;
}