My task is to implement simple HTTP server. I should support chunked transfer encoding when I send response. Here is my function that send response to client.
static int serve_request(int sock, struct conf_arg *arg, char version[])
{
FILE *html = NULL;
char buf[MAX_MSG];
strcat(arg->root, arg->defdoc);
html = fopen(arg->root, "r");
if (!html) {
not_found(sock, version);
return 0;
}
good_responce(sock, version);
do {
fgets(buf, sizeof(buf), html);
const unsigned chunk = CHUNK_SIZE;
char *pbuf = buf;
char tempbuf[chunk + 10];
while (strlen(pbuf) >= chunk) {
sprintf(tempbuf, "%x\r\n", chunk);
write(sock, tempbuf, strlen(tempbuf));
write(sock, pbuf, chunk);
pbuf += chunk;
strcpy(tempbuf, "\r\n");
write(sock, tempbuf, strlen(tempbuf));
}
if (strlen(pbuf) == 0) {
sprintf(tempbuf, "%x\r\n", 0);
write(sock, tempbuf, strlen(tempbuf));
}
if (strlen(pbuf) > 0) {
sprintf(tempbuf, "%x\r\n", (unsigned)strlen(pbuf));
write(sock, tempbuf, strlen(tempbuf));
write(sock, pbuf, strlen(pbuf));
sprintf(tempbuf, "%x\r\n", 0);
write(sock, tempbuf, strlen(tempbuf));
}
strcpy(tempbuf, "\r\n");
write(sock, tempbuf, strlen(tempbuf));
} while (!feof(html));
fclose(html);
return 0;
}
CHUNK_SIZE is defined as 1024 because I want to sent chunks with 1KB size. The problem occurs when I open page enter image description here
The page is not displayed properly.
Also I set Transfer-Encoding: chunked
strcpy(buf, ENCODING);
send(sock, buf, strlen(buf), 0);
ENCODING is defined as "Transfer-Encoding: chunked\r\n"
I think I know where the problem is, but am not entirely sure.
In your
doloop, you get abuffull of data and you send that. Then you get another buffer full of data and send that. But after having sent each buffer of data, you terminate the transfer by sending a0\r\n. For example:Although it may be better to fill your buffer again before sending the last chunk (use
memmoveto move the last part down, then callfgetsto fill the remainder), you may be "saved" by sending the0\r\nonly after thedo ... whileloop, e.g.:Note also that you must check the result of
fgetsas it can return zero upon eof; the buffer will not have been refreshed and you will send the last part again:See also the comments about your unnecessary use of
tempbuf.