{"id":20172259,"url":"https://github.com/apostoldevel/module-appserver","last_synced_at":"2025-11-29T02:05:28.853Z","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":"2025-11-29T02:05:28.824Z","avatar_url":"https://github.com/apostoldevel.png","language":"C++","readme":"Сервер приложений\n-\n**Модуль** для [Апостол CRM](https://github.com/apostoldevel/apostol-crm).\n\nОписание\n-\n* **Сервер приложений** (HTTP-сервер, RESTful-сервер) разработан на C++ с применением асинхронной модели программирования на базе epoll API с прямым доступом к СУБД PostgreSQL (через библиотеку: libpq) специально для высоконагруженных систем. \n\n* Используется для удалённого вызова процедур с применением архитектурного стиля [REST](https://ru.wikipedia.org/wiki/REST) (от англ. Representational State Transfer — _передача состояния представления_).\n\nУстановка\n-\nСледуйте указаниям по сборке и установке [Апостол CRM](https://github.com/apostoldevel/apostol-crm#%D1%81%D0%B1%D0%BE%D1%80%D0%BA%D0%B0-%D0%B8-%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0)\n\nДокументация\n-\n## REST API\n\n## Общая информация\n * Базовая конечная точка (endpoint): [localhost:8080](http://localhost:8080)\n * Все конечные точки возвращают `JSON-объект`\n * Все поля, относящиеся ко времени и меткам времени, указаны в **миллисекундах**. \n\n## HTTP коды возврата\n * HTTP `4XX` коды возврата применимы для некорректных запросов - проблема на стороне клиента.\n * HTTP `5XX` коды возврата используются для внутренних ошибок - проблема на стороне сервера. Важно **НЕ** рассматривать это как операцию сбоя. Статус выполнения **НЕИЗВЕСТЕН** и может быть успешным.\n \n## Коды ошибок\n * Любая конечная точка может вернуть ошибку.\n  \n**Пример ответа:**\n```json\n{\n  \"error\": {\n    \"code\": 404,\n    \"message\": \"Not Found\"\n  }\n}\n```\n\n## Общая информация о конечных точках\n * Для `GET` конечных точек параметры должны быть отправлены в виде `строки запроса (query string)` .\n * Для `POST` конечных точек, некоторые параметры могут быть отправлены в виде `строки запроса (query string)`, а некоторые в виде `тела запроса (request body)`:\n * При отправке параметров в виде `тела запроса` допустимы следующие типы контента:\n    * `application/x-www-form-urlencoded` для `query string`;\n    * `multipart/form-data` для `HTML-форм`;\n    * `application/json` для `JSON`.\n * Параметры могут быть отправлены в любом порядке.\n\n## Доступ к API\n\nДоступ к API возможен только при наличии _**маркера доступа**_ или **_цифровой подписи_** методом HMAC-SHA256. \n\n#### Маркер доступа\n\n**Маркера доступа** (`access_token`) **ДОЛЖЕН** присутствовать в HTTP заголовке `Authorization` каждого запроса.\n \nФормат:\n~~~\nAuthorization: Bearer \u003caccess_token\u003e\n~~~\n\n**Маркера доступа** - это `JSON Web Token` [RFC 7519](https://tools.ietf.org/html/rfc7519). \n\nВыдается он [сервером авторизации](https://github.com/apostoldevel/module-AuthServer), роль которого выполняет сама же система.\n\nПример запроса:\n* **http request:**\n```http request\nGET /api/v1/whoami HTTP/1.1\nHost: localhost:8080\nAuthorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiIDogImFjY291bnRzLnNoaXAtc2FmZXR5LnJ1IiwgImF1ZCIgOiAid2ViLXNoaXAtc2FmZXR5LnJ1IiwgInN1YiIgOiAiZGZlMDViNzhhNzZiNmFkOGUwZmNiZWYyNzA2NzE3OTNiODZhYTg0OCIsICJpYXQiIDogMTU5MzUzMjExMCwgImV4cCIgOiAxNTkzNTM1NzEwfQ.NorYsi-Ht826HUFCEArVZ60_dEUmYiJYXubnTyweIMg\n````\n\n#### Цифровая подпись методом HMAC-SHA256\n\nВместо HTTP заголовка `Authorization` можно использовать подпись. \n\nДля передачи данных авторизации в виде подписи используются следующие HTTP заголовки:\n  * `Session` - ключ сессии;\n  * `Nonce` - данное время в миллисекундах;\n  * `Signature` - подпись.\n\n**Примеры:**\n\n\u003cdetails\u003e\n  \u003csummary\u003eПример создания подписи на JavaScript (без данных в теле сообщения)\u003c/summary\u003e\n  \n~~~javascript\n// CryptoJS - Standard JavaScript cryptography library\n\nconst body = null;\n\nconst Session = localStorage.getItem('Session'); // efa885ebde1baa991a3c798fc1141f6bec92fc90\nconst Secret = localStorage.getItem('Secret'); // y2WYJRE9f13g6qwFOEOe0rGM/ISlGFEEesUpQadHNd/aJL+ExKRj5E6OSQ9TuJRC\n\nconst Path = '/whoami';\nconst Nonce = (Date.now() * 1000).toString(); // 1589998352818000\nconst Body = JSON.stringify(body); // if body === null then Body = \"null\" \u003c-- string  \n\nconst sigData = `${Path}${Nonce}${Body}`; // /whoami1589998352818000null\n\nconst Signature = CryptoJS.HmacSHA256(sigData, Secret).toString(); // 91609292e250fc30c48c2ad387d1121c703853fa88ce027e6ba0efe1fcb50ba1\n\nlet headers = new Headers();\n\nheaders.append('Session', Session);\nheaders.append('Nonce', Nonce);\nheaders.append('Signature', Signature);\nheaders.append('Content-Type', 'application/json');\n\nconst init = {\n    method: 'POST',\n    headers: headers,\n    body: Body,\n    mode: \"cors\"\n};\n\nconst apiPath = `/api/v1${Path}`;\n\nfetch(apiPath, init)\n    .then((response) =\u003e {\n        return response.json();\n    })\n    .then((json) =\u003e {\n        console.log(json);\n    })\n    .catch((e) =\u003e {\n        console.log(e.message);\n});\n~~~\n\n* **openssl command:**\n```shell script\necho -n \"/whoami1589998352818000null\" | \\\nopenssl sha256 -hmac \"y2WYJRE9f13g6qwFOEOe0rGM/ISlGFEEesUpQadHNd/aJL+ExKRj5E6OSQ9TuJRC\"\n(stdin)= 91609292e250fc30c48c2ad387d1121c703853fa88ce027e6ba0efe1fcb50ba1\n```\n* **curl command:**\n```curl\ncurl -X POST \\\n     -H \"Session: efa885ebde1baa991a3c798fc1141f6bec92fc90\" \\\n     -H \"Nonce: 1589998352818000\" \\\n     -H \"Signature: 91609292e250fc30c48c2ad387d1121c703853fa88ce027e6ba0efe1fcb50ba1\" \\\n     http://localhost:8080/api/v1/whoami\n````     \n* **http request:**\n```http request\nPOST /api/v1/whoami HTTP/1.1\nHost: localhost:8080\nSession: efa885ebde1baa991a3c798fc1141f6bec92fc90\nNonce: 1589998352818000\nSignature: 91609292e250fc30c48c2ad387d1121c703853fa88ce027e6ba0efe1fcb50ba1\n````\n\u003c/details\u003e\n  \n\u003cdetails\u003e\n  \u003csummary\u003eПример создания подписи на JavaScript (с данными в теле сообщения)\u003c/summary\u003e\n\n~~~javascript\n// CryptoJS - Standard JavaScript cryptography library\n\nconst body = {\n  classcode : 'client',\n  statecode : 'enabled',\n  actioncode: 'invite'\n};\n\nconst Session = localStorage.getItem('Session'); // efa885ebde1baa991a3c798fc1141f6bec92fc90\nconst Secret = localStorage.getItem('Secret'); // y2WYJRE9f13g6qwFOEOe0rGM/ISlGFEEesUpQadHNd/aJL+ExKRj5E6OSQ9TuJRC\n\nconst Path = '/method/get';\nconst Nonce = (Date.now() * 1000).toString(); // 1589998352902000\nconst Body = JSON.stringify(body); // \u003c-- JSON string  \n\nconst sigData = `${Path}${Nonce}${Body}`; // /method/get1589998352902000{\"classcode\":\"client\",\"statecode\":\"enabled\",\"actioncode\":\"invite\"}\n\nconst Signature = CryptoJS.HmacSHA256(sigData, Secret).toString(); // 2b2bf5188ea40dfe8207efec56956b6170bdbc2f0ab0bffd8b50acd60979b09b\n\nlet headers = new Headers();\n\nheaders.append('Session', Session);\nheaders.append('Nonce', Nonce);\nheaders.append('Signature', Signature);\nheaders.append('Content-Type', 'application/json');\n\nconst init = {\n    method: 'POST',\n    headers: headers,\n    body: Body,\n    mode: \"cors\"\n};\n\nconst apiPath = `/api/v1${Path}`;\n\nfetch(apiPath, init)\n    .then((response) =\u003e {\n        return response.json();\n    })\n    .then((json) =\u003e {\n        console.log(json);\n    })\n    .catch((e) =\u003e {\n        console.log(e.message);\n});\n~~~\n\n* **openssl command:**\n```shell script\necho -n \"/method/get1589998352902000{\\\"classcode\\\":\\\"client\\\",\\\"statecode\\\":\\\"enabled\\\",\\\"actioncode\\\":\\\"invite\\\"}\" | \\\nopenssl sha256 -hmac \"y2WYJRE9f13g6qwFOEOe0rGM/ISlGFEEesUpQadHNd/aJL+ExKRj5E6OSQ9TuJRC\"\n(stdin)= 2b2bf5188ea40dfe8207efec56956b6170bdbc2f0ab0bffd8b50acd60979b09b\n````\n* **curl command:**\n```curl\ncurl -X POST \\\n     -H \"Session: efa885ebde1baa991a3c798fc1141f6bec92fc90\" \\\n     -H \"Nonce: 1589998352902000\" \\\n     -H \"Signature: 2b2bf5188ea40dfe8207efec56956b6170bdbc2f0ab0bffd8b50acd60979b09b\" \\\n     -d \"{\\\"classcode\\\":\\\"client\\\",\\\"statecode\\\":\\\"enabled\\\",\\\"actioncode\\\":\\\"invite\\\"}\" \\\n     http://localhost:8080/api/v1/method/get\n````\n* **http request:**\n```http request\nPOST /api/v1/method/get HTTP/1.1\nHost: localhost:8080\nSession: efa885ebde1baa991a3c798fc1141f6bec92fc90\nNonce: 1589998352902000\nSignature: 2b2bf5188ea40dfe8207efec56956b6170bdbc2f0ab0bffd8b50acd60979b09b\n\n{\"classcode\":\"client\",\"statecode\":\"enabled\",\"actioncode\":\"invite\"}\n````\n\u003c/details\u003e\n\n### Конечные точки\n\n#### Тест подключения\n```http request\nGET /api/v1/ping\n```\nПроверить подключение к REST API.\n \n**Параметры запроса:**\nНЕТ\n \n**Пример ответа:**\n```json\n{}\n```\n \n#### Проверить время сервера\n```http request\nGET /api/v1/time\n```\nПроверить подключение к REST API и получить текущее время сервера.\n \n**Параметры запроса:**\n НЕТ\n  \n**Пример ответа:**\n```json\n{\n  \"serverTime\": 1583495795455\n}\n```\n\n**Полное описание конечных точек смотрите в репозитории вашего проекта**.\n","funding_links":[],"categories":[],"sub_categories":[],"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"}