mirror of
https://github.com/KevinMidboe/http-200.git
synced 2025-10-29 09:30:28 +00:00
Init commit
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
server
|
||||
11
Dockerfile
Normal file
11
Dockerfile
Normal file
@@ -0,0 +1,11 @@
|
||||
# Use the scratch base image
|
||||
FROM scratch
|
||||
|
||||
WORKDIR /app
|
||||
COPY server .
|
||||
|
||||
# Expose port 80
|
||||
EXPOSE 80
|
||||
|
||||
# Run the binary
|
||||
CMD ["/app/server"]
|
||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 Kevin Midbøe
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
41
Makefile
Normal file
41
Makefile
Normal file
@@ -0,0 +1,41 @@
|
||||
.PHONY: all docker-build run clean
|
||||
|
||||
# Variables for C compilation
|
||||
CC = gcc
|
||||
CFLAGS = -Os -fdata-sections -ffunction-sections -march=native -Wall -Wextra
|
||||
TARGET = server
|
||||
|
||||
# Variables for Docker Buildx
|
||||
IMAGE_NAME = kevinmidboe/http-200
|
||||
VERSION = latest
|
||||
PLATFORMS = linux/amd64,linux/arm64,linux/arm/v7
|
||||
DATE=$(shell date +%Y.%m.%d)
|
||||
|
||||
# Default rule to compile the C program and build Docker image
|
||||
all: $(TARGET)
|
||||
|
||||
run:
|
||||
./server
|
||||
|
||||
# Rule to compile the C executable
|
||||
$(TARGET): server.c
|
||||
$(CC) $(CFLAGS) -o $(TARGET) server.c
|
||||
|
||||
# Docker Buildx setup
|
||||
docker-setup: $(TARGET)
|
||||
docker buildx create --use --name multiarch_builder || true
|
||||
docker buildx inspect --bootstrap
|
||||
|
||||
# Build multi-platform Docker image without pushing to registry
|
||||
docker-build: docker-setup
|
||||
docker buildx build --platform $(PLATFORMS) -t $(IMAGE_NAME):$(VERSION) -t $(IMAGE_NAME):$(DATE) .
|
||||
|
||||
# Build multi-platform Docker image and push to registry
|
||||
docker-publish: docker-setup
|
||||
docker buildx build --platform $(PLATFORMS) -t $(IMAGE_NAME):$(VERSION) -t $(IMAGE_NAME):$(DATE) --push .
|
||||
|
||||
# Clean up Buildx builder and compiled binary
|
||||
clean:
|
||||
rm -f $(TARGET)
|
||||
docker buildx rm multiarch_builder || true
|
||||
|
||||
41
README.md
Normal file
41
README.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# http-200
|
||||
|
||||
Simple http C server that always responds 200 to all http requests. Resulting in docker image size smaller than 40 kB (or 3 kB compressed).
|
||||
|
||||
## build
|
||||
|
||||
```bash
|
||||
gcc -o server server.c
|
||||
```
|
||||
|
||||
or using make
|
||||
|
||||
```bash
|
||||
make
|
||||
```
|
||||
|
||||
## run
|
||||
|
||||
```bash
|
||||
./server
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```bash
|
||||
make run
|
||||
```
|
||||
|
||||
## docker
|
||||
|
||||
build using docker with
|
||||
|
||||
```bash
|
||||
docker build -t http-200 .
|
||||
```
|
||||
|
||||
publish (multi-arch) using
|
||||
|
||||
```bash
|
||||
make docker-publish
|
||||
```
|
||||
91
server.c
Normal file
91
server.c
Normal file
@@ -0,0 +1,91 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <arpa/inet.h> // For inet_ntop
|
||||
|
||||
int server_fd;
|
||||
|
||||
void handle_signal(int signal) {
|
||||
printf("\nReceived signal %d, shutting down server...\n", signal);
|
||||
fflush(stdout); // Ensure output is flushed immediately
|
||||
if (server_fd >= 0) {
|
||||
close(server_fd);
|
||||
}
|
||||
exit(0); // Graceful exit after closing the socket
|
||||
}
|
||||
|
||||
int main() {
|
||||
struct sockaddr_in address;
|
||||
struct sockaddr_in client_address;
|
||||
int client_fd;
|
||||
int addrlen = sizeof(address);
|
||||
int port = 80;
|
||||
|
||||
// Disable stdout buffering
|
||||
setbuf(stdout, NULL); // Disables buffering, output is immediate
|
||||
|
||||
// Setup signal handler for graceful shutdown
|
||||
struct sigaction sa;
|
||||
sa.sa_handler = handle_signal;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = 0;
|
||||
sigaction(SIGINT, &sa, NULL);
|
||||
sigaction(SIGTERM, &sa, NULL);
|
||||
|
||||
// Create socket
|
||||
server_fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (server_fd == 0) {
|
||||
perror("Socket failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Configure the server address and port
|
||||
address.sin_family = AF_INET;
|
||||
address.sin_addr.s_addr = INADDR_ANY;
|
||||
address.sin_port = htons(port);
|
||||
|
||||
// Bind the socket to the port
|
||||
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
|
||||
perror("Bind failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Start listening for incoming connections
|
||||
if (listen(server_fd, 1) < 0) {
|
||||
perror("Listen failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Output immediately after listening starts
|
||||
printf("Server listening on port %i...\n", port);
|
||||
fflush(stdout); // Ensure output is flushed immediately
|
||||
|
||||
while (1) {
|
||||
// Accept client connections
|
||||
client_fd = accept(server_fd, (struct sockaddr *)&client_address, (socklen_t *)&addrlen);
|
||||
if (client_fd < 0) {
|
||||
perror("Accept failed");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get the client's IP address
|
||||
char client_ip[INET_ADDRSTRLEN];
|
||||
if (inet_ntop(AF_INET, &client_address.sin_addr, client_ip, sizeof(client_ip)) == NULL) {
|
||||
perror("inet_ntop failed");
|
||||
} else {
|
||||
printf("Connection from IP: %s\n", client_ip); // Log the client IP
|
||||
}
|
||||
|
||||
// Send a simple HTTP 200 OK response
|
||||
char response[] = "HTTP/1.1 200 OK\r\nContent-Length: 0\r\nserver: http-200\r\n\r\n";
|
||||
send(client_fd, response, strlen(response), 0);
|
||||
close(client_fd); // Close the client connection after sending the response
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user