I've been working on a project where I'm implementing an HTTP server in C, and I'm encountering an issue with rendering images in a web browser. Every time I try to access the image via the server, I receive the error message "the image cannot be displayed because it contains an error."
I've checked my code thoroughly, but I'm unable to pinpoint the exact problem. Could someone please guide me on what I might be doing wrong? Below is a simplified version of my code for serving images:
main.c
#include <stdio.h>
#include <sys/socket.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <unistd.h>
#include <stdlib.h>
#include <arpa/inet.h>
#define PORT "8080"
#define BUFFSIZE 2048
#include "filehandle.h"
#include "httpresponse.h"
char *get_file_path(const char *request) {
char *path = NULL;
char *start = strstr(request, "GET ");
if (start != NULL) {
start += 4; // Move past "GET "
char *end = strstr(start, " ");
if (end != NULL) {
int path_length = end - start;
path = (char *)malloc(path_length + 1);
strncpy(path, start, path_length);
path[path_length] = '\0';
}
}
return path;
};
char* requestpath(int sockfd)
{
char *buffer=(char *)malloc(BUFFSIZE);
int bytes = read(sockfd,buffer,BUFFSIZE);
return buffer;
};
int main(int argc, char *argv[])
{
int status;
struct addrinfo hints, *res;
int sockfd;
int bindstatus;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
status = getaddrinfo(NULL, PORT, &hints, &res);
if (status == -1)
{
fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
}
sockfd = socket(res->ai_family, res->ai_socktype, 0);
if (sockfd == -1)
{
fprintf(stderr, "socket error %s\n", strerror(sockfd));
}
int opt = 1;
setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(opt));
bindstatus = bind(sockfd, res->ai_addr, res->ai_addrlen);
if (bindstatus == -1)
{
fprintf(stderr, "bind error %s\n", strerror(bindstatus));
}
freeaddrinfo(res);
int l;
l = listen(sockfd, 10);
if (l != 0)
{
fprintf(stderr, "LISTEN ERROR %s\n", strerror(l));
}
while (1)
{
struct sockaddr_in client_addr;
int newfd;
socklen_t theiraddr = sizeof client_addr;
newfd = accept(sockfd,(struct sockaddr *)&client_addr, &theiraddr);
if (newfd == -1)
{
fprintf(stderr, "accept error %s\n", strerror(errno));
}
else{
char str[INET_ADDRSTRLEN];
inet_ntop(client_addr.sin_family,(struct inaddr *)&client_addr.sin_addr,str,INET_ADDRSTRLEN);
printf("connection from %s\n",str);
}
char *request = requestpath(newfd);
char *filepath = get_file_path(request);
printf("%s\n",filepath);
free(request);
char *response = NULL;
if(strcmp(filepath,"/") == 0 || strcmp(filepath,"/index.html") == 0){
response = content("index.html");
}
// else if(strcmp(filepath,"/image.jpg") == 0){
// FILE *fp = fopen("image.jpg","rb");
// int count = count_file_bytes(fp);
// char *content_two = (char*)malloc(sizeof(char)*count+1);
// }
else if(strcmp(filepath,"/image.jpg") == 0){
response = read_binary_file("image.jpg");
}
else
response = "404 Not Found";
printf("Response is %s\n",response);
int len, bytes_sent;
char *http_response = (char *) malloc(4000);
char *generated_http_response = generate_http_response();
char *date = get_date_for_server();
char *ext = get_file_ext(filepath,'.');
printf("filepath %s\n",filepath);
char *type = NULL;
if(ext != NULL){
type = get_type(ext);
}
else{
type = "text/html";
}
int n = snprintf(http_response,4000,generated_http_response,date,type,response);
len = strlen(http_response);
bytes_sent = send(newfd, http_response, len, 0);
free(date);
shutdown(newfd,SHUT_WR);
}
close(sockfd);
return 0;
}
filehandle.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// open the requested file and return the file pointer
FILE* requestfile(char *filename){
FILE *fp;
fp = fopen(filename,"r");
if(fp != NULL){
return fp;
}
else{
perror("Error opening file\n");
}
}
// count the byte size of file
int count_file_bytes(FILE *fp)
{
int c,count = 0;
if(fp != NULL){
while((c = fgetc(fp)) != EOF)
count++;
}
fclose(fp);
return count;
}
// read the file content to buffer and return
char* content(char *filename)
{
FILE *fp = requestfile(filename);
int bytecount = count_file_bytes(fp);
char *content = (char *) malloc(bytecount+1);
FILE *file = requestfile(filename);
size_t i;
for(i=0;i<(bytecount+1);++i)
{
int c = fgetc(file);
if( c == EOF)
{
break;
}
content[i]= c;
}
content[i] = '\0';
fclose(file);
return content;
}
// get file extension before last '.'
char *get_file_ext(char *filename, int c)
{
char *type = strrchr(filename,c);
return type;
}
// read the file in binary format
char *read_binary_file(char *filename)
{
FILE *fp = fopen(filename,"rb");
if(fp == NULL)
fprintf(stderr,"\t Error Opening file: %s\n",filename);
long image_size;
int c;
int count = 0;
fseek(fp,0,SEEK_END);
image_size = ftell(fp);
rewind(fp);
char *buffer = (char *)malloc(image_size);
fread(buffer,1,image_size,fp);
fclose(fp);
return buffer;
}
httpresponse.c
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define MAXSIZE 30
// get the date for http response
char* get_date_for_server()
{
time_t result = time(NULL);
char *date = (char *)malloc(MAXSIZE*sizeof(char));
if(result != (time_t)(-1)){
size_t t = strftime(date,MAXSIZE,"%a, %d %b %Y %T GMT",localtime(&result));
}
return date;
}
// generate http response
char *generate_http_response()
{
char *Header =
"HTTP/1.1 200 OK\r\n"
"Access-Control-Allow-Origin: *\r\n"
"Connection: Keep-Alive\r\n"
"Date: %s\r\n"
"Content-Type: %s\r\n"
// "Content-Length: %d\r\n"
"\n"
"%s";
return Header;
}
// return the file mime type
char *get_type(char *filepath)
{
char *type = NULL;
if(strcmp(filepath, ".jpg") == 0){
type = "image/jpg";
}
else {
type = "text/html";
}
return type;
}
here is the output of the browser

strlen(seelen = strlen(http_response);), you are not going to get all of it. Same problem withsprintf %s.image_size, use that.