{"id":20756844,"url":"https://github.com/jesusbmx/juno-http-client","last_synced_at":"2026-05-07T13:03:20.976Z","repository":{"id":226472582,"uuid":"768792032","full_name":"jesusbmx/juno-http-client","owner":"jesusbmx","description":"HTTP client for Java and Android, which facilitates the creation of HTTP request such as: GET, POST, HEAD, OPTIONS, PUT, DELETE and TRACE.","archived":false,"fork":false,"pushed_at":"2025-02-11T17:33:36.000Z","size":17255,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-07T17:59:24.063Z","etag":null,"topics":["android","gson","http-client","http-request","jackson","java","java-http-client","json","jwt-authentication","send-request"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jesusbmx.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":null,"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":"jesusbmx"}},"created_at":"2024-03-07T18:33:36.000Z","updated_at":"2025-02-11T17:33:14.000Z","dependencies_parsed_at":"2024-08-27T01:37:27.979Z","dependency_job_id":"485120ef-0893-4b5c-af6f-2f10e4849ebd","html_url":"https://github.com/jesusbmx/juno-http-client","commit_stats":null,"previous_names":["jesusbmx/java-http-client","jesusbmx/juno-http-client"],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jesusbmx%2Fjuno-http-client","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jesusbmx%2Fjuno-http-client/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jesusbmx%2Fjuno-http-client/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jesusbmx%2Fjuno-http-client/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jesusbmx","download_url":"https://codeload.github.com/jesusbmx/juno-http-client/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243065577,"owners_count":20230783,"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":["android","gson","http-client","http-request","jackson","java","java-http-client","json","jwt-authentication","send-request"],"created_at":"2024-11-17T09:35:35.346Z","updated_at":"2025-10-06T17:54:47.188Z","avatar_url":"https://github.com/jesusbmx.png","language":"Java","funding_links":["https://github.com/sponsors/jesusbmx"],"categories":[],"sub_categories":[],"readme":"## Juno Http Client\n**HTTP client** for Java and Android, which facilitates the creation of **HTTP request**  such as: GET, POST, HEAD, OPTIONS, PUT, DELETE and TRACE.\n\n## Installation\n\nTo include Juno in your project using Gradle, add the following dependency:\n```\ndependencies {\n  implementation 'com.github.jesusbmx:juno:1.0.5'\n  implementation 'com.github.jesusbmx:juno-http-client:1.0.7'\n}\n```\n\nAlternatively, you can download the JAR file directly from [JitPack](https://jitpack.io/#jesusbmx/juno-http-client):\n\nDownload [juno.jar](https://jitpack.io/com/github/jesusbmx/juno/1.0.5/juno-1.0.5.jar)\n\nDownload [juno-http-client.jar](https://jitpack.io/com/github/jesusbmx/juno-http-client/1.0.7/juno-http-client-1.0.7.jar)\n\n\n## [Samples](src/test/java/Samples.java)\nStart by creating an instance of the `HttpClient`:\n```java\nHttpClient client = HttpClient.getInstance()\n    .setDebug(true);\n```\n\n#### GET\n```\nGET https://postman-echo.com/get HTTP/1.1\n```\n\n```java\nString get() throws Exception {\n  HttpRequest request = HttpRequest.get(\n       \"https://postman-echo.com/get\")\n  ;\n  return client.send(request, String.class);\n}\n```\n\n#### POST\n```\nPOST https://postman-echo.com/post HTTP/1.1\nContent-Type: application/x-www-form-urlencoded; charset=UTF-8\nContent-Length: 25\n\nid=7\u0026name=bar\u0026active=true\n```\n\n```java\nString post(int id, String name, boolean active) throws Exception {\n  // application-www-www-form-urlencoded\n  FormBody reqBody = new FormBody()\n          .add(\"id\", id)\n          .add(\"name\", name)\n          .add(\"active\", active)\n  ;\n  HttpRequest request = HttpRequest.post(\n      \"https://postman-echo.com/post\", reqBody)\n  ;\n  return client.send(request, String.class);\n}\n```\n\n#### RequestBody\n```\nPOST https://postman-echo.com/post HTTP/1.1\nContent-Type: application/json; charset=UTF-8\nContent-Length: 44\n\n{\"id\": \"7\", \"name\": \"bar\", \"active\": \"true\"}\n```\n\n```java\nString request() throws Exception {\n    String json = \"{\\\"id\\\": \\\"7\\\", \\\"name\\\": \\\"bar\\\", \\\"active\\\": \\\"true\\\"}\";\n    \n    // application/json\n    RequestBody reqBody = RequestBody.create(\n        \"application/json\", json)\n    ;\n    HttpRequest request = HttpRequest.post(\n        \"https://postman-echo.com/post\", reqBody)\n    ;\n    return client.send(request, String.class);\n}\n```\n\n#### Upload\n```\nPOST https://postman-echo.com/post HTTP/1.1\nContent-Type: multipart/form-data; boundary=30707575573640\nContent-Length: 71162\n\n--30707575573640\nContent-Disposition: form-data; name=\"name\"\nContent-Transfer-Encoding: 8bit\nContent-Type: text/plain; charset=UTF-8\n\nJohn Doe\n--30707575573640\nContent-Disposition: form-data; name=\"file\"; filename=\"file_1710436579164.png\"\nContent-Transfer-Encoding: binary\nContent-Type: application/octet-stream\n\n-- binary --\n```\n\n```java\nString upload(File file) throws Exception { \n  // multipart/form-data\n  MultipartBody reqBody = new MultipartBody()\n    .addParam(\"name\", \"John Doe\")\n    .addFile(\"file\", file)\n  ;\n  HttpRequest request = HttpRequest.post(\n    \"https://postman-echo.com/post\", reqBody)\n  ;\n  return client.send(request, String.class);\n}\n```\n\n#### Download\n```\nGET https://jitpack.io/com/github/jesusbmx/java-http-client/0.0.1/java-http-client-0.0.1.jar HTTP/1.1\n```\n\n```java\nFile download() throws Exception {\n  HttpRequest request = HttpRequest.get(\"https://jitpack.io/com/github/jesusbmx/java-http-client/0.0.1/java-http-client-0.0.1.jar\")\n      .setTimeoutMs(20000)\n  ;\n  FileResponseBodyConverter converter = new FileResponseBodyConverter()\n      .setDir(System.getProperty(\"user.home\") + \"\\\\Downloads\\\\\") \n      //.setName(\"httpclient.jar\")\n  ;  \n  return client.send(request, converter);\n  //return client.send(request, File.class);\n}\n```\n\n#### Url, Headers\n```\nGET http://ip-api.com/json/24.48.0.1?fields=status%2Cmessage%2Cquery%2Ccountry%2Ccity\u0026lang=en HTTP/1.1\n\nUser-Agent: nombre-cliente\n```\n\n```java\nHttpResponse getIpLocation() throws Exception { \n  HttpUrl url = new HttpUrl(\"http://ip-api.com/\")\n    .addPath(\"json\")\n    .addPath(\"24.48.0.1\")\n    .addQueryParameter(\"fields\", \"status,message,query,country,city\")\n    .addQueryParameter(\"lang\", \"en\")\n  ;\n  HttpRequest request = HttpRequest.get(url)\n    .addHeader(\"User-Agent\", \"nombre-cliente\")\n  ;\n  return client.send(request);\n}\n```\n#### HttpResponse\n\n```java\ntry ( HttpResponse response = getIpLocation() ) {\n  int code = response.code;  \n  Headers headers = response.headers;\n  Charset charset = response.getCharsetFromContentType();\n  InputStream content = response.content;\n\n  String str = response.readString(); // content.close()\n  byte[] bytes = response.readBytes(); // content.close()\n}\n```\n\n#### Interceptor\n\n```java\nHttpClient client = HttpClient.getInstance().setInterceptor((request, transport) -\u003e {\n    HttpResponse response = transport.send(request);\n    if (response.isSuccessful()) {\n        return response;\n    }\n    throw new Exception(\"Unknown error code: \" + response.code);\n});\n```\n\n\n\n## [Asynchronous and Synchronous Tasks](src/test/java/AsynTest.java)\n\nWe prepare the request\n\n```java\npublic Task\u003cString\u003e insert(\n    int id, String name, boolean active) {\n    \n  // application-www-www-form-urlencoded\n  FormBody reqBody = new FormBody()\n      .add(\"id\", id)\n      .add(\"name\", name)\n      .add(\"active\", active);\n  \n  HttpRequest request = HttpRequest.post(\n      \"https://postman-echo.com/post\", reqBody);\n\n  return client.newTask(request, String.class);\n}\n```\n\n#### Asynchronous\n\nAsynchronously send the request and notify your application with a callback when a response returns. Since this request is asynchronous, Restlight handles the execution in the background thread so that the\nMain UI is not blocked or interferes with it.\n\n```java\nTask\u003cString\u003e task = insert(22, \"John Doe\", true);\n    \ntask.async((String response) -\u003e {\n  String str = response;\n  System.out.println(str);\n\n}, (Exception e) -\u003e  {\n   e.printStackTrace();\n});\n```\n\n#### Synchronous\n\nSynchronously send the request and return your response.\n\n```java\nTask\u003cString\u003e task = insert(22, \"John Doe\", true);\n    \ntry {\n    String response = task.sync();\n    System.out.println(response);\n    \n} catch(Exception e) {\n    e.printStackTrace();\n}\n```\n\n## [JSON](https://github.com/stleary/JSON-java)\n(https://www.json.org/json-en.html)\n\nFor android it is not necessary to download [org.json jar](https://github.com/stleary/JSON-java)\nFor other java platforms like java swing if needed.\n\n#### JSON response\n```java\npublic Task\u003cJSONObject\u003e insert(\n    String name, int age, boolean active) {\n      \n    // application-www-www-form-urlencoded\n    FormBody reqBody = new FormBody()\n        .add(\"name\", name)\n        .add(\"age\", age)\n        .add(\"active\", active);\n\n    HttpRequest request = HttpRequest.post(\n        \"https://postman-echo.com/post\", reqBody);\n        \n    return client.newTask(request, JSONObject.class);\n}\n```\n\n#### JSON request body\n```java\nJSONObject jsonRequest() throws Exception {\n  JSONObject data = new JSONObject();\n  data.put(\"user_id\", 7);\n  data.put(\"name\", \"jesus\");\n\n  RequestBody reqBody = RequestBody.create(\n        \"application/json\", data.toString());\n\n  HttpRequest request = HttpRequest.post(\n        \"https://postman-echo.com/post\", reqBody);\n\n  return client.send(request, JSONObject.class);\n}\n```\n\n## Authorization\n\n[JWT](https://jwt.io/) enables automatic storage, cleansing, transmission, and refresh of authentication tokens.\n\n### Storage and Configuration\n\nFirst, you must create your own token storage and add the `JwtTokenProvider` to manage the tokens.\n```java\nDataStorage tokenStorage = new FileDataStorage(new File(\".../MyApi.jwt\"));\nTokenProvider tokenProvider = new JwtTokenProvider(tokenStorage, onTokenRefresh);\n\n// Configure the HTTP client with Bearer token authorization and enable debugging\nHttpClient client = new HttpClient()\n    .setAuthorization(new TokenAuthorization(\"Bearer \", tokenProvider))\n    .setDebug(true);\n```\n\n### Token Refresh Management\n\nIf the token expires or there is no saved token, a token refresh function will be executed. Below is an example of how to implement this logic.\n```java\nJwtTokenProvider.OnTokenRefresh onTokenRefresh = (TokenProvider provider) -\u003e {\n    // Create the request body with the refresh token\n    FormBody body = new FormBody()\n        .add(\"token\", provider.getRefreshToken())\n    ;\n    // Create a POST request to refresh the token\n    HttpRequest request = HttpRequest.post(\n        \".../auth/refresh_token\", body);\n\n    // Execute the request with another client to avoid entering a loop\n    JSONObject response = request.send(JSONObject.class);\n\n    // Update the access and refresh tokens\n    provider.setAccessToken(response.optString(\"accessToken\"));\n    provider.setRefreshToken(response.optString(\"refreshToken\"));\n};\n```\n\n### Sign In\nTo sign in and obtain the initial tokens, you can implement a login function like this:\n```java\nvoid login(String email, String password) throws Exception {\n    // Create the request body with login credentials\n    FormBody body = new FormBody()\n        .add(\"email\", email)\n        .add(\"password\", password)\n    ;\n    // Create a POST request to the login endpoint\n    HttpRequest request = HttpRequest.post(\n        \".../auth/login\", body);\n\n    // Execute the request with another client to avoid entering a loop\n    JSONObject response = request.send(JSONObject.class);\n\n    // Store the received access and refresh tokens\n    tokenProvider.setAccessToken(response.getString(\"accessToken\"));\n    tokenProvider.setRefreshToken(response.getString(\"refreshToken\"));\n}\n```\n\n### Executing Requests with the JWT Token\nOnce the HTTP client is configured with the JWT token provider, you can execute authenticated requests. Below is an example of how to make a POST request using the JWT token.\n\n```\nPOST https://postman-echo.com/post HTTP/1.1\nAuthorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c\n```\n\n```java\npublic HttpResponse requestWithToken() throws Exception{\n  // Create the POST request\n  HttpRequest request = HttpRequest.post(\n      \"https://postman-echo.com/post\");\n\n  // Execute the request using the client configured with JWT authorization\n  return client.send(request);\n```\n\n### Simple Sign In and Token Refresh\n\nIn this example, if there is no token available, the user will log in for the first time. When the token expires, the login process will be repeated to refresh it:\n\n```java\nJwtTokenProvider.OnTokenRefresh onTokenRefresh = (TokenProvider provider) -\u003e {\n    // Create the request body with login credentials\n    FormBody body = new FormBody()\n        .add(\"email\", \"myMail@domain.com\")\n        .add(\"password\", \"myPassword\")\n    ;\n    // Create a POST request to the login endpoint\n    HttpRequest request = HttpRequest.post(\n        \".../auth/login\", body);\n\n    // Execute the request with another client to avoid entering a loop\n    JSONObject response = request.send(JSONObject.class);\n\n    // Store the new access token\n    provider.setAccessToken(response.optString(\"accessToken\"));\n};\n```\n\n\n## [GSON](https://github.com/google/gson) \n\nIn your **build.gradle** you will need to add the dependencies for  **GSON**:\n\n```groovy\ndependencies {\n  ...\n  compile 'com.google.code.gson:gson:2.4'\n}\n```\n\n\nNow we are ready to start writing some code. The first thing we want to do is define our **Post** model.\nCreate a new file called **Post.java** and define the **Post** class like this:\n\n```java\npublic class Post {\n  \n  @SerializedName(\"id\")\n  public long ID;\n    \n  @SerializedName(\"date\")\n  public Date dateCreated;\n \n  public String title;\n  public String author;\n  public String url;\n  public String body;\n}\n```\n\n\nLet's create a new instance of **GSON** before calling request. We'll also need to set a custom date format on the **GSON** instance to handle the dates returned by the API:\n\nWe define the database interactions. They can include a variety of query methods:\n\n```java\npublic class PostApi {\n  HttpClient client = HttpClient.getInstance()\n          .setDebug(true);  \n    \n  public PostApi() {\n    Gson gson = new GsonBuilder()\n            .setDateFormat(\"M/d/yy hh:mm a\")\n            .create();\n    \n    client.addConverterFactory(new GsonConverterFactory(gson));\n  }\n\n  public Task\u003cPost[]\u003e getPosts() {\n    HttpRequest request = HttpRequest.get(\n        \"https://kylewbanks.com/rest/posts.json\");\n\n    return client.newTask(request, Post[].class);\n  }\n\n  public Task\u003cString\u003e insert(Post p) {\n    RequestBody reqBody = client.createRequestBody(p); // application/json\n    // RequestBody reqBody = new FormBody(Maps.getPublicFields(p)); // application-www-www-form-urlencoded\n    // RequestBody reqBody = new MultipartBody(Maps.getPublicFields(p)); // multipart/form-data\n    \n    HttpRequest request = HttpRequest.post(\n            \"https://postman-echo.com/post\", reqBody);\n    \n    return client.newTask(request, String.class);\n  }\n}\n```\n\nPrepares the request to be executed in the background. Ideal for android applications.\nAsynchronously send the request and notify your application with a callback when a response returns.\n```java\n...\nPostApi api = new PostApi();\n    \nTask\u003cPost[]\u003e task = api.getPosts(); \n\ntask.async((Post[] response) -\u003e {\n  List\u003cPost\u003e list = Arrays.asList(response);\n  for (Post post : list) {\n    System.out.println(post.title);\n  }\n\n}, (Exception e) -\u003e {\n  e.printStackTrace(System.out);\n});\n```\n\n## [Jackson](https://github.com/FasterXML/jackson) \n\nNow we are ready to start writing some code. The first thing we want to do is define our **Post** model.\nCreate a new file called **Post.java** and define the **Post** class like this:\n\n```java\npublic class Post {\n    \n  @JsonProperty(\"id\")\n  public long id;\n\n  @JsonProperty(\"date\")\n  public Date dateCreated;\n\n  @JsonProperty(\"title\")\n  public String title;\n  \n  @JsonProperty(\"author\")\n  public String author;\n  \n  @JsonProperty(\"url\")\n  public String url;\n  \n  @JsonProperty(\"body\")\n  public String body;\n}\n```\n\n\nLet's create a new instance of **ObjectMapper** before calling request. We'll also need to set a custom date format on the **ObjectMapper** instance to handle the dates returned by the API:\n\nWe define the database interactions. They can include a variety of query methods:\n\n```java\npublic class PostApi {\n  \n  HttpClient client = HttpClient.getInstance()\n          .setDebug(true);  \n    \n  public PostApi() {\n    ObjectMapper mapper = new ObjectMapper()\n            .setDateFormat(new SimpleDateFormat(\"M/d/yy hh:mm a\"))\n            .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);\n    \n    client.addConverterFactory(new JacksonConverterFactory(mapper));\n  }\n\n  public Task\u003cPost[]\u003e getPosts() {\n    HttpRequest request = HttpRequest.get(\n        \"https://kylewbanks.com/rest/posts.json\");\n\n    return client.newTask(request, Post[].class);\n  }\n  \n  public Task\u003cString\u003e insert(Post p) {\n    // application/json\n    RequestBody reqBody = client.createRequestBody(p);\n    \n    HttpRequest request = HttpRequest.post(\n            \"https://postman-echo.com/post\", reqBody);\n    \n    return client.newTask(request, String.class);\n  }\n}\n```\n\nPrepares the request to be executed in the background. Ideal for android applications.\nAsynchronously send the request and notify your application with a callback when a response returns.\n```java\n...\nPostApi api = new PostApi();\n    \ntask\u003cPost[]\u003e task = api.getPosts(); \n\ntask.async((Post[] response) -\u003e {\n  List\u003cPost\u003e list = Arrays.asList(response);\n  for (Post post : list) {\n    System.out.println(post.title);\n  }\n\n}, (Exception e) -\u003e {\n  e.printStackTrace(System.out);\n});\n```\n\nLicense\n=======\n\n    Copyright 2022 Juno Http Client, Inc.\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjesusbmx%2Fjuno-http-client","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjesusbmx%2Fjuno-http-client","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjesusbmx%2Fjuno-http-client/lists"}