From 32bb7218cec6d6176ba1a026fdb7cde9e6e1df2e Mon Sep 17 00:00:00 2001 From: Pixel Date: Sat, 19 Nov 2011 23:12:40 -0800 Subject: Adding error 500s support. --- src/HttpServer.cc | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 70 insertions(+), 4 deletions(-) (limited to 'src/HttpServer.cc') diff --git a/src/HttpServer.cc b/src/HttpServer.cc index 961af0f..18dc6c8 100644 --- a/src/HttpServer.cc +++ b/src/HttpServer.cc @@ -3,6 +3,26 @@ #include "Socket.h" #include "BStream.h" +class OutputCheck : public Balau::Handle { + public: + OutputCheck(Balau::IO h) : m_h(h), m_wrote(false) { Assert(m_h->canWrite()); m_name.set("OutputCheck(%s)", m_h->getName()); } + virtual void close() throw (Balau::GeneralException) { m_h->close(); } + virtual bool isEOF() { return m_h->isEOF(); } + virtual bool canWrite() { return true; } + virtual const char * getName() { return m_name.to_charp(); } + virtual ssize_t write(const void * buf, size_t count) throw (Balau::GeneralException) { + if (!count) + return 0; + m_wrote = true; + return m_h->write(buf, count); + } + bool wrote() { return m_wrote; } + private: + Balau::IO m_h; + Balau::String m_name; + bool m_wrote; +}; + static const ev_tstamp s_httpTimeout = 5; #define DAEMON_NAME "Balau/1.0" @@ -19,6 +39,7 @@ class HttpWorker : public Task { bool handleClient(); void send400(); void send404(); + void send500(const char * msg); String httpUnescape(const char * in); void readVariables(Http::StringMap & variables, char * str); @@ -109,7 +130,8 @@ void Balau::HttpWorker::send400() { " \n" "\n"; - m_socket->forceWrite(str, sizeof(str) - 1); + if (!m_socket->isClosed()) + m_socket->forceWrite(str, sizeof(str) - 1); Balau::Printer::elog(Balau::E_HTTPSERVER, "%s had an invalid request", m_name.to_charp()); } @@ -131,7 +153,37 @@ void Balau::HttpWorker::send404() { " \n" "\n"; - m_socket->forceWrite(str, sizeof(str) - 1); + if (!m_socket->isClosed()) + m_socket->forceWrite(str, sizeof(str) - 1); + Balau::Printer::elog(Balau::E_HTTPSERVER, "%s had an invalid request", m_name.to_charp()); +} + +void Balau::HttpWorker::send500(const char * msg) { + static const char str[] = +"HTTP/1.1 500 Not Found\r\n" +"Content-Type: text/html; charset=UTF-8\r\n" +"Server: " DAEMON_NAME "\r\n" +"\r\n" +"\n" +"\n" +" \n" +" 500 Internal Error\n" +" \n" +"\n" +" \n" +" The HTTP request you've sent triggered an internal error: `"; + static const char str2[] = +"'.\n" +" \n" +"\n"; + + if (!m_socket->isClosed()) + m_socket->forceWrite(str, sizeof(str) - 1); + if (!m_socket->isClosed()) + m_socket->forceWrite(msg, strlen(msg)); + if (!m_socket->isClosed()) + m_socket->forceWrite(str2, sizeof(str2) - 1); Balau::Printer::elog(Balau::E_HTTPSERVER, "%s had an invalid request", m_name.to_charp()); } @@ -377,6 +429,7 @@ bool Balau::HttpWorker::handleClient() { HttpServer::ActionFound f = m_server->findAction(uri.to_charp(), host.to_charp()); if (f.first) { + IO out(m_socket); Http::Request req; req.method = method; req.host = host; @@ -385,8 +438,21 @@ bool Balau::HttpWorker::handleClient() { req.headers = httpHeaders; req.files = files; req.persistent = persistent; - if (!f.first->Do(m_server, req, f.second, m_socket)) { - persistent = false; + try { + if (!f.first->Do(m_server, req, f.second, out)) + persistent = false; + } + catch (GeneralException e) { + Balau::Printer::elog(Balau::E_HTTPSERVER, "%s got an exception while processing its request: `%s'", m_name.to_charp(), e.getMsg()); + if (!out->wrote()) + send500(e.getMsg()); + return false; + } + catch (...) { + Balau::Printer::elog(Balau::E_HTTPSERVER, "%s got an un unknow exception while processing its request: `%s'", m_name.to_charp()); + if (!out->wrote()) + send500("unknow exception"); + return false; } } else { send404(); -- cgit v1.2.3