static inline void handle(Server *server, int fd, fd_set *activeFDs, struct sockaddr_in *addr) { int nread; char buff[20480]; if ((nread = recv(fd, buff, sizeof(buff), 0)) < 0) { fprintf(stderr, "error: read failed\n"); } else if (nread > 0) { buff[nread] = '\0'; Request *req = requestNew(buff); if (!req) { send(fd, "HTTP/1.0 400 Bad Request\r\n\r\nBad Request", 39, 0); LOG_400(addr); } else { ListCell *handler = server->handlers; Response *response = NULL; while (handler && !response) { response = (*(HandlerP)handler->value)(req); handler = handler->next; } if (!response) { send(fd, "HTTP/1.0 404 Not Found\r\n\r\nNot Found!", 36, 0); LOG_REQUEST(addr, METHODS[req->method], req->path, 404); } else { LOG_REQUEST(addr, METHODS[req->method], req->path, response->status); responseWrite(response, fd); responseDel(response); } requestDel(req); } } close(fd); FD_CLR(fd, activeFDs); }
Request *requestNew(char *buff) { Request *request = malloc(sizeof(Request)); char *segment, *bs; request->method = UNKNOWN_METHOD; request->path = NULL; request->uri = NULL; request->queryString = NULL; request->postBody = NULL; request->headers = NULL; request->cookies = NULL; request->account = NULL; // METHOD TOK(buff, " \t"); if (strcmp(segment, "OPTIONS") == 0) request->method = OPTIONS; else if (strcmp(segment, "GET") == 0) request->method = GET; else if (strcmp(segment, "HEAD") == 0) request->method = HEAD; else if (strcmp(segment, "POST") == 0) request->method = POST; else if (strcmp(segment, "PUT") == 0) request->method = PUT; else if (strcmp(segment, "DELETE") == 0) request->method = DELETE; else if (strcmp(segment, "TRACE") == 0) request->method = TRACE; else if (strcmp(segment, "CONNECT") == 0) request->method = CONNECT; else goto fail; // PATH TOK(NULL, " \t"); request->path = bsNew(segment); request->uri = bsNew(segment); if (strchr(request->path, '#') != NULL) goto fail; // VERSION TOK(NULL, "\n"); if (strncmp(segment, "HTTP/1.0", 8) != 0 && strncmp(segment, "HTTP/1.1", 8) != 0) goto fail; // HEADERS request->headers = parseHeaders(segment); // BODY bs = kvFindList(request->headers, "Content-Type"); if (bs != NULL && strncmp(bs, "application/x-www-form-urlencoded", 33) == 0) { segment = strtok(NULL, "\0"); if (segment == NULL) goto fail; request->postBody = parseQS(segment); } // QUERYSTRING segment = strchr(request->path, '?'); if (segment != NULL) { request->uri = bsNewLen(request->path, segment - request->path); request->queryString = parseQS(segment + 1); if (request->queryString == NULL) goto fail; } // COOKIES segment = kvFindList(request->headers, "Cookie"); if (segment != NULL) { request->cookies = parseCookies(segment); if (request->cookies == NULL) goto fail; } return request; fail: requestDel(request); return NULL; }