{"id":26870857,"url":"https://github.com/mrhdias/fastkiss","last_synced_at":"2025-05-07T06:29:04.760Z","repository":{"id":67933422,"uuid":"299105253","full_name":"mrhdias/fastkiss","owner":"mrhdias","description":"FastKISS - Nim's FastCGI Flexible Web Framework","archived":false,"fork":false,"pushed_at":"2024-02-23T22:02:06.000Z","size":4388,"stargazers_count":16,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-31T07:17:26.230Z","etag":null,"topics":["fastcgi","nim-lang","web"],"latest_commit_sha":null,"homepage":"","language":"Nim","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/mrhdias.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}},"created_at":"2020-09-27T19:36:18.000Z","updated_at":"2025-03-30T01:49:40.000Z","dependencies_parsed_at":null,"dependency_job_id":"8a5a2aef-8dd8-4b35-b06f-0486bf14ebf0","html_url":"https://github.com/mrhdias/fastkiss","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/mrhdias%2Ffastkiss","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mrhdias%2Ffastkiss/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mrhdias%2Ffastkiss/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mrhdias%2Ffastkiss/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mrhdias","download_url":"https://codeload.github.com/mrhdias/fastkiss/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252826408,"owners_count":21810107,"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":["fastcgi","nim-lang","web"],"created_at":"2025-03-31T07:17:30.022Z","updated_at":"2025-05-07T06:29:04.729Z","avatar_url":"https://github.com/mrhdias.png","language":"Nim","funding_links":[],"categories":[],"sub_categories":[],"readme":"# FastKISS - A FastCGI Web Framework for Nim\n⚠️ WARNING: This framework is still in heavy development. ⚠️\n\n**Fast** \u0026 **K**eep **I**t **S**mall and **S**imple is an FastCGI Host/Server Framework for [Nim](https://www.nim-lang.org) Web Applications. It was developed against Nginx, but should work with any web server that implements the FCGI spec. This work was based on the [FastCGI library for Nim](https://github.com/ba0f3/fastcgi.nim).\n\nThe FastCGI server allows you to easily integrate your FastKiss web application into a standard web server environment, taking advantage of existing features provided by a web server developed for this purpose. This allows you to use all the state of the art features such as advanced protocol support (HTTPS, HTTP/2.0), HTTP keep-alive, high performance static file delivery, HTTP compression, or URL redirect/rewrite services without increases the overhead and complexity of building anything into your application code.\n```nim\nimport fastkiss\nfrom fastkiss/utils import decodeData\nimport regex\nfrom strformat import `\u0026`\n\nproc main() =\n  let app = newApp()\n  app.config.port = 9000 # optional if default port\n\n  app.get(\"/\", proc (req: Request) {.async.} =\n    respond \"Hello World!\"\n  )\n\n  app.get(r\"/test/(\\w+)\".re, proc (req: Request) {.async.} =\n    respond \u0026\"Hello {req.matches.groupCaptures(0)[0]}\"\n  )\n\n  # http://example:8080/test/abc-012/def-345/test/xpto\n  app.get(r\"/test/(?:([a-z\\d]+-[a-z\\d]+)/)+test/(\\w+)\".re, proc (req: Request) {.async.} =\n    respond \u0026\"Hello Multi Capture {$req.matches.groupCaptures(0)} and {$req.matches.groupCaptures(1)}\"\n  )\n\n  # http://example:8080/myquery?a=1\u0026b=2\u0026c=3\n  app.get(\"/myquery\", proc (req: Request) {.async.} =\n    resp \"My Query:\\n\"\n    for k, v in decodeData(req.url.query):\n      resp \u0026\"{k} = {v}\\n\"\n  )\n\n  app.match([\"GET\", \"POST\"], \"/method\", proc (req: Request) {.async.} =\n    respond \u0026\"Hello Method {$req.reqMethod}\"\n  )\n\n  app.get(\"/static\", proc (req: Request) {.async.} =\n    sendFile \"./test.txt\"\n  )\n\n  app.run()\n\nmain()\n```\nIf you are using FastKiss to generate dynamic content of significant size, such as large binary images or large text-based datasets, then you need to consider the use of \"**resp**\" function instead of \"**respond**\" to minimize the memory footprint and preserve scalability.\n\nUsing \"**resp**\" function allows FastKiss to return chunks of data back to the client without the need to build an entire structure, or resource in-memory. See [example](https://github.com/mrhdias/fastkiss/blob/master/examples/loadimage.nim). You can use the \"**resp**\" function like the php \"echo\" function. You can even include files with code in the same way as you do with a php. See this [example](https://github.com/mrhdias/fastkiss/tree/master/examples/basicwebsite).\n```nim\nimport fastkiss\nimport tables\nfrom strformat import `\u0026`\n\nproc showPage(req: Request) {.async.} =\n\n  let t = {1: \"one\", 2: \"two\", 3: \"three\"}.toTable\n\n  \"\"\"\u003c!DOCTYPE html\u003e\n  \u003chtml lang=\"en\"\u003e\n    \u003chead\u003e\n      \u003cmeta charset=\"utf-8\"\u003e\n      \u003cmeta name=\"viewport\" content=\"width=device-width\"\u003e\n      \u003ctitle\u003eTest\u003c/title\u003e\n    \u003c/head\u003e\n    \u003cbody\u003e\n      \u003ctable\u003e\"\"\".resp\n\n  for k, v in pairs(t):\n    resp \u0026\"\"\"\u003ctr\u003e\n        \u003ctd\u003e\u003cstrong\u003e{k}\u003c/strong\u003e\u003c/td\u003e\n        \u003ctd\u003e{v}\u003c/td\u003e\n      \u003c/tr\u003e\n    \"\"\"\n\n  \"\"\"\u003c/table\u003e\n    \u003c/body\u003e\n  \u003c/html\u003e\"\"\".resp\n\nproc main() =\n  let app = newApp()\n  app.get(\"/\", showPage)\n  app.run()\n\nmain()\n```\nHere's a complete [example](https://github.com/mrhdias/fastkiss/blob/master/examples/sendmymail.nim) of an app to send emails with attachments.\n\n![Send Mail Example](https://raw.githubusercontent.com/mrhdias/fastkiss/master/examples/sendmymail.jpg)\n\nNGINX FastCGI Configuration File Example\n```\nserver {\n  listen  8080;\n  server_name example;\n  # add example to hosts file\n  # nano -w /etc/hosts\n  #\n  # 127.0.0.1   example\n  #\n\n  location / {\n    # Comment this line if you if you don't need http cookies\n    fastcgi_param HTTP_COOKIE $http_cookie;\n    # Comment this line if you if you don't need Basic Autentication\n    fastcgi_param HTTP_AUTHORIZATION $http_authorization;\n    # Uses REMOTE_ADDR value whenever it needs to deal with visitor IP address.\n    fastcgi_param REMOTE_ADDR $http_x_real_ip;\n\n    client_max_body_size 1000M;\n    include fastcgi_params;\n    fastcgi_pass 127.0.0.1:9000;\n  }\n}\n```\nAPACHE2 FastCGI Configuration File Example\n```\nListen 127.0.0.1:8080\nLoadModule proxy_module modules/mod_proxy.so\nLoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so\nLoadModule rewrite_module modules/mod_rewrite.so\n# Need a server with SSL support\n# LoadModule http2_module modules/mod_http2.so\n\n\u003cIfModule mod_proxy_fcgi.c\u003e\n\u003cVirtualHost *:8080\u003e\n  ServerName example\n  ServerAlias anotherexample\n  ServerAdmin admin@example.tld\n\n  ErrorLog /var/log/httpd/example_error.log\n  CustomLog /var/log/httpd/example_requests.log combined\n\n  ProxyPass \"/\" \"fcgi://localhost:9000/\"\n\n  # https://httpd.apache.org/docs/2.4/custom-error.html\n  ErrorDocument 503 \"Service Temporary Unavailable\"\n\n  # Need a server with SSL support\n  # Protocols h2 http/1.1\n\n  # Comment this two lines below if you if you don't need Basic Autentication\n  RewriteEngine on\n  RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]\n\u003c/VirtualHost\u003e\n\u003c/IfModule\u003e\n```\nTest\n```\n$ nimble install https://github.com/mrhdias/fastkiss\n$ nano -w example.nim\n$ nim c -r example.nim\n$ sudo systemctl start nginx / httpd\n$ wget -qO- http://example:8080/test\nHello World!!⏎\n```\nTo compile a release version use:\n```\n$ nim c -d:release example.nim\n$ ./example\n```\n\n### Configuration Options\n```nim\nconfig.port = 9000 # Default Port\nconfig.address = \"\"\nconfig.reuseAddr = true # Default value\nconfig.reusePort = false # Default value\n\n# Default temporary directory of the current user to save temporary files\nconfig.tmpUploadDir = getTempDir()\n# The value true will cause the temporary files left after request processing to be removed.\nconfig.autoCleanTmpUploadDir = true\n# To serve static files such as images, CSS files, and JavaScript files\nconfig.staticDir = \"\"\n# Sets the maximum allowed size of the client request body\nconfig.maxBody = 8388608 # Default 8MB = 8388608 Bytes\n```\n\n### Available Router Methods\nRoutes that respond to any HTTP verb\n```nim\nget*(\n  server: AsyncFCGIServer,\n  pattern: string | Regex,\n  callback: proc (request: Request): Future[void] {.closure, gcsafe.}\n)\n\npost*(\n  server: AsyncFCGIServer,\n  pattern: string | Regex,\n  callback: proc (request: Request): Future[void] {.closure, gcsafe.}\n)\n\nput*(\n  server: AsyncFCGIServer,\n  pattern: string | Regex,\n  callback: proc (request: Request): Future[void] {.closure, gcsafe.}\n)\n\npatch*(\n  server: AsyncFCGIServer,\n  pattern: string | Regex,\n  callback: proc (request: Request): Future[void] {.closure, gcsafe.}\n)\n\ndelete*(\n  server: AsyncFCGIServer,\n  pattern: string | Regex,\n  callback: proc (request: Request): Future[void] {.closure, gcsafe.}\n)\n\noptions*(\n  server: AsyncFCGIServer,\n  pattern: string | Regex,\n  callback: proc (request: Request): Future[void] {.closure, gcsafe.}\n)\n```\n\nRoute that responds to multiple HTTP verbs\n```nim\nmatch*(\n  server: AsyncFCGIServer,\n  methods: openArray[string],\n  pattern: string | Regex,\n  callback: proc (request: Request): Future[void] {.closure, gcsafe.}\n)\n```\n\nRoute that responds to all HTTP verbs\n```nim\nany*(\n  server: AsyncFCGIServer,\n  pattern: string | Regex,\n  callback: proc (request: Request): Future[void] {.closure, gcsafe.}\n)\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmrhdias%2Ffastkiss","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmrhdias%2Ffastkiss","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmrhdias%2Ffastkiss/lists"}