{"id":36427339,"url":"https://github.com/while-loop/rest4j","last_synced_at":"2026-01-11T18:03:36.749Z","repository":{"id":57724008,"uuid":"114703347","full_name":"while-loop/rest4j","owner":"while-loop","description":"Thin HTTP/REST wrapper on top of HTTP Servers","archived":false,"fork":false,"pushed_at":"2018-08-18T02:43:34.000Z","size":112,"stargazers_count":0,"open_issues_count":2,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-07-03T18:07:26.349Z","etag":null,"topics":["go","golang","http","json","middleware","rest","rest-api"],"latest_commit_sha":null,"homepage":"","language":"Java","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/while-loop.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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-12-19T01:04:07.000Z","updated_at":"2018-08-18T01:34:47.000Z","dependencies_parsed_at":"2022-09-02T06:54:28.130Z","dependency_job_id":null,"html_url":"https://github.com/while-loop/rest4j","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/while-loop/rest4j","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/while-loop%2Frest4j","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/while-loop%2Frest4j/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/while-loop%2Frest4j/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/while-loop%2Frest4j/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/while-loop","download_url":"https://codeload.github.com/while-loop/rest4j/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/while-loop%2Frest4j/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28317190,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-11T14:58:17.114Z","status":"ssl_error","status_checked_at":"2026-01-11T14:55:53.580Z","response_time":60,"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":["go","golang","http","json","middleware","rest","rest-api"],"created_at":"2026-01-11T18:03:36.037Z","updated_at":"2026-01-11T18:03:36.743Z","avatar_url":"https://github.com/while-loop.png","language":"Java","readme":"Rest4j\n==========\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://travis-ci.org/while-loop/rest4j\"\u003e\u003cimg src=\"https://img.shields.io/travis/while-loop/rest4j.svg?style=flat-square\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://mvnrepository.com/artifact/com.github.while-loop/rest4j\"\u003e\u003cimg src=\"https://maven-badges.herokuapp.com/maven-central/com.github.while-loop/rest4j/badge.svg?style=flat-square\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://coveralls.io/github/while-loop/rest4j\"\u003e\u003cimg src=\"https://img.shields.io/coveralls/while-loop/rest4j.svg?style=flat-square\"\u003e\u003c/a\u003e\n  \u003ca href=\"LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/badge/license-Apache 2.0-blue.svg?style=flat-square\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\nHTTP wrapper that sits on top of different HTTP Server implementations.\nBring Your Own Server (BYOS).\n\nInspiration from the Go stdlib http package.\n\n# Table of Contents\n1. [Download](#download)\n2. [Implemented Servers](#implemented-servers)\n3. [Usage \u0026 Examples](#usage)\n4. [Middleware](#middleware)\n5. [Chaining Routers](#chaining-routers)\n6. [Static resources](#static-resources)\n\nDownload\n--------\n\n#### Gradle\n```gradle\ndependencies {\n    compile 'com.github.while-loop:rest4j:1.0.4'\n}\n```\n\n#### Maven\n```maven\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.github.while-loop\u003c/groupId\u003e\n    \u003cartifactId\u003erest4j\u003c/artifactId\u003e\n    \u003cversion\u003e1.0.4\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nImplemented Servers\n-------------------\n\n- [com.sun.net.HttpServer](src/test/java/com/github/whileloop/rest4j/router/sun/SunRouterTest.java)\n- [org.eclipse.jetty.server.Server](src/test/java/com/github/whileloop/rest4j/router/jetty/JettyRouterTest.java)\n\nUsage\n-----\n\nFor a full demo example, check the [integration](src/test/java/com/github/whileloop/rest4j/integration) package\n\n```java\npublic class Example {\n    public static void main(String[] args) throws IOException {\n        HttpServer server = HttpServer.create(new InetSocketAddress(\"localhost\", 8080), 0);\n\n        Router r = new Router();\n        r.handle(\"/\", (req, resp) -\u003e {\n            String raddr = req.remoteAddr();\n\n            resp.headers.set(\"Content-Type\", \"text/plain\");\n            resp.write(\"hello \" + raddr + \"!!\");\n        });\n        r.handle(\"/:uuid\", Example::update).setMethods(PUT);\n\n        server.createContext(\"/\", new SunRouter(r)); // BYOS\n        server.setExecutor(Executors.newSingleThreadExecutor());\n        server.start();\n    }\n\n    private static void update(HttpRequest req, HttpResponse resp) {\n        String body = is2String(req);\n        String uuid = req.getParam(\"uuid\");\n        // do something with body\n\n        resp.writeHeader(ACCEPTED);\n    }\n\n    private static String is2String(InputStream is) {\n        try (java.util.Scanner s = new java.util.Scanner(is, StandardCharsets.UTF_8.name())) {\n            s.useDelimiter(\"\\\\A\");\n            return s.hasNext() ? s.next() : \"\";\n        }\n    }\n}\n```\n\nMiddleware\n----------\n\n```java\npublic class LoggerMiddleware implements Middleware {\n    private Logger logger;\n\n    public LoggerMiddleware() {\n        this(null);\n    }\n\n    public LoggerMiddleware(Logger logger) {\n        if (logger == null) {\n            logger = LoggerFactory.getLogger(LoggerMiddleware.class);\n        }\n\n        this.logger = logger;\n    }\n\n    @Override\n    public Handler handle(Handler next) {\n        return (req, resp) -\u003e {\n            // get the time before passing the request down the chain of middleware\n            long start = System.currentTimeMillis();\n\n            next.handle(req, resp); // apply the next handle\n\n            long elapsed = System.currentTimeMillis() - start;\n            logger.info(String.format(\"%-7s %-6s %d %s\",\n                    req.getMethod(), elapsed + \"ms\", resp.status.code(), req.getUrl().getPath()));\n        };\n    }\n}\n```\n\nChaining Routers\n----------------\n\n\n```java\nRouter r = new Router();\nr.use(new LoggerMiddleware(),\n        new JsonMiddleware(),\n        new CorsMiddleware());\n\nRouter v1 = new Router();\nRouter usersR = new Router();\nusersR.handle(\"/\", this::getAll);                               // GET /v1/users\nusersR.handle(\"/:uuid\", this::updateUser).setMethods(PUT);     // PUT /v1/users/:uuid\nusersR.handle(\"/:uuid\", this::deleteUuser).setMethods(DELETE); // DELETE /v1/users/:uuid\n\nRouter postsR = new Router();\nusersR.handle(\"/\", this::getAll);                                   // GET /v1/posts\nusersR.handle(\"/:postId\", this::updatePost).setMethods(PUT);       // PUT /v1/posts/:uuid\nusersR.handle(\"/:postId\", this::deletePost).setMethods(DELETE);    // DELETE /v1/posts/:uuid\n\nv1.handle(\"/users\", usersR); // /v1/users\nv1.handle(\"/posts\", usersR); // /v1/posts\nr.handle(\"/v1\", v1); // /v1\n```\n\nStatic Resources\n----------------\n\n```java\nString dir = getClass().getClassLoader().getResource(\"www\").toExternalForm();\nFileHandler fh = new FileHandler(dir);\n```\n\nChangelog\n---------\n\nThe format is based on [Keep a Changelog](http://keepachangelog.com/) \nand this project adheres to [Semantic Versioning](http://semver.org/).\n\n[CHANGELOG.md](CHANGELOG.md)\n\nLicense\n-------\nrest4j is licensed under the Apache 2.0 License.\nSee [LICENSE](LICENSE) for details.\n\nAuthor\n------\n\nAnthony Alves\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwhile-loop%2Frest4j","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwhile-loop%2Frest4j","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwhile-loop%2Frest4j/lists"}