{"id":15043719,"url":"https://github.com/joshgontijo/snappy","last_synced_at":"2026-02-19T04:32:24.245Z","repository":{"id":18991181,"uuid":"85755310","full_name":"joshgontijo/snappy","owner":"joshgontijo","description":"A tiny and powerful Java 8 server","archived":false,"fork":false,"pushed_at":"2022-08-18T19:05:01.000Z","size":3619,"stargazers_count":0,"open_issues_count":11,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-10-11T13:34:55.401Z","etag":null,"topics":["java-8","lambda","rest-server","server-sent-events","undertow","web-framework","web-server","websockets"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/joshgontijo.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}},"created_at":"2017-03-21T21:27:30.000Z","updated_at":"2020-08-10T15:29:11.000Z","dependencies_parsed_at":"2022-08-23T15:21:56.390Z","dependency_job_id":null,"html_url":"https://github.com/joshgontijo/snappy","commit_stats":null,"previous_names":["josueeduardo/snappy"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/joshgontijo/snappy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joshgontijo%2Fsnappy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joshgontijo%2Fsnappy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joshgontijo%2Fsnappy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joshgontijo%2Fsnappy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/joshgontijo","download_url":"https://codeload.github.com/joshgontijo/snappy/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joshgontijo%2Fsnappy/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29603074,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-19T04:01:40.476Z","status":"ssl_error","status_checked_at":"2026-02-19T04:01:12.960Z","response_time":117,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["java-8","lambda","rest-server","server-sent-events","undertow","web-framework","web-server","websockets"],"created_at":"2024-09-24T20:49:29.422Z","updated_at":"2026-02-19T04:32:24.220Z","avatar_url":"https://github.com/joshgontijo.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Snappy #\nA tiny and powerful web framework for Java 8\n\nFeatures:\n    \n- Based on [Undertow](http://undertow.io) handlers\n- Rest with content negotiation (media type only)\n- Server sent events\n- Server sent events client\n- Websockets\n- Websocket client\n- Built in simple service discovery\n- Small. ~6mb\n- No magic, plain and simple\n- Small memory footprint\n- Static files\n- Rest client\n- Multipart support\n- Executors and schedulers managed by the server\n- Extensible\n- Maven uber jar plugin using [Spring boot](https://projects.spring.io/spring-boot/)\n\n\n### Maven setup ###\n\n```xml\n    \u003cdependency\u003e\n        \u003cgroupId\u003eio.joshworks.snappy\u003c/groupId\u003e\n        \u003cartifactId\u003esnappy\u003c/artifactId\u003e\n        \u003cversion\u003e0.6.0\u003c/version\u003e\n    \u003c/dependency\u003e\n    \n```\n\n### Import ###\n```java\nimport static io.joshworks.snappy.SnappyServer.*;\nimport static io.joshworks.snappy.http.Response.*;\n```\n\n### Hello ###\n```java\npublic class App {\n\n    public static void main(final String[] args) {\n       get(\"/hello\", req -\u003e ok(\"Hello !\", \"txt\")); //or text/plain\n       start(); //9000\n    }\n}\n```\n\n### Path parameter ###\n```java\npublic class App {\n\n    public static void main(final String[] args) {\n       get(\"/hello/{name}\", req -\u003e ok(\"Hello \" + req.pathParameter(\"name\"), \"txt\"));\n       \n       start();\n    }\n}\n```\n\n### Receiving JSON ###\n```java\npublic class App {\n\n    public static void main(final String[] args) {\n       post(\"/users\", req -\u003e {\n           User user = req.body().asObject(User.class);\n           //..\n           return ok();\n       });\n       \n       start();\n    }\n}\n```\n\n### Sending JSON ###\n```java\npublic class App {\n\n    public static void main(final String[] args) {\n       get(\"/users\", req -\u003e ok(new User(\"John Doe\")));\n       start();\n    }\n}\n```\n\n### Filter ###\n```java\npublic class App {\n\n    public static void main(final String[] args) {\n        \n       beforeAll(\"/users\", req -\u003e System.out.println(\"A\")); \n       before(\"/users\", req -\u003e System.out.println(\"B\")); \n       after(\"/users\", (req, res) -\u003e System.out.println(\"C\")); \n       afterAll(\"/users\", (req, res) -\u003e System.out.println(\"D\")); \n       \n       get(\"/users\", req -\u003e {\n           System.out.println(\"Users\");\n            return ok();\n       });\n               \n       start();\n        \n        // Prints:\n        //A\n        //B\n        //Users\n        //C\n        //D\n    }\n}\n```\n\n### Error handling ###\n```java\npublic class App {\n\n    public static void main(final String[] args) {\n       \n       exception(Exception.class, (ex, req) -\u003e Response.internalServerError(ex));\n       \n       get(\"/users\", exchange -\u003e {\n           throw new RuntimeException(\"Some error\");\n       });\n\n       \n       start();\n    }\n}\n```\n\n### Serving static files ###\n```java\npublic class App {\n\n    public static void main(final String[] args) {\n        //from src/main/resources/static\n        //available on /pages\n        staticFiles(\"/pages\");\n        \n//        staticFiles(\"/pages\", \"someFolder\"); // src/main/resources/someFolder\n    }\n}\n```\n\n### Uploading file ###\n```java\npublic class App {\n\n    public static void main(final String[] args) {\n        post(\"/fileUpload\", req -\u003e {\n            Path theFile = req.multiPartBody(\"theFile\").file().path();\n            Files.copy(theFile, someOutputStream);\n        });\n    }\n}\n```\n\n### Broadcasting data with SSE ###\n```java\npublic class ClockServer {\n\n    public static void main(final String[] args) {\n            ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();\n\n            SseBroadcaster broadcaster =  sse(\"/clock\");\n            //curl http://localhost:9000/clock\n\n            onStart(() -\u003e scheduler.scheduleAtFixedRate(() -\u003e broadcaster.broadcast(new Date().toString()), 1, 1, TimeUnit.SECONDS));\n    \n            start();\n        }\n}\n```\n\n### SSE groups / topics ###\n```java\npublic class App {\n\n    public static void main(final String[] args) {\n        SseBroadcaster broadcaster = sse(\"/subscribe/{group}\", sse -\u003e {\n            sse.joinGroup(sse.pathParameter(\"group\"));\n        });\n\n        //curl http://localhost:9000/subscribe/group-a\n        //curl http://localhost:9000/subscribe/group-b\n\n        post(\"/publish/{group}\", req -\u003e {\n            String group = req.pathParameter(\"group\");\n            String message = req.body().asString();\n            broadcaster.broadcast(group, message);\n            return ok();\n        });\n    }\n}\n```\n\n### Registering a parser ###\n```java\npublic class App {\n\n    public static void main(final String[] args) {\n       Parsers.register(myXmlParser);\n       \n       get(\"/xml\", req -\u003e ok(\"\u003croot\u003e\u003c/root\u003e\"), produces(\"xml\"));\n       \n    }\n}\n```\n### Resource group ###\n```java\npublic class App {\n\n     public static void main(String[] args) {\n            \n        // /groupA/a\n        // /groupA/b\n        // /groupA/subgroup/c\n        group(\"/groupA\", () -\u003e {\n            get(\"/a\", req -\u003e {/* ... */});\n            put(\"/b\", req -\u003e {/* ... */});\n\n            group(\"/subgroup\", () -\u003e {\n                get(\"/c\", req -\u003e {/* ... */});\n            });\n        });\n\n        // /groupB/d\n        group(\"/groupB\", () -\u003e {\n            get(\"/d\", req -\u003e {/* ... */});\n        });\n        \n        }\n}\n```\n\n### Uber jar ###\n```xml\n\u003cbuild\u003e\n    \u003cfinalName\u003e${project.artifactId}\u003c/finalName\u003e\n    \u003cplugins\u003e\n        \u003cplugin\u003e\n            \u003cgroupId\u003eio.joshworks.snappy\u003c/groupId\u003e\n            \u003cartifactId\u003esnappy-maven-plugin\u003c/artifactId\u003e\n            \u003cversion\u003e0.5.2\u003c/version\u003e\n        \u003c/plugin\u003e\n    \u003c/plugins\u003e\n\u003c/build\u003e\n```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoshgontijo%2Fsnappy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjoshgontijo%2Fsnappy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoshgontijo%2Fsnappy/lists"}