this post was submitted on 22 Jan 2025
23 points (96.0% liked)

Programming

255 readers
5 users here now

Welcome to the Lemmygrad programming community! This is a space where programmers of all levels can discuss programming, ask for help with problems, and share their personal programming projects with others.


Rules

  1. Respect all users, regardless of their level of knowledge in programming. We're here to learn and help each other improve.
  2. Keep posts relevant to programming and related topics.
  3. Respect people's personal preferences. If you disagree with someone's choice of programming language, method of formatting code, or anything else, don't attack the poster. Genuine criticism is fine, but personal attacks are not.
  4. In order to promote breaks from typing, all code snippets must be photos of code written on paper.
    Just kidding :), please use proper markdown code blocks.

founded 2 years ago
MODERATORS
you are viewing a single comment's thread
view the rest of the comments
[–] [email protected] 4 points 4 weeks 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