UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2013 Olaf Wintermann. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include "error.h" 30 31 #include <cx/string.h> 32 #include "../util/pblock.h" 33 #include "../util/strbuf.h" 34 35 // macro for creating an error string (ucx cxmutstr) 36 #define ERRMSG(s) { s, sizeof(s)-1 } 37 38 static cxmutstr error_400 = ERRMSG("<html><body>bad request</body></html>"); 39 static cxmutstr error_403 = ERRMSG("<html><body>forbidden</body></html>"); 40 static cxmutstr error_404 = ERRMSG("<html><body>not found</body></html>"); 41 static cxmutstr error_500 = ERRMSG("<html><body>server error</body></html>"); 42 static cxmutstr error_503 = ERRMSG("<html><body>service unavailable</body></html>"); 43 44 static cxmutstr error_std = ERRMSG("<html><body>error</body></html>"); 45 46 int nsapi_error_request(Session *sn, Request *rq) { 47 short status = rq->status_num; 48 cxmutstr msg; 49 if(status <= 0) { 50 status = 500; 51 msg = error_500; 52 } else if(status < 400) { 53 msg.ptr = NULL; 54 msg.length = 0; 55 } else { 56 switch(status) { 57 default: msg = error_std; 58 case 403: { 59 msg = error_403; 60 break; 61 } 62 case 404: { 63 msg = error_404; 64 break; 65 } 66 case 500: { 67 msg = error_500; 68 break; 69 } 70 } 71 } 72 73 pblock_removekey(pb_key_content_type, rq->srvhdrs); 74 pblock_removekey(pb_key_content_length, rq->srvhdrs); 75 76 pblock_kninsert(pb_key_content_length, msg.length, rq->srvhdrs); 77 pblock_nvinsert("content-type", "text/html", rq->srvhdrs); 78 protocol_status(sn, rq, status, NULL); 79 http_start_response(sn, rq); 80 81 if(msg.length > 0) { 82 net_write(sn->csd, msg.ptr, msg.length); 83 } 84 85 return REQ_PROCEED; 86 } 87 88 void fatal_error(HTTPRequest *req, int status) { 89 cxmutstr msg = error_500; 90 char *statusmsg = "Internal Server Error"; 91 switch(status) { 92 case 400: { 93 msg = error_400; 94 statusmsg = "Bad request"; 95 break; 96 } 97 case 500: { 98 msg = error_500; 99 statusmsg = "Internal Server Error"; 100 break; 101 } 102 case 503: { 103 msg = error_503; 104 statusmsg = "Service Unavailable"; 105 break; 106 } 107 } 108 109 char buf[512]; 110 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); 111 112 // set socket blocking 113 int flags; 114 if (-1 == (flags = fcntl(req->connection->fd, F_GETFL, 0))) { 115 flags = 0; 116 } 117 if (fcntl(req->connection->fd, F_SETFL, flags & ~O_NONBLOCK) != 0) { 118 // error 119 } 120 121 req->connection->write(req->connection, buf, len); 122 req->connection->write(req->connection, msg.ptr, msg.length); 123 } 124