Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 50 additions & 3 deletions exmaples.c → .arch/exmaples.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

#include <pthread.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define ARRAY_LEN(arr) (sizeof(arr) / sizeof((arr)[0]))

Expand All @@ -25,7 +28,10 @@ void swagger_json_handler(chttpx_request_t* req, chttpx_response_t* res)

void swagger_gui_handler(chttpx_request_t* req, chttpx_response_t* res)
{
char* url = "http://localhost:80/api/v1";
const char* port_env = getenv("CHTTPX_PORT");
const char* port = port_env && port_env[0] != '\0' ? port_env : "8080";
char url[128];
snprintf(url, sizeof(url), "http://localhost:%s/api/v1", port);

char swagger_html[8192];
snprintf(swagger_html, sizeof(swagger_html),
Expand Down Expand Up @@ -153,12 +159,51 @@ void file_upload(chttpx_request_t* req, chttpx_response_t* res)
return;
}

void chat_on_open(chttpx_wsocket_t* ws, void* userdata)
{
(void)userdata;
const char* room = cHTTPX_WSocketParam(ws, "room_id");
char welcome[256];
snprintf(welcome, sizeof(welcome), "Welcome to room %s!", room ? room : "?");
cHTTPX_WSocketSend(ws, welcome);
}

void chat_on_message(chttpx_wsocket_t* ws, const unsigned char* data, size_t len, int opcode, void* userdata)
{
(void)opcode;
(void)userdata;

char msg[4096];
if (len >= sizeof(msg))
len = sizeof(msg) - 1;
memcpy(msg, data, len);
msg[len] = '\0';

/* Only clients in the same room (same URL path) receive the message. */
cHTTPX_WSocketBroadcastPeers(ws, msg);
}

void chat_on_close(chttpx_wsocket_t* ws, void* userdata)
{
(void)ws;
(void)userdata;
}

static chttpx_wsocket_callbacks_t chat_callbacks = {
.on_open = chat_on_open,
.on_message = chat_on_message,
.on_close = chat_on_close,
};

int main()
{
chttpx_serv_t serv = {0};

size_t max_clients = 2;
if (cHTTPX_Init(&serv, 80, &max_clients) != 0)
const char* port_env = getenv("CHTTPX_PORT");
uint16_t port = port_env ? (uint16_t)atoi(port_env) : 8080;

size_t max_clients = 1024;
if (cHTTPX_Init(&serv, port, &max_clients) != 0)
{
printf("Failed to start server\n");
return 1;
Expand All @@ -180,6 +225,8 @@ int main()
cHTTPX_RegisterRoute(&v1, "PATCH", "/file", file_upload);
cHTTPX_RegisterRoute(&v1, "GET", "/doc.api/swagger/json", swagger_json_handler);
cHTTPX_RegisterRoute(&v1, "GET", "/doc.api/swagger/gui", swagger_gui_handler);
/* Client connects: ws://host/api/v1/ws/chat/lobby (room_id = "lobby") */
cHTTPX_WSocketRegisterRoute(&v1, "/ws/chat/{room_id}", &chat_callbacks);

/* At the very end, to start listening to incoming requests from users. */
cHTTPX_Listen();
Expand Down
File renamed without changes
File renamed without changes.
18 changes: 18 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.git
.github
.out
.build
*.tar.gz
libchttpx-dev
libchttpx.so
*.dll
*.a
logs/
exmaples.c
swagger.json
DEBIAN/
scripts/
tools/
*.md
LICENSE
ChangeLog
5 changes: 5 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,15 @@ Use a **conventional commit** title — it becomes the release version on merge:

- [ ] PR title follows the table above
- [ ] Code builds on Linux (`make lin` and `make libchttpx.so`)
- [ ] Tests pass (`make test`)
- [ ] Example server builds separately (`make example`) if needed
- [ ] Code builds on Windows (`make win`) if applicable
- [ ] Source is formatted (`make lin-format` or `clang-format`)
- [ ] README updated if public API or usage changed

## Related issues

<!-- Closes #123 -->

<!-- libchttpx-preview -->
<!-- /libchttpx-preview -->
9 changes: 7 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ name: CI

on:
push:
branches: [main, master]
branches: [develop, main, master]
pull_request:
branches: [main, master]

permissions:
contents: read
Expand All @@ -25,6 +24,9 @@ jobs:
- name: Build binary
run: make lin

- name: Run tests
run: make test

- name: Build shared library
run: make libchttpx.so

Expand All @@ -50,6 +52,9 @@ jobs:
- name: Build
run: mingw32-make win SHELL=cmd

- name: Run tests
run: mingw32-make win-test-run SHELL=cmd

static-analysis:
name: Static analysis (cppcheck)
runs-on: ubuntu-latest
Expand Down
54 changes: 54 additions & 0 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: Docker

on:
push:
branches: [main, master]
workflow_dispatch:

permissions:
contents: read

concurrency:
group: docker-${{ github.ref }}
cancel-in-progress: false

jobs:
publish:
name: Build and push to Docker Hub
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up QEMU
uses: docker/setup-qemu-action@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: noneandundefined/libchttpx
tags: |
type=raw,value=latest,enable={{is_default_branch}}
type=ref,event=branch
type=sha,prefix=

- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
platforms: linux/amd64,linux/arm64
128 changes: 128 additions & 0 deletions .github/workflows/pr-preview.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
name: PR Preview Build

on:
pull_request:
types: [opened, synchronize, reopened]

permissions:
contents: read
pull-requests: write

jobs:
preview-linux:
name: Preview build (Linux)
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Install dependencies
run: |
sudo apt update
sudo apt install -y gcc make libcjson-dev

- name: Build preview archive
run: make lin-lib

- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: libchttpx-dev-pr-${{ github.event.pull_request.number }}
path: libchttpx-dev.tar.gz
retention-days: 14

- name: Update PR with install instructions
uses: actions/github-script@v7
env:
RUN_ID: ${{ github.run_id }}
PR_NUMBER: ${{ github.event.pull_request.number }}
HEAD_REF: ${{ github.head_ref }}
HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }}
with:
script: |
const markerStart = '<!-- libchttpx-preview -->';
const markerEnd = '<!-- /libchttpx-preview -->';
const runId = process.env.RUN_ID;
const prNumber = process.env.PR_NUMBER;
const headRef = process.env.HEAD_REF;
const headRepo = process.env.HEAD_REPO;
const { owner, repo } = context.repo;
const fullRepo = `${owner}/${repo}`;
const runUrl = `https://github.com/${fullRepo}/actions/runs/${runId}`;
const scriptUrl = `https://raw.githubusercontent.com/${headRepo}/${headRef}/scripts/install-preview.sh`;
const oneLiner = `curl -sL ${scriptUrl} | sudo bash -s -- ${runId} ${prNumber} ${fullRepo}`;

const section = [
markerStart,
'## libchttpx preview build (Linux)',
'',
'> Auto-generated by CI on every push. Artifact is kept for 14 days.',
'',
'| | |',
'|---|---|',
`| **PR** | #${prNumber} |`,
`| **Workflow run** | [${runId}](${runUrl}) |`,
`| **Artifact** | \`libchttpx-dev-pr-${prNumber}\` |`,
'',
'### One-liner install (Linux)',
'',
'Requires [GitHub CLI](https://cli.github.com/) — run `gh auth login` once.',
'',
'```bash',
oneLiner,
'```',
'',
'### Manual install',
'',
'```bash',
`gh run download ${runId} -R ${fullRepo} -n libchttpx-dev-pr-${prNumber}`,
'tar -xzf libchttpx-dev.tar.gz && cd libchttpx-dev',
'sudo mkdir -p /usr/local/include/libchttpx /usr/local/lib/pkgconfig',
'sudo cp -r include/* /usr/local/include/libchttpx/',
'sudo cp libchttpx.so /usr/local/lib/',
'sudo cp libchttpx.pc /usr/local/lib/pkgconfig/',
'sudo ldconfig',
'```',
'',
'### Compile your app',
'',
'```bash',
'gcc main.c $(pkg-config --cflags --libs libchttpx) -lcjson',
'```',
markerEnd,
].join('\n');

const isFork = headRepo !== fullRepo;
const { data: pr } = await github.rest.pulls.get({
owner,
repo,
pull_number: Number(prNumber),
});

if (isFork) {
await github.rest.issues.createComment({
owner,
repo,
issue_number: Number(prNumber),
body: section.replace(markerStart, '').replace(markerEnd, '').trim()
+ '\n\n> Posted as comment because this PR is from a fork.',
});
return;
}

let body = pr.body ?? '';
const startIdx = body.indexOf(markerStart);
const endIdx = body.indexOf(markerEnd);

if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {
body = body.slice(0, startIdx) + section + body.slice(endIdx + markerEnd.length);
} else {
body = body.trimEnd() + '\n\n' + section;
}

await github.rest.pulls.update({
owner,
repo,
pull_number: Number(prNumber),
body,
});
50 changes: 50 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# syntax=docker/dockerfile:1

# Dev base image: prebuilt libchttpx + toolchain for compiling C/C++ apps.
#
# Usage in other projects:
# FROM noneandundefined/libchttpx:latest
# WORKDIR /app
# COPY . .
# RUN gcc main.c $(pkg-config --cflags --libs libchttpx) -lcjson -o app

FROM debian:bookworm-slim AS builder

RUN apt-get update \
&& apt-get install -y --no-install-recommends \
build-essential \
libcjson-dev \
pkg-config \
&& rm -rf /var/lib/apt/lists/*

WORKDIR /src

COPY Makefile libchttpx.pc ./
COPY include/ include/
COPY src/ src/
COPY tests/ tests/

RUN make test \
&& make lib-install DESTDIR=/out PREFIX=/usr/local

FROM debian:bookworm-slim

RUN apt-get update \
&& apt-get install -y --no-install-recommends \
build-essential \
libcjson-dev \
pkg-config \
&& rm -rf /var/lib/apt/lists/*

COPY --from=builder /out/usr/local/ /usr/local/

RUN ldconfig \
&& pkg-config --exists libchttpx \
&& test -f /usr/local/lib/libchttpx.so \
&& test -d /usr/local/include/libchttpx

LABEL org.opencontainers.image.source="https://github.com/netcorelink/libchttpx" \
org.opencontainers.image.description="A powerful, cross-platform HTTP server library in C/C++ for building full-featured web servers." \
org.opencontainers.image.licenses="MIT"

WORKDIR /app
Loading
Loading