static struct HTTPRequest *read_request(FILE *in) { struct HTTPRequest *req; struct HTTPHeaderField *h; req = xmalloc(sizeof(struct HTTPRequest)); read_request_line(req, in); req->header = NULL; while (h = read_header_field(in)) { h->next = req->header; req->header = h; } req->length = content_length(req); if (req->length != 0) { if (req->length > MAX_REQUEST_BODY_LENGTH) { log_exit("request body too long"); } req->body = xmalloc(req->length); if (fread(req->body, req->length, 1, in) < 1) { log_exit("failed to read request body"); } } else { req->body = NULL; } return req; }
bool SKKHttpDictionaryLoader::NeedsUpdate() { net::socket::tcpstream http(remote_); if(request(http)) { return download(http, content_length(http)); } return false; }
std::string generate_404_NOT_FOUND(std::vector<char> payload) { std::string response(HTTP_Code::_404); response += Content_Type::_text_plain; response += content_length(payload); response += header_delimiter; response.append(payload.data(), payload.size()); response += "\r\n"; return response; }
std::string generate_500_INTERNAL_SERVER_ERROR( std::vector<char> payload) { std::string response(HTTP_Code::_500); response += Content_Type::_text_plain; response += content_length(payload); response += header_delimiter; response.append(payload.data(), payload.size()); response += "\r\n"; return response; }
/*************************** read_request リクエストのread ***************************/ HttpRequest* read_request( FILE *in ) { HttpRequest *req; HttpHeaderField *h; int ret = 0; req = xmalloc(sizeof(HttpRequest)); read_request_line(req, in); req->header = NULL; while(NULL != (h = read_header_field(in))) { h->next = req->header; req->header = h; } req->length = content_length(req); if(req->length != 0) { if(req->length != MAX_REQUEST_BODY_LENGTH) { log_exit("request body too long"); } req->body = xmalloc(req->length); ret = fread(req->body, req->length, 1, in); if(ret < 1) { log_exit("failed to read request body"); } else { req->body = NULL; } } return req; }
void process( redisContext *c ) { FCGX_Stream *in, *out, *err; FCGX_ParamArray envp; redisReply *r; json reason = { .type = STRING, .name = "reason", .str = NULL }; json* failureEls[1] = { &reason }; json success = { .type = OBJECT, .length = 0, .name = NULL, .objArr = NULL }; json failure = { .type = OBJECT, .length = 1, .name = NULL, .objArr = failureEls }; while ( FCGX_Accept( &in, &out, &err, &envp ) >= 0 ) { // Check method if ( check_method_post( out, envp ) ) continue; // Check user is logged in char sid[33]; char *user = session( c, envp, sid ); if ( !user ) { header( out, 401, NULL ); reason.str = "Not logged in."; json_out( out, &failure ); continue; } // Initialize reused variables reason.str = ""; // Get contentlength long len = content_length( envp ); // Get post params char *s; if ( !read_stream( &s, in, len ) ) { header( out, 400, NULL ); reason.str = "No parameters provided"; json_out( out, &failure ); continue; } // Parse POST params param *p; ssize_t num = convert_to_params( &p, s, "&", "=", -1 ); // Get parameters char *courses = NULL, *date = NULL, *start = NULL, *finish = NULL, *students = NULL, *idStr = NULL; for ( int i = 0; i < num; ++i ) { if ( !courses && !strcmp( p[i].name, "courses" ) ) { courses = p[i].value; } else if ( !date && !strcmp( p[i].name, "date" ) ) { date = p[i].value; } else if ( !start && !strcmp( p[i].name, "start" ) ) { start = p[i].value; } else if ( !finish && !strcmp( p[i].name, "finish" ) ) { finish = p[i].value; } else if ( !students && !strcmp( p[i].name, "students" ) ) { students = p[i].value; } else if ( !idStr && !strcmp( p[i].name, "id" ) ) { idStr = p[i].value; } } // Check all parameters entered if ( !courses || !date || !start || !finish || !students ) { header( out, 400, NULL ); reason.str = "All details must be entered."; json_out( out, &failure ); goto err; } // URL decode components inplace_url_decode( courses ); inplace_url_decode( date ); inplace_url_decode( start ); inplace_url_decode( finish ); inplace_url_decode( students ); // Get next tute id long long id = -1; if ( idStr ) { // Convert to long long id = strtol( idStr, NULL, 10 ); // Check user owns tute r = redisCommand( c, "SISMEMBER tute:tutor:%s %lld", user, id ); if ( r->type != REDIS_REPLY_INTEGER ) { header( out, 500, NULL ); reason.str = "DB Error."; json_out( out, &failure ); freeReplyObject( r ); goto err; } if ( r->type != 1 ) { header( out, 400, NULL ); reason.str = "Invalid ID."; json_out( out, &failure ); freeReplyObject( r ); goto err; } } else { r = redisCommand( c, "INCR tute:tute:counter" ); if ( r->type != REDIS_REPLY_INTEGER ) { header( out, 500, NULL ); reason.str = "Could not fetch tute counter."; json_out( out, &failure ); freeReplyObject( r ); goto err; } id = r->integer; freeReplyObject( r ); } // Save tute r = redisCommand( c, "HMSET tute:tute:%lld tutor %s date %s start %s finish %s", id, user, date, start, finish ); if ( r->type == REDIS_REPLY_ERROR ) { header( out, 500, NULL ); reason.str = "Could not save tute."; json_out( out, &failure ); freeReplyObject( r ); goto err; } freeReplyObject( r ); // Save id to tutor r = redisCommand( c, "SADD tute:tutor:%s %lld", user, id ); if ( r->type == REDIS_REPLY_ERROR ) { header( out, 500, NULL ); reason.str = "Could not save tute."; json_out( out, &failure ); freeReplyObject( r ); goto err; } freeReplyObject( r ); // Parse codes param *course; ssize_t numCourses = convert_to_params( &course, courses, ";", ":", -1 ); num = numCourses; while ( num-- ) { // convert to lower to_lower( course[num].name ); // Save each code to tute id r = redisCommand( c, "SADD tute:tute:%lld:courses %s", id, course[num].name ); if ( r->type == REDIS_REPLY_ERROR ) { header( out, 500, NULL ); reason.str = "Could not save tute."; json_out( out, &failure ); freeReplyObject( r ); goto courseErr; } freeReplyObject( r ); // Add tute id to each code r = redisCommand( c, "SADD tute:course:%s:tutes %lld", course[num].name, id ); if ( r->type == REDIS_REPLY_ERROR ) { header( out, 500, NULL ); reason.str = "Could not save tute."; json_out( out, &failure ); freeReplyObject( r ); goto courseErr; } freeReplyObject( r ); } // Parse students param *student; num = convert_to_params( &student, students, ";", ":", -1 ); while ( num-- ) { // Add each student to tute r = redisCommand( c, "SADD tute:tute:%lld:students %s", id, student[num].name ); if ( r->type == REDIS_REPLY_ERROR ) { header( out, 500, NULL ); reason.str = "Could not save tute."; json_out( out, &failure ); freeReplyObject( r ); goto studentErr; } freeReplyObject( r ); // Save student data param *data; ssize_t fields = convert_to_params( &data, student[num].value, ",", "|", -1 ); if ( fields ) { char *college = NULL, *first = NULL, *last = NULL; while ( fields-- ) { if ( !college && !strcmp( data[fields].name, "college" ) ) { college = data[fields].value; } else if ( !first && !strcmp( data[fields].name, "first" ) ) { first = data[fields].value; } else if ( !last && !strcmp( data[fields].name, "last" ) ) { last = data[fields].value; } } if ( college && first && last ) { r = redisCommand( c, "HMSET tute:student:%s college %s first %s last %s", student[num].name, college, first, last ); if ( r->type == REDIS_REPLY_ERROR ) { header( out, 500, NULL ); reason.str = "Could not save tute."; json_out( out, &failure ); freeReplyObject( r ); free( data ); goto studentErr; } freeReplyObject( r ); } free( data ); } // Add tute id to each student r = redisCommand( c, "SADD tute:attendee:%s %lld", student[num].name, id ); if ( r->type == REDIS_REPLY_ERROR ) { header( out, 500, NULL ); reason.str = "Could not save tute."; json_out( out, &failure ); freeReplyObject( r ); goto studentErr; } freeReplyObject( r ); // Add student to each course ssize_t n = numCourses; while ( n-- ) { r = redisCommand( c, "SADD tute:course:%s:students %s", course[n].name, student[num].name ); if ( r->type == REDIS_REPLY_ERROR ) { header( out, 500, NULL ); reason.str = "Could not save tute."; json_out( out, &failure ); freeReplyObject( r ); goto studentErr; } freeReplyObject( r ); } } // Output success header( out, 200, sid ); json_out( out, &success ); studentErr: free( student ); // free params structure courseErr: free( course ); err: free( user ); free( p ); // Free params structure free( s ); // Free POST stream } } int main ( int argc, char *argv[] ) { return init( &process ); }
int body_length() const { return content_length() + padding_length(); }
/* * @brief: 根据解析下来的going_http_header_t来处理客户的请求. * @param phttpdr: 指向要处理的going_http_header_t; out: 保存处理的结果,http响应包. * @return: http status code. * * 目前支持的请求首部: * 目前支持的响应首部: */ int going_do_http_header(going_http_header_t *phttphdr, string& out) { char status_line[256] = {0}; string crlf("\r\n"); string server("Server: Gogoing\r\n"); string Public("Public: GET, HEAD\r\n"); string content_base = "Content-base: " + going_domain + crlf; string date = "Date: " + going_time_get() + crlf; string content_length("Content-Length: "); string content_location("Content-Location: "); string last_modify("Last-Modify: "); if(phttphdr == NULL){ snprintf(status_line, sizeof(status_line), "HTTP/1.1 %d %s\r\n", GOING_HTTP_BAD_REQUEST, going_get_state_by_codes(GOING_HTTP_BAD_REQUEST)); out = status_line + crlf; return GOING_HTTP_BAD_REQUEST; } string method = phttphdr->method; string real_url = going_make_url(phttphdr->url); string version = phttphdr->version; if(method == "GET" || method == "HEAD"){ if(going_is_file_existed(real_url.c_str()) == -1){ snprintf(status_line, sizeof(status_line), "HTTP/1.1 %d %s\r\n", GOING_HTTP_NOT_FOUND, going_get_state_by_codes(GOING_HTTP_NOT_FOUND)); out += status_line; return GOING_HTTP_NOT_FOUND; }else{ int len = going_get_file_length(real_url.c_str()); snprintf(status_line, sizeof(status_line), "HTTP/1.1 %d %s\r\n", GOING_HTTP_OK, going_get_state_by_codes(GOING_HTTP_OK)); out += status_line; snprintf(status_line, sizeof(status_line), "%d\r\n", len); out += content_length + status_line; out += server + content_base + date; out += last_modify + going_get_file_modified_time(real_url.c_str()) + crlf + crlf; } } else if(method == "PUT"){ snprintf(status_line, sizeof(status_line), "HTTP/1.1 %d %s\r\n", GOING_HTTP_NOT_IMPLEMENTED, going_get_state_by_codes(GOING_HTTP_NOT_IMPLEMENTED)); out += status_line + server + Public + date + crlf; return GOING_HTTP_NOT_IMPLEMENTED; } else if(method == "DELETE"){ snprintf(status_line, sizeof(status_line), "HTTP/1.1 %d %s\r\n", GOING_HTTP_NOT_IMPLEMENTED, going_get_state_by_codes(GOING_HTTP_NOT_IMPLEMENTED)); out += status_line + server + Public + date + crlf; return GOING_HTTP_NOT_IMPLEMENTED; }else if(method == "POST"){ snprintf(status_line, sizeof(status_line), "HTTP/1.1 %d %s\r\n", GOING_HTTP_NOT_IMPLEMENTED, going_get_state_by_codes(GOING_HTTP_NOT_IMPLEMENTED)); out += status_line + server + Public + date + crlf; return GOING_HTTP_NOT_IMPLEMENTED; }else{ snprintf(status_line, sizeof(status_line), "HTTP/1.1 %d %s\r\n", GOING_HTTP_BAD_REQUEST, going_get_state_by_codes(GOING_HTTP_BAD_REQUEST)); out = status_line + crlf; return GOING_HTTP_BAD_REQUEST; } return GOING_HTTP_OK; }