{"id":15617088,"url":"https://github.com/patarapolw/webview-server","last_synced_at":"2025-03-29T15:25:02.677Z","repository":{"id":95361377,"uuid":"291231458","full_name":"patarapolw/webview-server","owner":"patarapolw","description":"webview for web servers, with focus on customizability and security","archived":false,"fork":false,"pushed_at":"2020-09-09T06:04:04.000Z","size":88,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-04T16:17:02.179Z","etag":null,"topics":["csrf","golang","lorca","webview"],"latest_commit_sha":null,"homepage":"","language":"Go","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/patarapolw.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-29T08:23:39.000Z","updated_at":"2020-09-09T06:04:01.000Z","dependencies_parsed_at":null,"dependency_job_id":"72e1720d-e812-4a3f-9afe-1c628c2b43bf","html_url":"https://github.com/patarapolw/webview-server","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patarapolw%2Fwebview-server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patarapolw%2Fwebview-server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patarapolw%2Fwebview-server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patarapolw%2Fwebview-server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/patarapolw","download_url":"https://codeload.github.com/patarapolw/webview-server/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246201955,"owners_count":20739864,"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":["csrf","golang","lorca","webview"],"created_at":"2024-10-03T07:41:26.051Z","updated_at":"2025-03-29T15:25:02.641Z","avatar_url":"https://github.com/patarapolw.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Practical web server in Golang with clean-up function\n\nSo, I tried to write a web server in Golang to fit in with [zserge/lorca](https://github.com/zserge/lorca). Focusing on [maximize/fullscreen on all platforms](https://github.com/webview/webview/issues/458) as well.\n\nSee [the original post](https://dev.to/patarapolw/practical-web-server-in-vanilla-go-with-clean-up-function-i-don-t-really-know-what-i-am-doing-1nh5).\n\nTested with cURL's\n\n```sh\n% PORT=3000 ./webview-server\n% curl -i -X PUT --data 'hello' http://127.0.0.1:3000/api/file\\?filename\\=test.txt\n```\n\nThis, by default, works with [lokijs](https://github.com/techfort/LokiJS), by using a custom adaptor.\n\n```ts\nimport Loki from 'lokijs'\n\nclass LokiRestAdaptor {\n  loadDatabase (dbname: string, callback: (data: string | null | Error) =\u003e void) {\n    fetch(`/api/file?filename=${encodeURIComponent(dbname)}`)\n      .then((r) =\u003e r.text())\n      .then((r) =\u003e callback(r))\n      .catch((e) =\u003e callback(e))\n  }\n\n  saveDatabase (dbname: string, dbstring: string, callback: (e: Error | null) =\u003e void) {\n    fetch(`/api/file?filename=${encodeURIComponent(dbname)}`, {\n      method: 'PUT',\n      body: dbstring\n    })\n      .then(() =\u003e callback(null))\n      .catch((e) =\u003e callback(e))\n  }\n\n  deleteDatabase (dbname: string, callback: (data: Error | null) =\u003e void) {\n    fetch(`/api/file?filename=${encodeURIComponent(dbname)}`, {\n      method: 'DELETE'\n    })\n      .then(() =\u003e callback(null))\n      .catch((e) =\u003e callback(e))\n  }\n}\n\n// eslint-disable-next-line import/no-mutable-exports\nexport let loki: Loki\n\nexport async function initDatabase () {\n  return new Promise((resolve) =\u003e {\n    loki = new Loki('db.loki', {\n      adapter: new LokiRestAdaptor(),\n      autoload: true,\n      autoloadCallback: () =\u003e {\n        resolve()\n      },\n      autosave: true,\n      autosaveInterval: 4000\n    })\n  })\n}\n\nwindow.onbeforeunload = (e: Event) =\u003e {\n  if (loki) {\n    if (loki.autosaveDirty()) {\n      loki.saveDatabase()\n\n      e.preventDefault()\n      e.returnValue = false\n    }\n  }\n}\n```\n\nAnd, in you Webpack dev server (e.g. `webpack.config.js`)\n\n```js\n// @ts-check\n\n/* eslint-disable @typescript-eslint/no-var-requires */\nconst fs = require('fs')\nconst path = require('path')\n\nconst morgan = require('morgan')\n\nconst BINARY_DIR = 'release'\n\nmodule.exports = {\n  devServer: {\n    /**\n     *\n     * @param {import('express').Express} app\n     * @param {import('http').Server} server\n     * @param {*} compiler\n     */\n    // eslint-disable-next-line @typescript-eslint/no-unused-vars\n    before (app, server, compiler) {\n      app.use('/api', morgan('tiny'))\n\n      app.get('/api/file', (req, res) =\u003e {\n        /** @type {*} */\n        const { filename } = req.query\n        const p = path.resolve(__dirname, BINARY_DIR, filename)\n\n        if (fs.existsSync(p)) {\n          fs.createReadStream(p).pipe(res)\n          return\n        }\n\n        res.sendStatus(404)\n      })\n\n      app.put('/api/file', (req, res) =\u003e {\n        /** @type {*} */\n        const { filename } = req.query\n        const p = path.resolve(__dirname, BINARY_DIR, filename)\n\n        req.pipe(fs.createWriteStream(p))\n        res.sendStatus(201)\n      })\n\n      app.delete('/api/file', (req, res) =\u003e {\n        /** @type {*} */\n        const { filename } = req.query\n        const p = path.resolve(__dirname, BINARY_DIR, filename)\n\n        fs.unlinkSync(p)\n        res.sendStatus(201)\n      })\n    }\n  }\n}\n```\n\n## Web browser in use\n\nCurrently, this app doesn't bundle a web browser. Instead, it uses Chrome DevTools Protocol; therefore, either Chrome or Chromium must be installed.\n\nSee [/deps.md](/deps.md).\n\n## Security concerns\n\nI learnt this from [pywebview](https://pywebview.flowrl.com/guide/security.html). A major thing about this, is [CSRF attack](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)).\n\n## Customization\n\nPlease see [/config/types.go](/config/types.go). The easiest way is to create `/config.yaml` alongside the built `webview-server*`.\n\n## Building\n\nYou can also build for your platform, or multiple platforms at once -- take a peek inside [robo.yml](/robo.yml)\n\nNote that executables in macOS can also run in windowed mode (no console), by renaming the extension to `*.app`. No need to make a folder of `*.app/`.\n\nI cannot upload `*.app` directly to GitHub Releases.\n\n[`darwin`](https://en.wikipedia.org/wiki/Darwin_%28operating_system%29) binaries can used for macOS, although not built natively on macOS.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpatarapolw%2Fwebview-server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpatarapolw%2Fwebview-server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpatarapolw%2Fwebview-server/lists"}