{"id":16367318,"url":"https://github.com/medz/spry","last_synced_at":"2026-04-01T20:43:46.953Z","repository":{"id":65120890,"uuid":"581144782","full_name":"medz/spry","owner":"medz","description":"Spry - A HTTP middleware framework for Dart to make web applications and APIs server more enjoyable to write.","archived":false,"fork":false,"pushed_at":"2024-04-30T16:46:48.000Z","size":2493,"stargazers_count":27,"open_issues_count":0,"forks_count":3,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-05-01T14:14:58.348Z","etag":null,"topics":["dart","freamework","http","middleware","router","server","spry","web"],"latest_commit_sha":null,"homepage":"https://spry.fun","language":"Dart","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/medz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","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},"funding":{"github":"medz","open_collective":"openodroe"}},"created_at":"2022-12-22T11:47:19.000Z","updated_at":"2024-05-03T17:03:49.099Z","dependencies_parsed_at":"2023-09-24T03:48:00.318Z","dependency_job_id":"4dba19f3-f9e3-48a7-9ed4-f96bd8c3e2d4","html_url":"https://github.com/medz/spry","commit_stats":{"total_commits":471,"total_committers":8,"mean_commits":58.875,"dds":0.227176220806794,"last_synced_commit":"b84d7815c52e8d2e367c8028b5e3db8f544c09dc"},"previous_names":["medz/spry","odroe/spry"],"tags_count":42,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/medz%2Fspry","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/medz%2Fspry/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/medz%2Fspry/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/medz%2Fspry/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/medz","download_url":"https://codeload.github.com/medz/spry/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243624072,"owners_count":20321028,"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":["dart","freamework","http","middleware","router","server","spry","web"],"created_at":"2024-10-11T02:49:37.051Z","updated_at":"2026-04-01T20:43:46.946Z","avatar_url":"https://github.com/medz.png","language":"Dart","readme":"# Spry\n\n[![Test](https://github.com/medz/spry/actions/workflows/test.yml/badge.svg)](https://github.com/medz/spry/actions/workflows/test.yml)\n[![Pub Version](https://img.shields.io/pub/v/spry.svg)](https://pub.dev/packages/spry)\n[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/medz/spry/blob/main/LICENSE)\n[![X (twitter)](https://img.shields.io/badge/twitter-%40shiweidu-blue.svg)](https://twitter.com/shiweidu)\n[![Documentation](https://img.shields.io/badge/docs-spry.medz.dev-brightgreen.svg)](https://spry.medz.dev/)\n[![Netlify Status](https://api.netlify.com/api/v1/badges/186bd6a9-4783-4e3a-ad88-42259d67c8a5/deploy-status)](https://app.netlify.com/projects/dart-spry/deploys)\n\nNext-generation Dart server framework. Build modern servers and deploy them to the runtime you prefer.\n\n## Quick Start\n\nInstall the package:\n\n```bash\ndart pub add spry\n```\n\nCreate a minimal project structure:\n\n```text\n.\n├─ routes/\n│  └─ index.dart\n└─ spry.config.dart\n```\n\n`spry.config.dart`\n\n```dart\nimport 'package:spry/config.dart';\n\nvoid main() {\n  defineSpryConfig(\n    host: '127.0.0.1',\n    port: 4000,\n    target: BuildTarget.vm,\n  );\n}\n```\n\n`routes/index.dart`\n\n```dart\nimport 'package:spry/spry.dart';\n\nResponse handler(Event event) {\n  return Response.json({\n    'message': 'hello from spry',\n    'runtime': event.context.runtime.name,\n    'path': event.url.path,\n  });\n}\n```\n\nStart the dev server:\n\n```bash\ndart run spry serve\n```\n\n## Core Ideas\n\n- `routes/` defines request handlers with file routing\n- `middleware/` and `_middleware.dart` shape cross-cutting request behavior\n- `_error.dart` provides scoped error handling\n- `defineHandler(...)` adds handler-local middleware and error handling\n- `public/` serves static assets directly\n- `spry.config.dart` selects the runtime target and build behavior\n\n## OpenAPI\n\nSpry can generate an `openapi.json` document as part of the normal build\npipeline.\n\nUse `package:spry/config.dart` for the build-side config and\n`package:spry/openapi.dart` for the document objects:\n\n```dart\nimport 'package:spry/config.dart';\nimport 'package:spry/openapi.dart';\n\nvoid main() {\n  defineSpryConfig(\n    openapi: OpenAPIConfig(\n      document: OpenAPIDocumentConfig(\n        info: OpenAPIInfo(title: 'Spry API', version: '1.0.0'),\n      ),\n      output: OpenAPIOutput.route('openapi.json'),\n    ),\n  );\n}\n```\n\nRoute files can expose top-level `openapi` metadata:\n\n```dart\nimport 'package:spry/openapi.dart';\n\nfinal openapi = OpenAPI(\n  summary: 'List users',\n  tags: ['users'],\n);\n```\n\nKey rules:\n\n- `OpenAPIConfig.document.components` defines document-level components.\n- Route-level `OpenAPI(..., globalComponents: ...)` is lifted into document\n  `components` during generation.\n- A route without a method suffix expands to `GET`, `POST`, `PUT`, `PATCH`,\n  `DELETE`, and `OPTIONS` in OpenAPI.\n- `HEAD` is only emitted when a route explicitly defines `.head.dart`.\n- `OpenAPIOutput.route('openapi.json')` writes the file into `public/`, so it is\n  served like any other static asset.\n\n## Runtime Targets\n\nSpry can emit output for:\n\n| Target | Runtime | Deploy Docs |\n|---|---|---|\n| `vm` | Dart VM | [Dart VM](https://spry.medz.dev/deploy/dart) |\n| `exe` | Native executable | [Native executable](https://spry.medz.dev/deploy/dart#native-executable) |\n| `aot` | AOT snapshot | [AOT snapshot](https://spry.medz.dev/deploy/dart#aot-snapshot) |\n| `jit` | JIT snapshot | [JIT snapshot](https://spry.medz.dev/deploy/dart#jit-snapshot) |\n| `kernel` | Kernel snapshot | [Kernel snapshot](https://spry.medz.dev/deploy/dart#kernel-snapshot) |\n| `node` | Node.js | [Node.js](https://spry.medz.dev/deploy/node) |\n| `bun` | Bun | [Bun](https://spry.medz.dev/deploy/bun) |\n| `deno` | Deno | [Deno](https://spry.medz.dev/deploy/deno) |\n| `cloudflare` | Cloudflare Workers | [Cloudflare Workers](https://spry.medz.dev/deploy/cloudflare) |\n| `vercel` | Vercel | [Vercel](https://spry.medz.dev/deploy/vercel) |\n| `netlify` | Netlify Functions | [Netlify Functions](https://spry.medz.dev/deploy/netlify) |\n\n## WebSockets\n\nSpry exposes websocket upgrades from the request event without introducing a\nsecond routing system.\n\n```dart\nimport 'package:spry/spry.dart';\nimport 'package:spry/websocket.dart';\n\nResponse handler(Event event) {\n  if (!event.ws.isSupported || !event.ws.isUpgradeRequest) {\n    return Response('plain http fallback');\n  }\n\n  return event.ws.upgrade((ws) async {\n    ws.sendText('connected');\n\n    await for (final message in ws.events) {\n      switch (message) {\n        case TextDataReceived(text: final text):\n          ws.sendText('echo:$text');\n        case BinaryDataReceived():\n        case CloseReceived():\n          break;\n      }\n    }\n  }, protocol: 'chat');\n}\n```\n\nCurrent websocket support follows the underlying `osrv` runtime surface:\n\n- supported: Dart VM, Node.js, Bun, Deno, Cloudflare Workers\n- unsupported: Vercel, current Netlify Functions runtime\n\n## Documentation\n\n[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/medz/spry)\n\nRead the documentation at [spry.medz.dev](https://spry.medz.dev/).\n\nStart here:\n\n- [Getting Started](https://spry.medz.dev/getting-started)\n- [File Routing](https://spry.medz.dev/guide/routing)\n- [Configuration](https://spry.medz.dev/config)\n- [Deploy Overview](https://spry.medz.dev/deploy/)\n\n## License\n\n[MIT](https://github.com/medz/spry/blob/main/LICENSE)\n\n## Sponsors\n\nSpry framework is an [MIT licensed](https://github.com/medz/spry/blob/main/LICENSE) open source project with its ongoing development made possible entirely by the support of these awesome backers. If you'd like to join them, please consider [sponsoring Seven(@medz)](https://github.com/sponsors/medz) development.\n\n\u003cp align=\"center\"\u003e\n  \u003ca target=\"_blank\" href=\"https://github.com/sponsors/medz#:~:text=Featured-,sponsors,-Current%20sponsors\"\u003e\n    \u003cimg alt=\"sponsors\" src=\"https://cdn.jsdelivr.net/gh/medz/public/sponsors.tiers.svg\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n## Contributing\n\nThank you to all the people who already contributed to Spry!\n\n[![Contributors](https://contrib.rocks/image?repo=medz/spry)](https://github.com/medz/spry/graphs/contributors)\n","funding_links":["https://github.com/sponsors/medz","https://opencollective.com/openodroe"],"categories":["Dart"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmedz%2Fspry","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmedz%2Fspry","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmedz%2Fspry/lists"}