{"id":1993,"url":"https://github.com/ApacheExpress/ApacheExpress","last_synced_at":"2025-07-31T12:33:23.147Z","repository":{"id":215156350,"uuid":"80063377","full_name":"ApacheExpress/ApacheExpress","owner":"ApacheExpress","description":"Reliable Server Side Swift ✭ Make Apache great again!","archived":false,"fork":false,"pushed_at":"2022-05-08T14:14:34.000Z","size":621,"stargazers_count":174,"open_issues_count":0,"forks_count":4,"subscribers_count":6,"default_branch":"develop","last_synced_at":"2024-08-15T00:19:50.942Z","etag":null,"topics":["apache2","express","mod-swift","mustache","swift"],"latest_commit_sha":null,"homepage":"http://apacheexpress.io/","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ApacheExpress.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}},"created_at":"2017-01-25T22:17:20.000Z","updated_at":"2024-01-04T16:10:51.000Z","dependencies_parsed_at":"2024-01-05T20:18:40.955Z","dependency_job_id":null,"html_url":"https://github.com/ApacheExpress/ApacheExpress","commit_stats":null,"previous_names":["apacheexpress/apacheexpress"],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ApacheExpress%2FApacheExpress","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ApacheExpress%2FApacheExpress/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ApacheExpress%2FApacheExpress/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ApacheExpress%2FApacheExpress/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ApacheExpress","download_url":"https://codeload.github.com/ApacheExpress/ApacheExpress/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228248409,"owners_count":17891447,"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":["apache2","express","mod-swift","mustache","swift"],"created_at":"2024-01-05T20:16:00.725Z","updated_at":"2024-12-05T06:31:18.444Z","avatar_url":"https://github.com/ApacheExpress.png","language":"Swift","funding_links":[],"categories":["Server"],"sub_categories":["Keychain","Other free courses"],"readme":"\u003ch2\u003emod_swift\n  \u003cimg src=\"http://zeezide.com/img/mod_swift.svg\"\n       align=\"right\" width=\"128\" height=\"128\" /\u003e\n\u003c/h2\u003e\n\n![Apache 2](https://img.shields.io/badge/apache-2-yellow.svg)\n![Swift](https://img.shields.io/badge/swift-blue.svg)\n![macOS](https://img.shields.io/badge/os-macOS-green.svg?style=flat)\n![tuxOS](https://img.shields.io/badge/os-tuxOS-green.svg?style=flat)\n![Raspiberry Pi](https://img.shields.io/badge/works%20on-Raspberry%20Pi-CA0B3D.svg?style=flat)\n\nThis is a technology demo which shows how to write native modules\nfor the\n[Apache Web Server](https://httpd.apache.org)\nin the \n[Swift](http://swift.org/)\nprogramming language.\nThe demo includes a \n[C module to load Swift modules](mod_swift/README.md),\na [basic demo module](mods_baredemo/README.md),\nthe [ApacheExpress](ApacheExpress/README.md) framework which provides an Express \nlike API for mod_swift,\na [demo for ApacheExpress](mods_expressdemo/README.md),\na [Todo MVC](mods_todomvc/README.md) backend (w/ CalDAV support!),\nand a few supporting libraries\n(such as Freddy or Noze.io [Mustache](ThirdParty/mustache/README.md)).\n\n**Server Side Swift the [right](http://www.alwaysrightinstitute.com/) way**.\nInstead of reinventing the HTTP server, hook into something that just works\nand is battle proven. \nAnd comes with HTTP/2 as well as TLS support out of the box 🤓\n(If you don't care, [Noze.io](http://noze.io) might be something for you.)\n\nNote: [mod_swift](https://mod-swift.org/) is now available as a separate,\n      self-contained project.\n\n\n### What is an Apache module?\n\nWell, Apache is a highly modular and efficient server framework. The httpd\ndaemon itself is quite tiny and pretty much all webserver functionality is\nactually implemented in the form of\n[modules](https://httpd.apache.org/docs/2.4/mod/).\nBe it thread handling, access control, mime detection or content negotation -\nall of that is implemented as modules. And can be replaced by own modules!\n\nThe Apache core modules are written in portable C. Some modules are built\nright into the server, but most are loaded as\n[dynamic libraries](https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/DynamicLibraries/000-Introduction/Introduction.html).\nWhich ones is specified by the user in the\n[configuration file](https://httpd.apache.org/docs/2.4/configuring.html), e.g.:\n\n    LoadModule authz_core_module /usr/libexec/apache2/mod_authz_core.so\n    LoadModule mime_module       /usr/libexec/apache2/mod_mime.so\n\nNow with **mod_swift** you can write such modules using the\n[Swift](http://swift.org/)\nprogramming language. Enter:\n\n    LoadSwiftModule ApacheMain /usr/libexec/apache2/mods_demo.so\n\nThis is a little different to something like `mod_php` which enables Apache\nto directly interpret PHP scripts. `mod_php` itself is C software and a single\nmodule.\nSince Swift compiles down to regular executable binaries,\nand because Swift has excellent \n[C integration](https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithCAPIs.html#//apple_ref/doc/uid/TP40014216-CH8-ID17),\nyou can write arbitrary modules with **mod_swift** which behave just like the\nregular C modules.\n\n### This is boring, show us something!\n\nOK, ok.\nSo in short with **mod_swift** you can extend Apache in many many ways,\nor just write dynamic HTTP endpoints,\nbe it dynamically generated web pages or web services.\nThere is no interpreter or JVM or proxy, the compiled Swift code runs directly\nas part of Apache - a.k.a. superfast.\nHere is your screenshot:\n\n\u003cimg src=\"DocRoot/mod_swift-mustache-screenshot.jpg\" align=\"center\" /\u003e\n\nand here is some code used to generate that page (shortened,\n[full](Sources/mods_demo/MustacheHandler.swift)):\n\n```Swift\nlet sampleDict  : [ String : Any ] = [\n  \"name\"        : \"Chris\",\n  \"value\"       : 10000,\n  \"taxed_value\" : Int(10000 - (10000 * 0.4))\n]\n\nfunc MustacheHandler(p: UnsafeMutablePointer\u003crequest_rec\u003e?) -\u003e Int32 {\n  var req = ZzApacheRequest(raw: p!) // make it nicer to use\n  guard req.handler == \"de.zeezide.mustache\" else { return DECLINED }\n  \n  req.contentType = \"text/html; charset=ascii\"\n  guard let fn = req.filename else { return HTTP_NOT_FOUND }\n  \n  guard let template = try? String(contentsOfFile: fn) else {\n    return HTTP_INTERNAL_SERVER_ERROR\n  }\n  req.puts(MustacheParser().parse(string: template).render(object: sampleDict))\n  return OK\n}\n```\n\nWhat this does is it loads a\n[Mustache](http://mustache.github.io)\ntemplate \n[located in the Apache documents directory](DocRoot/HelloWorld.mustache).\nIt then resolves the template from some Swift dictionary and returns the result\nto the browser.\nNote that the file lookup and all that is managed by other Apache modules,\nthis handler is just invoked for Mustache templates\n([as configured in our apache.conf](apache.conf#L44)).\n\nRemember that this is just a proof of concept. Quite likely you'd want some\nwrapper library making the Apache API a little 'Swiftier'.\nAlso remember that you can use this not only to deliver dynamic content,\nbut you can also use it to add new authentication modules to Apache,\nor write new filter modules (say one which converts XML to JSON on demand).\n\n\n### Know what? This looks awkwardly difficult ...\n\nFair enough. So we integrated a tiny subset of \n[Noze.io](http://noze.io/)\nto allow you to do just that. This is what it looks like:\n\n```Swift\nfunc expressMain() {\n  apache.onRequest { req, res in\n    res.writeHead(200, [ \"Content-Type\": \"text/html\" ])\n    try res.end(\"\u003ch1\u003eHello World\u003c/h1\u003e\")\n  }\n}\n```\n\nAnd is configured like this in the Apache conf:\n\n    \u003cLocationMatch /express/*\u003e\n      SetHandler de.zeezide.ApacheExpress\n    \u003c/LocationMatch\u003e\n\nNow you are saying, this is all nice and pretty. But what about Connect?\nI want to write and reuse middleware!\nHere you go:\n\n```Swift\nfunc expressMain() {\n  let app = apache.connect()\n  \n  app.use { req, res, next in\n    console.info(\"Request is passing Connect middleware ...\")\n    res.setHeader(\"Content-Type\", \"text/html; charset=utf-8\")\n    // Note: we do not close the request, we continue with the next middleware\n    try next()\n  }\n  \n  app.use(\"/express/connect\") { req, res, next in\n    try res.write(\"\u003cp\u003eThis is a random cow:\u003c/p\u003e\u003cpre\u003e\")\n    try res.write(vaca())\n    try res.write(\"\u003c/pre\u003e\")\n    res.end()\n  }\n}\n```\n\nAnd Express? Sure, the Apache Express is about to leave:\n```Swift\nlet app = apache.express(cookieParser(), session())\n\napp.get(\"/express/cookies\") { req, res, _ in\n  // returns all cookies as JSON\n  try res.json(req.cookies)\n}\n\napp.get(\"/express/\") { req, res, _ in\n  let tagline = arc4random_uniform(UInt32(taglines.count))\n  \n  let values : [ String : Any ] = [\n    \"tagline\"     : taglines[Int(tagline)],\n    \"viewCount\"   : req.session[\"viewCount\"] ?? 0,\n    \"cowOfTheDay\" : cows.vaca()\n  ]\n  try res.render(\"index\", values)\n}\n```\n\nYes. All that is running within Apache.\nThe working example can be found here:\n[ExpressMain.swift](mods_expressdemo/Sources/ExpressMain.swift#L9).\nThe [TodoMVC](mods_todomvc/Sources/TodoMVCMain.swift) is pretty neat too\n(and comes with a demo CalDAV/CardDAV implementation).\n\n\n### And how do I access MySQL/PostgreSQL/SQLite3?\n\nFunny that you ask. A feature of Apache 2 known to few is\n[mod_dbd](https://httpd.apache.org/docs/2.4/mod/mod_dbd.html).\nUsing that you can configure a database connection within the Apache.conf and\nuse that within all your Apache modules/handlers.\nIt does all the pooling and maintenance required. Like so:\n\n    \u003cIfModule dbd_module\u003e\n      DBDriver  sqlite3\n      DBDParams \"/var/data/testdb.sqlite3\"\n    \u003c/IfModule\u003e\n\nWell, and as part of \n[mods_baredemo](mods_baredemo/Sources/DatabaseHandler.swift)\nwe provide an example on how to use this. It looks like this:\n```swift\nguard let con = req.dbdAcquire()                 else { return ... }\nguard let res = con.select(\"SELECT * FROM pets\") else { return ... }\n\nwhile let row = res.next() {\n  req.puts(\"\u003cli\u003e\\(row[0])\u003c/li\u003e\")\n}\n```\n\nBoth macOS Apache installations (system and Homebrew) include the SQLite3\ndriver, so we included a demo database in the `data` directory.\nOn Linux you need to install the drivers you want\n(`sudo apt-get install libaprutil1-dbd-sqlite3 libaprutil1-dbd-pgsql`).\n\u003cbr /\u003e\nA little more work: Next you need to load `mod_dbd` in the proper\n[apache.conf](apache.conf#L73)\nand\nspecify the absolute path to the `data/testdb.sqlite3` database (the path where\nyou checked out **mod_swift**).\n\u003cbr /\u003e\nIf you got that right, restart Apache and\n[http://localhost:8042/database/](http://localhost:8042/database/)\nshould be able to successfully query stuff.\n\n\n### This is wicked! How can I try it?\n\nEasy! Just clone this repository, make and run it:\n\n    git clone https://github.com/AlwaysRightInstitute/mod_swift.git\n    cd mod_swift\n    make run\n\nThen open [http://localhost:8042/](http://localhost:8042/) and voilà,\nyou should see a webpage delivered by Apache.\n\nIt works out of the box on macOS 10.11+ with Xcode 8 \nand the builtin system Apache (no Apache install required!),\nwith the Homebrew Apache 2.4 on macOS (`brew install homebrew/apache/httpd24`),\nand on Linux (tested with Ubuntu 16.04).\n \nOn Linux you need to hack `/usr/include/apr-1.0/apr.h` and add a\n`typedef int pid_t;` just below the MingW section to make swiftc behave.\n\nTo explore and hack the code, just open the `UseMe.xcworkspace`.\nYou can run everything directly from within Xcode.\n\nDon't be afraid, the Apache invoked here doesn't interfere with your system\nApache at all (but uses it, Apache is part of all macOS installs).\nIt uses the [apache.conf](apache.conf) included in this repo,\nruns against the [DocRoot](DocRoot/) included in this repo\nand loads the libraries from the Xcode build dir (hardcoded to SRCROOT/.libs).\n\nYou want an intro into Apache module programming?\nTry this: [Developing modules for the Apache HTTP Server 2.4](https://httpd.apache.org/docs/2.4/developer/modguide.html).\n\n### Various Notes of Interest\n\n- The code is \n  [properly formatted](http://www.alwaysrightinstitute.com/swifter-space/),\n  max width 80 chars, 2-space indent.\n- ApacheExpress is just code copy/pasted in from Noze.io. It may very well be\n  non-sensical in the context of Apache :-)\n- This doesn't use `apxs` because that is badly b0rked on both 10.11 and 10.12.\n- It uses a lot of hardcoded load and lookup pathes, remember, it is a demo!\n- It has some leaks and issues, e.g. modules are not properly unloaded.\n- Sure, you can link against arbitrary Swift dylibs, \n  [mustache](Sources/mustache/) is an example for exactly that.\n- However, you currently cannot use the Swift Package Manager to create\n  dylibs (AFAIK). So while in theory that would work, you need to do the\n  final linking step separately.\n- Yes `mod_swift` itself could be avoided by including the .c in the Swift\n  module. Yes, you can even statically link Swift including its runtime. Let\n  me know if this is interesting, I have a branch which does exactly that.\n- There is one big bet in the code: Officially there is no way to invoke a\n  Swift function from C, only the other way around!\n  In other words: it is pure luck that \n  [this works](Sources/mod_swift/mod_swift.c#L47) and is ABI compatible with C.\n- If you would want to debug the stuff in Xcode - `/usr/sbin/httpd` is under\n  [macOS SIP](https://support.apple.com/en-us/HT204899).\n- On macOS 10.11 starting Apache with -X crashes a few seconds after the last\n  request was received. Maybe just SIGPIPE or sth. 10.12 looks fine.\n- Unloading is an issue. I think the Apple and GNUstep Objective-C\n  runtimes cannot be properly unloaded (I've heard there is a great runtime\n  that can).\n  No idea what the situation with 'pure Swift' is.\n- Would be cool if Swift 4 would get a proper `extern C {}`.\n- Yes, Apache content handlers are not [Noze.io](http://noze.io/) like \n  asynchronous but run in a traditional, synchronous thread-setup.\n- Apache varargs funcs are not available since Swift doesn't support such. We\n  provide a wrapper for `ap_log_rerror_`, other funcs would need to be wrapped\n  the same way.\n- Apache also uses quite a few `#define`s, e.g. `ap_fwrite`\n- The Apache C headers are prone to crash `swiftc`. Which is why we wrap the\n  Apache `request_rec` in an additional struct.\n\n              (__)\n            /  .\\/.     ______\n           |  /\\_|     |      \\\n           |  |___     |       |\n           |   ---@    |_______|\n        *  |  |   ----   |    |\n         \\ |  |_____\n          \\|________|\n    [CompuCow Discovers Bug in Compiler](http://zeezide.com/en/products/codecows/index.html)\n\nOh, ages ago I did\n[mod_objc](https://github.com/AlwaysRightInstitute/mod_objc1)\nfor Apache 1.3.\n\n### Status\n\n- 2022-05-08:\n  - This is an outdated demo. Things like `mod_swift` are now living in their\n    own packages (and mod_swift is in a working state).\n- 2017:\n  - This is a demo. Do not use it for realz.\n\n### Who\n\n**mod_swift** is brought to you by\n[The Always Right Institute](http://www.alwaysrightinstitute.com)\nand\n[ZeeZide](http://zeezide.de).\nWe like feedback, GitHub stars, cool contract work,\npresumably any form of praise you can think of.\nWe don't like people who are wrong.\n\nThere is a `#mod_swift` channel on the [Noze.io Slack](http://slack.noze.io).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FApacheExpress%2FApacheExpress","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FApacheExpress%2FApacheExpress","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FApacheExpress%2FApacheExpress/lists"}