/** Respond to an HTTP \a request with a redirect. * * \param request * \param url The URL to which the user is redirected. * \param permanent Whether the redirect is permanent. */ QDjangoHttpResponse *QDjangoHttpController::serveRedirect(const QDjangoHttpRequest &request, const QUrl &url, bool permanent) { const QString urlString = url.toString(); QDjangoHttpResponse *response = serveError(request, permanent ? QDjangoHttpResponse::MovedPermanently : QDjangoHttpResponse::Found, QString("You are being redirect to <a href=\"%1\">%2</a>").arg(urlString, urlString)); response->setHeader("Location", urlString.toUtf8()); return response; }
/** * parseRequest : parses the given http request and generates the * appropriate response * args: buffer: incoming http request responseBuffer: buffer to fill the response * return: none */ void parseRequest(char *buffer, bufStruct *response,char *rootDirPath) { int size = 0; int uriLength = 0; int httpLength = 0; char methodName[MAX_BUF_SIZE + 1]; char uri[MAX_BUF_SIZE + 1]; char httpVersion[MAX_BUF_SIZE + 1]; char ch; FILE *fp = NULL; int method = -1; char resourcePath[MAX_PATH] = ""; char finalURI[MAX_PATH]=""; while((size < MAX_BUF_SIZE ) && ( (ch = buffer[size]) != ' ')) { methodName[size] = ch; size++; } methodName[size] = '\0'; //check Get method response->entitySize = 0; if((method = checkMethod(methodName)) == FAILURE) { serveError(501,response,FAILURE); return; } /*increment size to skip space delimiter*/ size++; /*check uri*/ while((size < MAX_BUF_SIZE) && ((ch = buffer[size]) != ' ')) { uri[uriLength] = ch; uriLength++; size++; } uri[uriLength] = '\0'; getFinalURI(uri,finalURI); strcpy(resourcePath,rootDirPath); strcat(resourcePath,finalURI); //Check resource path: int fileError = checkFile(resourcePath); if(fileError != SUCCESS) { serveError(fileError,response,method); return; } //finding resource if((fp = openFile(resourcePath)) == NULL ) { serveError(404,response,method); return; } /*increment size to skip space delimiter*/ size++; while((size < MAX_BUF_SIZE ) && ( (ch = buffer[size]) != '\r')) { httpVersion[httpLength] = ch; httpLength++; size++; } httpVersion[httpLength] = '\0'; if(checkHttpVersion(httpVersion) == -1) { serveError(505,response,method); return; } /*increment the size and check for '\n' */ int returnVal = checkHeader(buffer,size); if(returnVal == FAILURE) { serveError(400,response,method); return; } /*Parse header if needed*/ /*file return*/ if(method == GET) { serveGet(response,fp,resourcePath); return; } else if( method == HEAD) { serveHead(response,fp,resourcePath); return; } else { /*Control never reaches here*/ exit(FAILURE); } }
/** Respond to a malformed HTTP request. * * \param request */ QDjangoHttpResponse *QDjangoHttpController::serveBadRequest(const QDjangoHttpRequest &request) { return serveError(request, QDjangoHttpResponse::BadRequest, "Your browser sent a malformed request."); }
/** Respond to an HTTP \a request with a not found error. * * \param request */ QDjangoHttpResponse *QDjangoHttpController::serveNotFound(const QDjangoHttpRequest &request) { return serveError(request, QDjangoHttpResponse::NotFound, "The document you requested was not found."); }
/** Respond to an HTTP \a request with an internal server error. * * \param request */ QDjangoHttpResponse *QDjangoHttpController::serveInternalServerError(const QDjangoHttpRequest &request) { return serveError(request, QDjangoHttpResponse::InternalServerError, "An internal server error was encountered."); }
/** *newClientThread : Services the client's request. *args: client connection socket file descriptor. * *return: NULL */ void *newClientThread(void *vargp) { pthread_detach(pthread_self()); int client_sock = *((int*) vargp); free(vargp); bool connLimitFlag = false; pthread_mutex_lock(&connMutex); if(globalConnectionCount<CONNECTION_LIMIT) { globalConnectionCount++; } else { connLimitFlag=true; } pthread_mutex_unlock(&connMutex); int bytes_received, bytes_sent, total_sent; char buffer[MAX_LINE]; int ret = 0; total_sent = bytes_received = bytes_sent = 0; /* Read the date sent from the client */ if(!connLimitFlag) { while((( ret= recv(client_sock,(buffer + bytes_received), MAX_LINE - 1, 0)) > 0) && (bytes_received < MAX_BUF_SIZE)) { bytes_received += ret; if(strncmp((buffer+ (bytes_received -4)),"\r\n\r\n",4) == 0) { break; } } /* * Echo - Write (send) the data back to the client taking care of short * counts */ if (bytes_received > 0) { buffer[bytes_received] = '\0'; bufStruct response; response.buffer = (char *) malloc(sizeof(char)*(MAX_BUF_SIZE + 1)); response.bufSize = 0; response.entitySize=0; parseRequest(buffer,&response,path); while (total_sent != response.bufSize) { bytes_sent = send(client_sock, response.buffer + total_sent, response.bufSize - total_sent, 0); if (bytes_sent <= 0) { break; } else { total_sent += bytes_sent; } } //reset for file transfer total_sent = 0; //Send file if applicable while (total_sent != response.entitySize) { bytes_sent = send(client_sock, response.entityBuffer + total_sent, response.entitySize - total_sent, 0); if (bytes_sent <= 0) { break; } else { total_sent += bytes_sent; } } if(response.entitySize !=0) { free(response.entityBuffer); } free(response.buffer); } } else { //Send 503- Service Unavailable. bufStruct response; response.buffer = (char *) malloc(sizeof(char)*(MAX_BUF_SIZE + 1)); response.bufSize = 0; response.entitySize=0; serveError(503,&response,FAILURE); while (total_sent != response.bufSize) { bytes_sent = send(client_sock, response.buffer + total_sent, response.bufSize - total_sent, 0); if (bytes_sent <= 0) { break; } else { total_sent += bytes_sent; } } if(response.entitySize !=0) { free(response.entityBuffer); } free(response.buffer); } debug_log("Closing connection %s:%d", client_addr_string, ntohs(client_addr.sin_port)); /* Our work here is done. Close the connection to the client */ close(client_sock); pthread_mutex_lock(&connMutex); if(globalConnectionCount>0) { globalConnectionCount--; } pthread_mutex_unlock(&connMutex); return NULL; }