{"id":21133880,"url":"https://github.com/mozgiii/sap","last_synced_at":"2025-07-09T02:32:03.221Z","repository":{"id":240624779,"uuid":"803125403","full_name":"MOZGIII/sap","owner":"MOZGIII","description":"Opinionated HTTP server for hosting static files of Single Page Apps from memory with blazing fast speeds","archived":false,"fork":false,"pushed_at":"2024-10-15T19:52:03.000Z","size":167,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-10-17T01:03:39.675Z","etag":null,"topics":["http","http-server","spa","static-file-server","static-files","static-site","web-server"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MOZGIII.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2024-05-20T05:50:38.000Z","updated_at":"2024-10-15T19:52:06.000Z","dependencies_parsed_at":"2024-05-20T07:39:27.646Z","dependency_job_id":"b0ed29c5-f7c2-4ff0-918f-b5555c4a9cfe","html_url":"https://github.com/MOZGIII/sap","commit_stats":null,"previous_names":["mozgiii/sap"],"tags_count":10,"template":false,"template_full_name":"MOZGIII/template-rust","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MOZGIII%2Fsap","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MOZGIII%2Fsap/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MOZGIII%2Fsap/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MOZGIII%2Fsap/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MOZGIII","download_url":"https://codeload.github.com/MOZGIII/sap/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225476486,"owners_count":17480294,"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":["http","http-server","spa","static-file-server","static-files","static-site","web-server"],"created_at":"2024-11-20T06:19:12.328Z","updated_at":"2024-11-20T06:19:13.216Z","avatar_url":"https://github.com/MOZGIII.png","language":"Rust","readme":"# sap\n\nOpinionated HTTP server for hosting static files of Single Page Apps from memory\nwith blazing fast speeds.\n\n## Goals and non-goals\n\nGoals:\n\n- serve static files\n- simple templating to allow injecting ENV-values-based configurations\n- easy docker image composition\n- sane configuration for select HTTP header values, like CSP and etc\n\nNon-goals:\n\n- SSR\n- SPA code builds (you can still do this via your own docker stages)\n- API proxying (already handled by the reverse proxy / edge)\n- HTTPS (already handled by the reverse proxy / edge)\n\n## Usage\n\nUsing the `onbuild` image:\n\n```dockerfile\nFROM ghcr.io/mozgiii/sap:latest-onbuild\n```\n\nor using the regular image and copying the files manually:\n\n```dockerfile\nFROM ghcr.io/mozgiii/sap:latest\n\nCOPY . /app\n\nENV ROOT_DIR=/app\n```\n\n## Configuration\n\n### Server configuration\n\nAll the configuration parameters are set via env vars.\n\nSee [`crates/sap/src/main.rs`](crates/sap/src/main.rs) to learn about the available settings.\n\n### SPA configuration\n\nThere are two (opinionated) ways for configuring Single Page Applications\nwith `sap`:\n\n1. substituting values from the env variables for the corresponding\n   JSON object keys in the HTML `script` tag with the `type` attribute set\n   to `application/spa-cfg` on the `/` route - this is called HTML templating,\n   and\n2. substituting values from the env variables for the corresponding\n   JSON object keys in the JSON file on the `/config.json` route - this is\n   called JSON templating.\n\n#### General idea\n\nThe in both cases we take the JSON object. We iterate over the keys of\nthe object, we take each key, turn it into `CONSTANT_CASE` add prefix and\ncheck if a env var with this name exists. If it doesn't - the value of the key\nis left as it is in the original JSON, but if the env var **is** set - then\nwe replace the value in JSON with the value of the env var.\n\n\u003e [!WARNING]\n\u003e\n\u003e We require that JSON object used for configuration has only `string` values.\n\u003e\n\u003e In TypeScript that requirement would look like this:\n\u003e\n\u003e ```js\n\u003e type Config = { [key: string]: string };\n\u003e ```\n\n#### HTML templating\n\nHere is a simplified example of `index.html` file (used as the root (`/`) route):\n\n```html\n\u003chtml\u003e\n\u003cbody\u003e\n  \u003cscript type=\"application/spa-cfg\"\u003e{\"myKey\": \"default value\"}\u003c/script\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\nWith `sap` using default SPA configs prefix `APP_` and with\nthe `APP_MY_KEY` env var set to `override value`, this is what the returned\npage body will look like:\n\n```html\n\u003chtml\u003e\n\u003cbody\u003e\n  \u003cscript type=\"application/spa-cfg\"\u003e{\"myKey\": \"override value\"}\u003c/script\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\n##### Example with Docker (HTML templating)\n\nIf we assume that you have a `Dockerfile` like this:\n\n```shell\n$ cat Dockerfile\nFROM ghcr.io/mozgiii/sap:latest\nENV ROOT_DIR /app\nCOPY build /app\n```\n\nand the `index.html` in the `build` directory like this:\n\n```shell\n$ cat build/index.html\n\u003chtml\u003e\n\u003cbody\u003e\n  \u003cscript type=\"application/spa-cfg\"\u003e{\"myKey\": \"default value\"}\u003c/script\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\nwe can build the test image like this:\n\n```shell\n$ docker build . -t sap-test\n...\n```\n\nAt this point we have our app dockerized and ready to run.\n\n```shell\n$ docker run --rm -it -p 8080:8080 sap-test\n...\n2024-01-01T12:34:56.789123Z  Successfully applied HTML templating route=/ dir_entry_path=\"/app/index.html\"\n...\n2024-01-01T12:34:56.789123Z  INFO sap: About to start the server addr=0.0.0.0:8080\n...\n```\n\nIn another terminal we can run the following command to try it:\n\n```shell\n$ curl http://localhost:8080\n\u003chtml\u003e\n\u003cbody\u003e\n  \u003cscript type=\"application/spa-cfg\"\u003e{\"myKey\": \"default value\"}\u003c/script\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\nThe neat thing is that we can change the settings as we please, without\nrebuilding the app from source or recreating docker image - just like\nit was intended with containers!\n\nContinue with stopping the `sap-test` container via `Ctrl+C`...\n\n```shell\nC^\n... (stopping) ...\n$\n```\n\n... and running with the env var to change the SPA configuration:\n\n```shell\n$ docker run --rm -it -p 8080:8080 -e APP_MY_KEY=\"override value\" sap-test\n...\n2024-01-01T12:34:56.789123Z  Successfully applied HTML templating route=/ dir_entry_path=\"/app/index.html\"\n...\n2024-01-01T12:34:56.789123Z  INFO sap: About to start the server addr=0.0.0.0:8080\n...\n```\n\nThen in the other terminal:\n\n```shell\n$ curl http://localhost:8080\n\u003chtml\u003e\n\u003cbody\u003e\n  \u003cscript type=\"application/spa-cfg\"\u003e{\"myKey\": \"override value\"}\u003c/script\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\nNote how the configuration value `myKey` has changed.\n\n##### Usage in the SPA code (HTML templating)\n\nThis can be utilized from the SPA with the code like this:\n\n```js\nfunction readConfig() {\n  const el = document.querySelector(\"script[type=\\\"application/spa-cfg\\\"]\");\n  const configText = el.innerText;\n  const config = JSON.parse(configText);\n  return config;\n}\n```\n\nThis allows you to get the dynamic configuration without rebuilds. This way also\nhas a benefit of not involving any `async` or `Promise`s.\n\n#### JSON templating\n\n\u003e [!IMPORTANT]\n\u003e\n\u003e JSON templating in an opt-in, and requires `CONFIG_JSON_TEMPLATING=true` env\n\u003e var to be set to work.\n\nAn example of `config.json` file (with the `/config.json` route):\n\n```json\n{\"myKey\":\"default value\"}\n```\n\nWith `sap` with `CONFIG_JSON_TEMPLATING=true`, using default SPA configs prefix\n`APP_`  and with the `APP_MY_KEY` env var set to `override value`, this is what\nthe returned `/config.json` response body will look like:\n\n```json\n{\"myKey\":\"override value\"}\n```\n\n##### Example with Docker (JSON templating)\n\nIf we assume that you have a `Dockerfile` like this:\n\n```shell\n$ cat Dockerfile\nFROM ghcr.io/mozgiii/sap:latest\nENV ROOT_DIR /app\nCOPY build /app\n```\n\nand the `config.json` in the `build` directory like this:\n\n```shell\n$ cat build/config.json\n{\"myKey\":\"default value\"}\n```\n\nwe can build the test image like this:\n\n```shell\n$ docker build . -t sap-test\n...\n```\n\nAt this point we have our app dockerized and ready to run.\n\n\u003e Well, technically it is just the config, but you can add the rest of the files\n\u003e of your app there as well.\n\n```shell\n$ docker run --rm -it -p 8080:8080 sap-test\n...\n2024-01-01T12:34:56.789123Z  Successfully applied JSON templating route=/config.json dir_entry_path=\"/app/config.json\"\n...\n2024-01-01T12:34:56.789123Z  INFO sap: About to start the server addr=0.0.0.0:8080\n...\n```\n\nIn another terminal we can run the following command to try it:\n\n```shell\n$ curl http://localhost:8080/config.json\n{\"myKey\":\"default value\"}\n```\n\nThe neat thing, just like with HTML templating, is that we can change\nthe settings as we please, without rebuilding the app from source or recreating\ndocker image - just like it was intended with containers!\n\nContinue with stopping the `sap-test` container via `Ctrl+C`...\n\n```shell\nC^\n... (stopping) ...\n$\n```\n\n... and running with the env var to change the SPA configuration:\n\n```shell\n$ docker run --rm -it -p 8080:8080 -e APP_MY_KEY=\"override value\" sap-test\n...\n2024-01-01T12:34:56.789123Z  Successfully applied JSON templating route=/config.json dir_entry_path=\"/app/config.json\"\n...\n2024-01-01T12:34:56.789123Z  INFO sap: About to start the server addr=0.0.0.0:8080\n...\n```\n\nThen in the other terminal:\n\n```shell\n$ curl http://localhost:8080/config.json\n{\"myKey\":\"override value\"}\n```\n\nAgain, just like with HTML templating, configuration value of the key `myKey`\nhas changed.\n\n##### Usage in the SPA code (JSON templating)\n\nThis can be utilized from the SPA with the code like this:\n\n```js\nconst readConfig = async () =\u003e fetch(\"/config.json\").then(res =\u003e res.json());\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmozgiii%2Fsap","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmozgiii%2Fsap","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmozgiii%2Fsap/lists"}