{"id":16567857,"url":"https://github.com/sylvainhalle/jerrydog","last_synced_at":"2026-05-27T20:32:14.443Z","repository":{"id":145563637,"uuid":"55153134","full_name":"sylvainhalle/Jerrydog","owner":"sylvainhalle","description":"Web application server in Java","archived":false,"fork":false,"pushed_at":"2023-06-18T18:51:05.000Z","size":77,"stargazers_count":0,"open_issues_count":1,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-05T10:46:34.235Z","etag":null,"topics":["httpd","lightweight","server","tomcat","web","web-application","web-server"],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sylvainhalle.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,"publiccode":null,"codemeta":null}},"created_at":"2016-03-31T13:34:15.000Z","updated_at":"2025-01-06T12:26:31.000Z","dependencies_parsed_at":"2024-11-15T11:42:31.144Z","dependency_job_id":null,"html_url":"https://github.com/sylvainhalle/Jerrydog","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/sylvainhalle/Jerrydog","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sylvainhalle%2FJerrydog","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sylvainhalle%2FJerrydog/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sylvainhalle%2FJerrydog/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sylvainhalle%2FJerrydog/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sylvainhalle","download_url":"https://codeload.github.com/sylvainhalle/Jerrydog/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sylvainhalle%2FJerrydog/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33583394,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-27T02:00:06.184Z","response_time":53,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["httpd","lightweight","server","tomcat","web","web-application","web-server"],"created_at":"2024-10-11T21:07:39.373Z","updated_at":"2026-05-27T20:32:14.429Z","avatar_url":"https://github.com/sylvainhalle.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"Jerrydog: a lightweight web application server in Java\n======================================================\n\n![The dog in Tom and Jerry](jerrydog.jpg?raw=true)\n\nJerrydog is a web application server, comparable in essence to\n[Apache Tomcat](https://tomcat.apache.org), but much simpler and\nlightweight (compare Jerrydog's 30 kilobytes to Tomcat's 9 *mega*bytes).\nIt allows you to easily create a server that listens to HTTP requests,\ndispatches its content to one of the *callbacks* you can create, and \nreturns its response. As such, Jerrydog can be seen as a thin wrapper \nover Java's `com.sun.net.httpserver` classes, taking care of a lot of\nboilerplate code you'd otherwise have to write.\n\nHow it works\n------------\n\nSuppose you want to create a server on `localhost` that accepts two\nrequests:\n\n- When calling `http://localhost/hello`, the server should reply\n  with the string \"Hi\"\n- When calling `http://localhost/time/xyz`, the server should\n  reply with the current local time in city \"xyz\", or with an error\n  response if the city is not found.\n\n### Create a callback\n\nThe first step is to create a class for each request, that will\ntake care of producing the appropriate response. You do this by\ninheriting from the `RequestCallback` class. Here is a possible callback\nfor `hello`:\n\n    class HelloCallback {\n    \n      public boolean fire(HttpExchange t) {\n        String path = t.getRequestURI().getPath();\n        return path.compareTo(\"/hello\") == 0;\n      }\n      \n      public CallbackResponse process(HttpExchange t) {\n        CallbackResponse cbr = new CallbackResponse(t);\n        cbr.setCode(CallbackResponse.HTTP_OK).setContents(\"Hi\");\n        return cbr;\n      }\n    }\n\nThe first method, `fire()`, decides based on the contents of the HTTP\nrequest whether this callback should take care of it. In this case,\nwe look at the path contained in the request, and return `true` if this\npath is the string \"/hello\", indicating \"this request is for me\"; we\nreturn false otherwise.\n\nThe second method, `process()`, is responsible for producing a response\nto the request. We create an empty object `CallbackResponse`, and populate\ntwo of its fields. The first is the response *code*, which can be any of\nthe [HTTP status codes](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes);\nthe most common are represented in Jerrydog by constants, such as HTTP_OK\n(200). The second is the response contents, which can be any array of\nbytes (binary data, a string containing HTML, JSON, etc.). In our case,\nthe contents is simply the character string \"Hi\".\n\nA callback can be created in the same way for the second URL:\n\n    class TimeCallback {\n    \n      public boolean fire(HttpExchange t) {\n        String path = t.getRequestURI().getPath();\n        return path.startsWith(\"/time\") == 0;\n      }\n      \n      public CallbackResponse process(HttpExchange t) {\n        CallbackResponse cbr = new CallbackResponse(t);\n        String parts[] = t.getRequestURI().getPath().split(\"/\");\n        String time = getTimeForCity(parts[1]);\n        if (time == null) {\n          cbr.setCode(CallbackResponse.HTTP_NOT_FOUND);\n        } else {\n          cbr.setCode(CallbackResponse.HTTP_OK).setContents(time);\n        }\n        return cbr;\n      }\n      \n      String getTimeForCity(String city) {\n        ...\n      }\n    }\n\nThe callback is set to fire when the URL starts with the string \"/time\".\nThe `process()` method extracts the city name from the URL string, attempts\nto retrieve the time for that city; if the time is null, the response\ncode is set to 404 (HTTP_NOT_FOUND), otherwise, it is set to 200 and the\ntime string is put into the response body.\n\n### Creating the server\n\nThe last step is to create a server with these callbacks. The simplest way\nis to instantiate an empty `Server` class, and to add the two callbacks to\nit:\n\n    Server s = new Server();\n    s.registerCallback(new HelloCallback());\n    s.registerCallback(new TimeCallback());\n    s.startServer();\n\nThat's it. After calling `startServer()`, the server will listen to HTTP\nrequests on port 80 of `localhost`, and serve appropriate responses when\ncalled (all these defaults can be changed, see the Javadoc). Total size:\n17 lines of code.\n\nA different way of doing it is by creating a new class descending from\nserver:\n\n    class MyServer extends Server {\n      public MyServer() {\n        super();\n        registerCallback(new HelloCallback());\n        registerCallback(new TimeCallback());\n      }\n    }\n\nIn your code, you can then create instances of `MyServer`, which will\nalready contain the callbacks.\n\nGoing further\n-------------\n\nThis simple example shows the basic functionality of Jerrydog. It is\npossible to create more complex servers and callbacks.\n\n- The `RestCallback` class provides functionalities to encode and\n  decode URL parameters (such as \"foo=bar\u0026baz=123\u0026abc\")\n- The `InnerFileCallback` can easily serve the contents of local files\n- Cookies can be carried in requests and responses using the `Cookie`\n  class\n\nDependencies\n------------\n\nNone. (And it should stay that way.)\n\nProjects that use Jerrydog\n--------------------------\n\n- [LabPal](https://liflab.github.io/labpal), a library for running\n  experiments on a computer\n- [Cornipickle](https://github.com/liflab/cornipickle), a web layout\n  testing tool\n- The [HTTP palette](https://github.com/liflab/beepbeep-3-palettes)\n  of the [BeepBeep 3](https://liflab.github.io/beepbeep-3) event\n  stream processing engine\n\nWhy is it called Jerrydog?\n--------------------------\n\n    String name = \"Tomcat\";\n    return name.replace(\"Tom\", \"Jerry\").replace(\"cat\", \"dog\");\n\nAbout the author                                                   {#about}\n----------------\n\nJerrydog was written by [Sylvain Hallé](http://leduotang.ca/sylvain),\nassociate professor at [Université du Québec à\nChicoutimi](http://www.uqac.ca), Canada.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsylvainhalle%2Fjerrydog","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsylvainhalle%2Fjerrydog","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsylvainhalle%2Fjerrydog/lists"}