📄 response.c
字号:
/*============================================================================= response=============================================================================== This module contains callbacks from and services for a request handler. Copyright information is at the end of the file=============================================================================*/#include <ctype.h>#include <assert.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <errno.h>#include <time.h>#include "xmlrpc_config.h"#include "mallocvar.h"#include "xmlrpc-c/string_int.h"#include "xmlrpc-c/abyss.h"#include "server.h"#include "session.h"#include "conn.h"#include "token.h"#include "date.h"#include "data.h"#include "abyss_info.h"#include "http.h"voidResponseError(TSession * const sessionP) { const char * const reason = HTTPReasonByStatus(sessionP->status); const char * errorDocument; ResponseAddField(sessionP, "Content-type", "text/html"); ResponseWriteStart(sessionP); xmlrpc_asprintf(&errorDocument, "<HTML><HEAD><TITLE>Error %d</TITLE></HEAD>" "<BODY><H1>Error %d</H1><P>%s</P>" SERVER_HTML_INFO "</BODY></HTML>", sessionP->status, sessionP->status, reason); ConnWrite(sessionP->conn, errorDocument, strlen(errorDocument)); xmlrpc_strfree(errorDocument);}abyss_boolResponseChunked(TSession * const sessionP) { /* This is only a hope, things will be real only after a call of ResponseWriteStart() */ assert(!sessionP->responseStarted); sessionP->chunkedwrite = (sessionP->version.major > 1) || (sessionP->version.major == 1 && (sessionP->version.minor >= 1)); sessionP->chunkedwritemode = TRUE; return TRUE;}voidResponseStatus(TSession * const sessionP, uint16_t const code) { sessionP->status = code;}uint16_tResponseStatusFromErrno(int const errnoArg) { uint16_t code; switch (errnoArg) { case EACCES: code=403; break; case ENOENT: code=404; break; default: code=500; } return code;}voidResponseStatusErrno(TSession * const sessionP) { ResponseStatus(sessionP, ResponseStatusFromErrno(errno));}abyss_boolResponseAddField(TSession * const sessionP, const char * const name, const char * const value) { return TableAdd(&sessionP->response_headers, name, value);}static voidaddDateHeader(TSession * const sessionP) { char dateValue[64]; abyss_bool validDate; validDate = DateToString(&sessionP->date, dateValue); if (sessionP->status >= 200 && validDate) ResponseAddField(sessionP, "Date", dateValue);}voidResponseWriteStart(TSession * const sessionP) { struct _TServer * const srvP = ConnServer(sessionP->conn)->srvP; unsigned int i; assert(!sessionP->responseStarted); if (sessionP->status == 0) { // Handler hasn't set status. That's an error sessionP->status = 500; } sessionP->responseStarted = TRUE; { const char * const reason = HTTPReasonByStatus(sessionP->status); const char * line; xmlrpc_asprintf(&line,"HTTP/1.1 %u %s\r\n", sessionP->status, reason); ConnWrite(sessionP->conn, line, strlen(line)); xmlrpc_strfree(line); } if (HTTPKeepalive(sessionP)) { const char * keepaliveValue; ResponseAddField(sessionP, "Connection", "Keep-Alive"); xmlrpc_asprintf(&keepaliveValue, "timeout=%u, max=%u", srvP->keepalivetimeout, srvP->keepalivemaxconn); ResponseAddField(sessionP, "Keep-Alive", keepaliveValue); xmlrpc_strfree(keepaliveValue); } else ResponseAddField(sessionP, "Connection", "close"); if (sessionP->chunkedwrite && sessionP->chunkedwritemode) ResponseAddField(sessionP, "Transfer-Encoding", "chunked"); addDateHeader(sessionP); /* Generation of the server field */ if (srvP->advertise) ResponseAddField(sessionP, "Server", SERVER_HVERSION); /* send all the fields */ for (i = 0; i < sessionP->response_headers.size; ++i) { TTableItem * const ti = &sessionP->response_headers.item[i]; const char * line; xmlrpc_asprintf(&line, "%s: %s\r\n", ti->name, ti->value); ConnWrite(sessionP->conn, line, strlen(line)); xmlrpc_strfree(line); } ConnWrite(sessionP->conn, "\r\n", 2); }abyss_boolResponseWriteBody(TSession * const sessionP, const char * const data, uint32_t const len) { return HTTPWriteBodyChunk(sessionP, data, len);}abyss_boolResponseWriteEnd(TSession * const sessionP) { return HTTPWriteEndChunk(sessionP);}abyss_boolResponseContentType(TSession * const serverP, const char * const type) { return ResponseAddField(serverP, "Content-type", type);}abyss_boolResponseContentLength(TSession * const sessionP, uint64_t const len) { char contentLengthValue[32]; sprintf(contentLengthValue, "%llu", len); return ResponseAddField(sessionP, "Content-length", contentLengthValue);}/*********************************************************************** MIMEType*********************************************************************/struct MIMEType { TList typeList; TList extList; TPool pool;};static MIMEType * globalMimeTypeP = NULL;MIMEType *MIMETypeCreate(void) { MIMEType * MIMETypeP; MALLOCVAR(MIMETypeP); if (MIMETypeP) { ListInit(&MIMETypeP->typeList); ListInit(&MIMETypeP->extList); PoolCreate(&MIMETypeP->pool, 1024); } return MIMETypeP;}voidMIMETypeDestroy(MIMEType * const MIMETypeP) { PoolFree(&MIMETypeP->pool);}voidMIMETypeInit(void) { if (globalMimeTypeP != NULL) abort(); globalMimeTypeP = MIMETypeCreate();}voidMIMETypeTerm(void) { if (globalMimeTypeP == NULL) abort(); MIMETypeDestroy(globalMimeTypeP); globalMimeTypeP = NULL;}static voidmimeTypeAdd(MIMEType * const MIMETypeP, const char * const type, const char * const ext, abyss_bool * const successP) { uint16_t index; void * mimeTypesItem; abyss_bool typeIsInList; assert(MIMETypeP != NULL); typeIsInList = ListFindString(&MIMETypeP->typeList, type, &index); if (typeIsInList) mimeTypesItem = MIMETypeP->typeList.item[index]; else mimeTypesItem = (void*)PoolStrdup(&MIMETypeP->pool, type); if (mimeTypesItem) { abyss_bool extIsInList; extIsInList = ListFindString(&MIMETypeP->extList, ext, &index); if (extIsInList) { MIMETypeP->typeList.item[index] = mimeTypesItem; *successP = TRUE; } else { void * extItem = (void*)PoolStrdup(&MIMETypeP->pool, ext); if (extItem) { abyss_bool addedToMimeTypes; addedToMimeTypes = ListAdd(&MIMETypeP->typeList, mimeTypesItem); if (addedToMimeTypes) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -