UNIXworkcode

/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2013 Olaf Wintermann. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include "error.h" #include <cx/string.h> #include "../util/pblock.h" #include "../util/strbuf.h" // macro for creating an error string (ucx cxmutstr) #define ERRMSG(s) { s, sizeof(s)-1 } static cxmutstr error_400 = ERRMSG("<html><body>bad request</body></html>"); static cxmutstr error_403 = ERRMSG("<html><body>forbidden</body></html>"); static cxmutstr error_404 = ERRMSG("<html><body>not found</body></html>"); static cxmutstr error_500 = ERRMSG("<html><body>server error</body></html>"); static cxmutstr error_503 = ERRMSG("<html><body>service unavailable</body></html>"); static cxmutstr error_std = ERRMSG("<html><body>error</body></html>"); int nsapi_error_request(Session *sn, Request *rq) { short status = rq->status_num; cxmutstr msg; if(status <= 0) { status = 500; msg = error_500; } else if(status < 400) { msg.ptr = NULL; msg.length = 0; } else { switch(status) { default: msg = error_std; case 403: { msg = error_403; break; } case 404: { msg = error_404; break; } case 500: { msg = error_500; break; } } } pblock_removekey(pb_key_content_type, rq->srvhdrs); pblock_removekey(pb_key_content_length, rq->srvhdrs); pblock_kninsert(pb_key_content_length, msg.length, rq->srvhdrs); pblock_nvinsert("content-type", "text/html", rq->srvhdrs); protocol_status(sn, rq, status, NULL); http_start_response(sn, rq); if(msg.length > 0) { net_write(sn->csd, msg.ptr, msg.length); } return REQ_PROCEED; } void fatal_error(HTTPRequest *req, int status) { cxmutstr msg = error_500; char *statusmsg = "Internal Server Error"; switch(status) { case 400: { msg = error_400; statusmsg = "Bad request"; break; } case 500: { msg = error_500; statusmsg = "Internal Server Error"; break; } case 503: { msg = error_503; statusmsg = "Service Unavailable"; break; } } char buf[512]; int len = snprintf(buf, 512, "HTTP/1.1 %d %s\r\nServer: webserver\r\nContent-type: text/html\r\nContent-length: %zd\r\n\r\n", status, statusmsg, msg.length); // set socket blocking int flags; if (-1 == (flags = fcntl(req->connection->fd, F_GETFL, 0))) { flags = 0; } if (fcntl(req->connection->fd, F_SETFL, flags & ~O_NONBLOCK) != 0) { // error } req->connection->write(req->connection, buf, len); req->connection->write(req->connection, msg.ptr, msg.length); }