Home > database >  Browser doesn't send entire POST data to C socket server
Browser doesn't send entire POST data to C socket server

Time:12-14

I've got a simple C socket server listening at localhost:8080 that continuously reads from the client socket until it encounters quit at the end of the message.

I tested this on Chrome (Android) and Firefox (Android). I sent a POST request as follows:

<form
    action="http://localhost:8080"
    method="POST" >
    <input type="hidden" name="MAX_FILE_SIZE" value="100000"/>
    Choose a file to upload: <input name="uploadedfile" type="file"/><br/>
    <input type="submit" value="Upload File"/>
</form>

On the server side, I could only see that it recieved the request headers. No file data was recieved.

Req from Chrome:

POST / HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Content-Length: 52
Cache-Control: max-age=0
sec-ch-ua: "Not?A_Brand";v="8", "Chromium";v="108", "Google Chrome";v="108"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Linux"
Origin: http://localhost:5000
DNT: 1
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36
Accept: text/html,application/xhtml xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-site
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://localhost:5000/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8,bn;q=0.7

When I added enctype="multipart/form-data" to the above form's attribute though, the full data and file with multiple boundaries was recieved.

Afterwards I tried the following POST with and without multipart:

<form
    action="http://localhost:8080"
    method="POST" >
    <input name="test" value="foobar"/>
    <input type="submit" value="Submit"/>
</form>

Results were same, only headers were recieved with urlencoded data. Full data was sent with multipart.

My question is why this is happening, and does the browser expect a response in the first case before it continues sending further data?

My aim is to recieve the POST data at once. Is that not possible?

On a side note, I noticed that after the multipart POST request, the request didn't end with two CR LFs, instead just one.

Edit: Just noticed that when I reload the browser it closes the connection and atbthat moment the remaining POST data shows up (without any CR LF ending after the POST).

Serve code

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>

int main (int argc, char *argv[]) {
    int portno = argc == 2 ? atoi(argv[1]) : 8080;
    int srvfd = socket(AF_INET, SOCK_STREAM, 0);
    int option = 1;
    setsockopt(srvfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
    struct sockaddr_in serv_addr;
    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    serv_addr.sin_port = htons(portno);
    if (bind(srvfd, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) < 0) {
        perror("server: error binding");
        exit(1);
    }
    listen(srvfd, 1000);
    printf("server: listening at port %d\n\n", portno);
    struct sockaddr_in cli_addr;
    socklen_t clilen = sizeof(cli_addr);
    int clifd = accept(srvfd, (struct sockaddr*) &cli_addr, &clilen);
    while (true) {
        char buffer[256];
        int n = read(clifd, buffer, 255);
        if (n == 0) {
            fprintf(stderr, "server: error: connection closed\n");
            exit(1);
        } else if (n < 0) {
            perror("server: error reading from socket");
            exit(1);
        }
        buffer[n] = 0;
        printf("%s", buffer);
        if (!strncmp(buffer, "quit", 4))
            exit(0);
    }
    return 0;
}

CodePudding user response:

After printing some data, call fflush(stdout); to make sure it is not buffered.

There is not an extra CRLF after the end of the POST data. The server knows the end of the POST data because of the Content-Length header. Because the browser specifies Content-Length: 52 the server knows the POST data is exactly 52 bytes.

  • Related