{"id":20172259,"url":"https://github.com/apostoldevel/module-appserver","last_synced_at":"2026-06-08T00:32:02.055Z","repository":{"id":110915410,"uuid":"291068854","full_name":"apostoldevel/module-AppServer","owner":"apostoldevel","description":"Module: Application Server","archived":false,"fork":false,"pushed_at":"2024-09-20T17:41:09.000Z","size":40,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-01-13T15:50:02.049Z","etag":null,"topics":["app-service","application-server"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/apostoldevel.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-08-28T14:35:26.000Z","updated_at":"2024-09-20T17:41:13.000Z","dependencies_parsed_at":"2024-11-14T01:30:38.426Z","dependency_job_id":"f7829adf-cd0f-4c19-b67b-f7345fdad356","html_url":"https://github.com/apostoldevel/module-AppServer","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apostoldevel%2Fmodule-AppServer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apostoldevel%2Fmodule-AppServer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apostoldevel%2Fmodule-AppServer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apostoldevel%2Fmodule-AppServer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/apostoldevel","download_url":"https://codeload.github.com/apostoldevel/module-AppServer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241607700,"owners_count":19989942,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["app-service","application-server"],"created_at":"2024-11-14T01:29:26.552Z","updated_at":"2026-06-08T00:32:02.047Z","avatar_url":"https://github.com/apostoldevel.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![ru](https://img.shields.io/badge/lang-ru-green.svg)](README.ru-RU.md)\n\nApp Server\n-\n\n**Module** for **Apostol CRM**[^crm].\n\nDescription\n-\n\n**App Server** is a C++ HTTP/RESTful server module for the [Apostol (C++20)](https://github.com/apostoldevel/libapostol) framework. It runs inside Apostol worker processes and handles all incoming HTTP requests routed to the `/api/` path prefix.\n\nKey characteristics:\n\n* Written in C++20 using an asynchronous, non-blocking I/O model based on the **epoll** API — suitable for high-throughput, low-latency deployments.\n* Connects directly to **PostgreSQL** via the `libpq` library. Every API request is dispatched to a PL/pgSQL function in the database; all business logic lives in the database, not in the module itself.\n* Implements **REST** (Representational State Transfer) conventions for remote procedure calls over HTTP.\n* Supports multiple authentication methods: **Bearer JWT** token, **Session + Secret** headers, and **Cookie-Based** authentication (`__Secure-AT`).\n* Response format is always `application/json`.\n* Built-in endpoints (`/ping`, `/time`) require no database interaction and are handled entirely in C++. All other endpoints are forwarded to the PostgreSQL `daemon` schema functions.\n\n### How it fits into Apostol\n\nApostol runs a master process that forks N worker processes. Each worker loads a set of modules. `AppServer` is one such module — it registers itself as the handler for any request whose path starts with `/api/`. When a matching request arrives:\n\n1. The worker's event loop (epoll) accepts the connection and reads the HTTP request.\n2. `AppServer` inspects the `Authorization` header to determine the authentication context.\n3. Based on the authentication result, it constructs a parameterised SQL call and submits it to the PostgreSQL connection pool asynchronously:\n   - **Bearer JWT** (valid token) → `daemon.fetch`\n   - **Session + Secret** headers → `daemon.session_fetch`\n   - **No credentials** → `daemon.unauthorized_fetch`\n   - **Expired token** with refresh cookie → auto-refreshes via `daemon.refresh_token`, then calls `daemon.fetch` with the new token\n4. When the query result arrives, the module serialises it as JSON and sends the HTTP reply.\n\nDocumentation\n-\n\nREST API\n-\n\n### General information\n\n* Base endpoint: [http://localhost:8080](http://localhost:8080)\n* All endpoints return a **JSON object**.\n* All time and timestamp fields are in **milliseconds** (Unix epoch).\n\n### HTTP status codes\n\n* `2XX` — success.\n* `4XX` — client error (malformed request, authentication failure, resource not found, etc.).\n* `5XX` — server error. The outcome of the operation is **unknown** — do not assume failure without verifying.\n\n### Error response format\n\nAny endpoint may return an error. The response body will contain an `error` object:\n\n```json\n{\n  \"error\": {\n    \"code\": 404,\n    \"message\": \"Not Found\"\n  }\n}\n```\n\nError codes \u003e= 10000 are divided by 100 to map to standard HTTP status codes (e.g. 40401 → 404).\n\n### Endpoint conventions\n\n* For `GET` endpoints, all parameters are passed as **query string** values.\n* For `POST` endpoints, parameters may be sent as a query string or as the request body. Supported content types for the request body:\n  * `application/json`\n  * `application/x-www-form-urlencoded`\n  * `multipart/form-data`\n* Parameters may be sent in any order.\n* The module accepts `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, and `OPTIONS`. All other HTTP methods return `405 Method Not Allowed`.\n\n### Response shaping (optional query parameters)\n\nTwo optional query parameters influence how PostgreSQL query results are serialised:\n\n| Parameter | Allowed values | Effect |\n|-----------|----------------|--------|\n| `result_object` | `true`, `false` | When `true`, wraps the result in `{\"result\": ...}` |\n| `result_format` | `object`, `array`, `null` | Forces the JSON serialisation format of the result set. Paths containing `/list` default to `array`. |\n\nAPI Access\n-\n\nAccess requires a **Bearer access token**, **Session + Secret** headers, or **Cookie-Based** authentication.\n\n### Bearer token (JWT)\n\nThe access token **must** be present in the `Authorization` HTTP header of every authenticated request.\n\nFormat:\n\n```\nAuthorization: Bearer \u003caccess_token\u003e\n```\n\nThe access token is a JSON Web Token ([RFC 7519](https://tools.ietf.org/html/rfc7519)). It is issued by the [AuthServer](https://github.com/apostoldevel/module-AuthServer) module (which is part of the same Apostol application).\n\nThe module validates the token locally using the configured provider secrets/keys before forwarding the request to the database. Supported algorithms: HS256, HS384, HS512, RS256, RS384, RS512, ES256, ES384, ES512, PS256, PS384, PS512.\n\nTokens are also accepted from the `__Secure-AT` cookie (set by the server after login); the accompanying refresh token is read from `__Secure-RT`.\n\n**Example request:**\n\n```http\nGET /api/v1/whoami HTTP/1.1\nHost: localhost:8080\nAuthorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiIDogImFjY291bnRzLnNoaXAtc2FmZXR5LnJ1IiwgImF1ZCIgOiAid2ViLXNoaXAtc2FmZXR5LnJ1IiwgInN1YiIgOiAiZGZlMDViNzhhNzZiNmFkOGUwZmNiZWYyNzA2NzE3OTNiODZhYTg0OCIsICJpYXQiIDogMTU5MzUzMjExMCwgImV4cCIgOiAxNTkzNTM1NzEwfQ.NorYsi-Ht826HUFCEArVZ60_dEUmYiJYXubnTyweIMg\n```\n\nBuilt-in Endpoints\n-\n\nThese endpoints are handled entirely in C++ and require no database access or authentication.\n\n### Ping\n\n```http\nGET /api/v1/ping\n```\n\nTests connectivity to the REST API.\n\n**Parameters:** none\n\n**Response:**\n\n```json\n{}\n```\n\n### Server time\n\n```http\nGET /api/v1/time\n```\n\nTests connectivity and returns the current server time.\n\n**Parameters:** none\n\n**Response:**\n\n```json\n{\n  \"serverTime\": 1583495795455\n}\n```\n\n`serverTime` is the number of milliseconds since the Unix epoch (UTC).\n\nApplication-specific Endpoints\n-\n\nAll paths under `/api/` that are not handled by the built-in endpoints above are forwarded to PostgreSQL. The database function called depends on the authentication context:\n\n| Context | PostgreSQL function |\n|---------|---------------------|\n| Bearer JWT token | `daemon.fetch(token, method, path, payload, agent, host)` |\n| Session + Secret headers (Basic) | `daemon.session_fetch(session, secret, method, path, payload, agent, host)` |\n| No credentials (when enabled) | `daemon.unauthorized_fetch(method, path, payload, agent, host)` |\n\nThe full set of application endpoints is therefore defined entirely in the project's database, in the `daemon` schema PL/pgSQL functions. **See your project's repository for endpoint documentation.**\n\nInstallation\n-\n\nFollow the build and installation instructions for [Apostol (C++20)](https://github.com/apostoldevel/libapostol#build-and-installation).\n\n[^crm]: **Apostol CRM** — a template project built on the [A-POST-OL](https://github.com/apostoldevel/libapostol) (C++20) and [PostgreSQL Framework for Backend Development](https://github.com/apostoldevel/db-platform) frameworks.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fapostoldevel%2Fmodule-appserver","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fapostoldevel%2Fmodule-appserver","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fapostoldevel%2Fmodule-appserver/lists"}