• FuckBigTech347@lemmygrad.ml
    link
    fedilink
    arrow-up
    4
    ·
    13 days ago

    I don’t even want to think about how much time and electricity is getting wasted each day because of all these massively bloated websites and webapps. Modern computers are insanely fast, yet webapps sometimes take more than 10 seconds to start up on a good day.

    Personally I like my WebApps in C89
    /* app.c */
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    #include <netinet/in.h>
    #include <sys/socket.h>
    #ifdef __linux__
    #include <linux/net.h> /* For SO_REUSEPORT */
    #endif
    
    #define LISTEN_PORT 9000
    
    #define REQUEST_TYPE_UNKNOWN 0
    #define REQUEST_TYPE_GET 1
    
    static const char *html_main = (
        "<!DOCTYPE html>"
        "<html>"
        "<header>"
        "<title>My first Web App</title>"
        "</header>"
        "<body>"
        "<h1>Hello World</h1>"
        "</body>"
        "</html>"
    );
    
    static size_t html_main_length;
    
    static void http_reply(int cl_sock_fd,
                           const uint16_t status,
                           const char *status_msg,
                           const char *mimetype,
                           const size_t content_length)
    {
        char buffer[0x400];
        int length;
        
        length = sprintf(
            buffer,
            "HTTP/1.1 %u %s\r\n"
            "Content-Type: %s\r\n"
            "Content-Length: %lu\r\n"
            "\r\n",
            status,
            status_msg,
            mimetype,
            content_length
        );
    
        write(cl_sock_fd, buffer, length);
    }
    
    int main(void)
    {
        int32_t sv_sock_fd, cl_sock_fd;
        struct sockaddr_in sv_addr, cl_addr;
        socklen_t cl_addr_size;
        uint32_t option;
        char *input_buffer;
        size_t input_length, input_buffer_length;
        uint8_t request_type;
        
        memset(&sv_addr, 0, sizeof(sv_addr));
        sv_addr.sin_family = AF_INET;
        sv_addr.sin_addr.s_addr = INADDR_ANY;
        sv_addr.sin_port = htons(LISTEN_PORT);
        sv_sock_fd = socket(sv_addr.sin_family, SOCK_STREAM, 0);
        
        if (sv_sock_fd == -1)
        {
            perror("Unable to create server socket");
            return EXIT_FAILURE;
        }
        
        /* Tell it to re-use the address and port... */
        option = 1;
        
        if (setsockopt(sv_sock_fd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option)))
        {
            close(sv_sock_fd);
            perror("Unable to setsockopt on socket");
            return EXIT_FAILURE;
        }
        
        if (setsockopt(sv_sock_fd, SOL_SOCKET, SO_REUSEPORT, &option, sizeof(option)))
        {
            close(sv_sock_fd);
            perror("Unable to setsockopt on socket");
            return EXIT_FAILURE;
        }
        
        if (bind(sv_sock_fd, (struct sockaddr *)&sv_addr, sizeof(sv_addr)))
        {
            close(sv_sock_fd);
            perror("Unable to bind socket to address");
            return EXIT_FAILURE;
        }
    
        if (listen(sv_sock_fd, 0))
        {
            close(sv_sock_fd);
            perror("Unable to listen on socket");
            return EXIT_FAILURE;
        }
    
        input_buffer_length = 0x400;
        input_buffer = malloc(input_buffer_length);
    
        if (!input_buffer)
        {
            close(sv_sock_fd);
            perror("input_buffer == NULL");
            return EXIT_FAILURE;
        }
    
        html_main_length = strlen(html_main);
        cl_addr_size = sizeof(cl_addr);
        printf("Waiting for new connections on port %u ...\n", LISTEN_PORT);
        
        while (1)
        {
            cl_sock_fd = accept(sv_sock_fd, (struct sockaddr *)&cl_addr, &cl_addr_size);
    
            if (cl_sock_fd == -1)
            {
                perror("Error when accept()ing");
                break;
            }
            
            request_type = REQUEST_TYPE_UNKNOWN;
            input_length = 0;
            /* Read from the client */
            while (read(cl_sock_fd, input_buffer + input_length, 1) > 0)
            {
                if (input_length >= input_buffer_length)
                {
                    input_buffer_length += 0x400;
                    input_buffer = realloc(input_buffer, input_buffer_length);
    
                    if (!input_buffer)
                    {
                        close(sv_sock_fd);
                        close(cl_sock_fd);
                        perror("Failed to realloc() input_buffer");
                        return EXIT_FAILURE;
                    }
                }
                
                if (input_buffer[input_length] == ' ')
                {
                    if (request_type == REQUEST_TYPE_GET)
                    {
                        printf("GET request: %.*s\n", (int)input_length, input_buffer);
                        
                        if (strncmp(input_buffer, "/", input_length) == 0)
                        {
                            http_reply(cl_sock_fd, 200, "OK", "text/html; charset=UTF-8", html_main_length);
                            write(cl_sock_fd, html_main, html_main_length);
                            break;
                        }
                        
                        http_reply(cl_sock_fd, 404, "Not Found", "", 0);
                        break;
                    }
                    
                    if (strncmp(input_buffer, "GET", input_length) == 0)
                    {
                        request_type = REQUEST_TYPE_GET;
                        input_length = 0;
                        continue;
                    }
    
                    break;
                }
                
                ++input_length;
            }
            
            close(cl_sock_fd);
        }
        
        free(input_buffer);
        close(sv_sock_fd);
        return EXIT_SUCCESS;
    }
    

    To compile on a UNIX-like system: $ cc -o app app.c -std=c89 -Wall -Wextra