void hio_response_http_send_headers(HioResponseHttp *http) { /* FIXME send actual headers */ g_mutex_lock(http->headers_lock); /* Sending headers twice is allowed, for example request handlers * can do it early, but a container might do it automatically * after the request handler runs. Only first send does anything * of course and it's an error to try to set headers after we * already sent them. */ if (http->headers_sent) { g_mutex_unlock(http->headers_lock); return; } http->headers_sent = TRUE; write_to_header(http, "HTTP/1.1 200 OK\r\n"); write_to_header(http, "Date: Wed, 21 Jul 2010 02:24:36 GMT\r\n"); write_to_header(http, "Server: hrt/" VERSION "\r\n"); write_to_header(http, "Last-Modified: Tue, 01 Dec 2009 23:10:05 GMT\r\n"); write_to_header(http, "Content-Type: text/html\r\n"); write_to_header(http, "Connection: close\r\n"); write_to_header(http, "\r\n"); hio_output_stream_close(http->header_stream); g_mutex_unlock(http->headers_lock); }
void read_request ( struct process* process ) { int sock = process->sock, s; char* buf=process->buf; char read_complete = 0; ssize_t count; while ( 1 ) { count = read ( sock, buf + process->read_pos, BUF_SIZE - process->read_pos ); if ( count == -1 ) { if ( errno != EAGAIN ) { handle_error ( process, "read request" ); return; } else { //errno == EAGAIN表示读取完毕 break; } } else if ( count == 0 ) { // 被客户端关闭连接 cleanup ( process ); return; } else if ( count > 0 ) { process->read_pos += count; } } int header_length = process->read_pos; // determine whether the request is complete if ( header_length > BUF_SIZE - 1 ) { process->response_code = 400; process->status = STATUS_SEND_RESPONSE_HEADER; strcpy ( process->buf, header_400 ); send_response_header ( process ); handle_error ( processes, "bad request" ); return; } buf[header_length]=0; read_complete = ( strstr ( buf, "\n\n" ) != 0 ) || ( strstr ( buf, "\r\n\r\n" ) != 0 ); int error = 0; if ( read_complete ) { //重置读取位置 reset_process ( process ); // get GET info if ( !strncmp ( buf, "GET", 3 ) == 0 ) { process->response_code = 400; process->status = STATUS_SEND_RESPONSE_HEADER; strcpy ( process->buf, header_400 ); send_response_header ( process ); handle_error ( processes, "bad request" ); return; } // get first line int n_loc = ( int ) strchr ( buf, '\n' ); int space_loc = ( int ) strchr ( buf + 4, ' ' ); if ( n_loc <= space_loc ) { process->response_code = 400; process->status = STATUS_SEND_RESPONSE_HEADER; strcpy ( process->buf, header_400 ); send_response_header ( process ); handle_error ( processes, "bad request" ); return; } char path[255]; int len = space_loc - ( int ) buf - 4; if ( len > MAX_URL_LENGTH ) { process->response_code = 400; process->status = STATUS_SEND_RESPONSE_HEADER; strcpy ( process->buf, header_400 ); send_response_header ( process ); handle_error ( processes, "bad request" ); return; } buf[header_length] = 0; strncpy ( path, buf+4, len ); path[len] = 0; struct stat filestat; char fullname[256]; char *prefix = doc_root; strcpy ( fullname, prefix ); strcpy ( fullname + strlen ( prefix ), path ); s = get_index_file ( fullname, &filestat); if ( s == -1 ) { process->response_code = 404; process->status = STATUS_SEND_RESPONSE_HEADER; strcpy ( process->buf, header_404 ); send_response_header ( process ); handle_error ( processes, "not found" ); return; } int fd = open ( fullname, O_RDONLY ); process->fd = fd; if ( fd<0 ) { process->response_code = 404; process->status = STATUS_SEND_RESPONSE_HEADER; strcpy ( process->buf, header_404 ); send_response_header ( process ); handle_error ( processes, "not found" ); return; } else { process->response_code = 200; } char tempstring[256]; //检查有无If-Modified-Since,返回304 char* c = strstr ( buf, HEADER_IF_MODIFIED_SINCE ); if(c!=0){ char* rn = strchr(c, '\r'); if(rn==0){ rn = strchr(c, '\n'); if(rn==0){ process->response_code = 400; process->status = STATUS_SEND_RESPONSE_HEADER; strcpy ( process->buf, header_400 ); send_response_header ( process ); handle_error ( processes, "bad request" ); return; } } int time_len = rn - c - sizeof(HEADER_IF_MODIFIED_SINCE) + 1; strncpy(tempstring, c + sizeof(HEADER_IF_MODIFIED_SINCE) - 1,time_len); tempstring[time_len]=0; { struct tm tm; time_t t; strptime(tempstring, RFC1123_DATE_FMT, &tm); tzset(); t=mktime(&tm); t-=timezone; gmtime_r(&t, &tm); if(t >= filestat.st_mtime){ process->response_code = 304; } } } //开始header process->buf[0] = 0; if(process->response_code == 304){ write_to_header ( header_304_start ); } else { write_to_header ( header_200_start ); } process->total_length = filestat.st_size; { //写入当前时间 struct tm *tm; time_t tmt; tmt = time ( NULL ); tm = gmtime ( &tmt ); strftime ( tempstring, sizeof ( tempstring ), RFC1123_DATE_FMT, tm ); write_to_header ( "Date: " ); write_to_header ( tempstring ); write_to_header ( "\r\n" ); //写入文件修改时间 tm = gmtime ( &filestat.st_mtime ); strftime ( tempstring, sizeof ( tempstring ), RFC1123_DATE_FMT, tm ); write_to_header ( "Last-modified: " ); write_to_header ( tempstring ); write_to_header ( "\r\n" ); if(process->response_code == 200){ //写入content长度 sprintf ( tempstring, "Content-Length: %ld\r\n", filestat.st_size ); write_to_header ( tempstring ); } } //结束header write_to_header ( header_end ); process->status = STATUS_SEND_RESPONSE_HEADER; //修改此sock的监听状态,改为监视写状态 event.data.fd = process->sock; event.events = EPOLLOUT | EPOLLET; s = epoll_ctl ( efd, EPOLL_CTL_MOD, process->sock, &event ); if ( s == -1 ) { perror ( "epoll_ctl" ); abort (); } //发送header send_response_header ( process ); } }