Unirest for Java

repository·main·Indexed 25 days ago

https://github.com/kong/unirest-java

A lightweight, fluent HTTP client library for Java applications. Version 4 requires Java 11 and features a modular dependency structure. It supports HTTP 1, HTTP 2, WebSockets, and JSON Patch (RFC-6902), with optional object mapper modules for Jackson and GSON. Key features include global request/response interceptors, in-memory response caching with custom provider support, and a MockClient for testing HTTP interactions.

Tokens
14.1K
Snippets
48
Records
72
Agent score
83%

What's inside unirest-java

  1. Overview of Unirest-Java features

    main

    Unirest-Java is a fluent HTTP client library designed for simplicity and ease of use. It supports modern HTTP protocols and provides extensive capabilities for both request building and response handling.

    Key Features:

    • Protocols: HTTP 1 and HTTP 2, and WebSockets.
    • Data Formats: JSON Patch (RFC-6902) support and default object mappers for Jackson and GSON.
    • Request Building:
      • Path parameters and query parameter building.
      • Header manipulation, including full cookie support.
      • Multipart requests.
      • Automatic conversion of POJOs into string or binary bodies.
      • Global request interceptors.
    • Response Handling:
      • Global response interceptors.
      • Automatic conversion of response bodies into POJOs.
      • Built-in error handling.
    • Testing: Includes a mocking library for testing HTTP interactions.
  2. Manage Multiple Unirest Instances

    main

    While Unirest maintains a primary single instance, you can manage multiple isolated configurations or use instances for testing purposes instead of the static context.

        // Access the same instance used by the static Unirest class
        UnirestInstance unirest = Unirest.primaryInstance();
        unirest.config().connectTimeout(5000);
        String result = unirest.get("http://foo").asString().getBody();
    
        // Create a completely new, isolated instance
        UnirestInstance unirest = Unirest.spawnInstance();
  3. Upgrade to Unirest 3.0 (JSON Implementation Changes)

    main

    Unirest 3.0 replaced the org.json dependency with a clean-room implementation of the org.json interface using Google Gson as the engine. This was done to avoid licensing issues associated with org.json.

    Key Differences:

    • Namespace: The new namespace is kong.unirest.core.json.
    • Supported Classes: JSONArray, JSONObject, and JSONPointer honor most public interfaces and behaviors of the original org.json.
    • Limitations: Utility classes like XML-to-JSON or CSV-to-JSON are not implemented. Custom indenting via .toString(int spaces) always uses 2 spaces.
  4. Verify Mock Expectations

    main

    Validate that expected requests were actually made using the following methods:

    • mock.verifyAll(): Validates that every registered expectation was called at least once.
    • expectation.verify(): Validates that a specific expectation was called.
    • expectation.verify(Times times): Validates a specific expectation was called a specific number of times (e.g., Times.never()).
        @Test
        void verifyMultiple(){
            MockClient mock = MockClient.register();
        
            var zombo =    mock.expect(HttpMethod.POST, "http://zombo.com").thenReturn();
            var homestar = mock.expect(HttpMethod.DELETE, "http://homestarrunner.com").thenReturn();
        
            Unirest.post("http://zombo.com").asString().getBody();
        
            zombo.verify();
            homestar.verify(Times.never());
        }
  5. Perform Instant Mocking with UnirestInstance

    main

    To avoid affecting the global static state, use Unirest.spawnInstance() to create a new UnirestInstance. Register the mock specifically for that instance using MockClient.register(unirest). This is useful for isolated testing.

        @Test
        void mockInstant(){
            UnirestInstance unirest = Unirest.spawnInstance();
            MockClient mock = MockClient.register(unirest);
            
            mock.expect(HttpMethod.GET, "http://zombo.com")
                            .thenReturn("You can do anything!");
            
            assertEquals(
                "You can do anything!", 
                unirest.get("http://zombo.com").asString().getBody()
            );
        }
  6. Install Unirest 4 using Maven BOM

    main
    Unirest 4 is built on modern Java standards and requires at least Java 11. To manage its modular dependencies and avoid version conflicts, it is recommended to use the Maven Bill of Materials (BOM).
  7. Handle large responses using streams

    main

    Methods like asString() and asJson() load the entire response into memory, which can cause issues with large payloads. To handle large responses efficiently, you can process the content stream directly using asObject with a custom mapper or use thenConsumeAsync to process the response asynchronously.

    // Process large response via stream to avoid memory issues
    Map r = Unirest.get(MockServer.GET)
                   .queryString("firstname", "Gary")
                   .asObject(i -> new Gson().fromJson(i.getContentReader(), HashMap.class))
                   .getBody();
    
    // Or use an async consumer
    Unirest.get(MockServer.GET)
           .thenConsumeAsync(r -> {
               // Handle response (e.g., write stream to disk)
           });
  8. Install Unirest 4 with Maven

    main

    Unirest 4 requires at least Java 11.

    To manage Unirest 4's modular dependencies and avoid version conflicts, it is recommended to use the unirest-java-bom in your <dependencyManagement> section.

    Important: The unirest-java-core module no longer includes any transient dependencies for JSON parsing. If you need to perform object mapping or use JSON objects, you must explicitly declare a JSON module (such as Gson or Jackson) in your <dependencies>.

    <dependencyManagement>
        <dependencies>
            <!-- https://mvnrepository.com/artifact/com.konghq/unirest-java-bom -->
            <dependency>
                <groupId>com.konghq</groupId>
                <artifactId>unirest-java-bom</artifactId>
                <version>4.5.1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    
    <dependencies>
    <!-- https://mvnrepository.com/artifact/com.konghq/unirest-java-core -->
    <dependency>
        <groupId>com.konghq</groupId>
        <artifactId>unirest-java-core</artifactId>
    </dependency>
    
    <!-- pick a JSON module if you want to parse JSON include one of these: -->
    <!-- Google GSON -->
    <dependency>
        <groupId>com.konghq</groupId>
        <artifactId>unirest-modules-gson</artifactId>
    </dependency>
    
    <!-- OR maybe you like Jackson better? -->
    <dependency>
        <groupId>com.konghq</groupId>
        <artifactId>unirest-modules-jackson</artifactId>
    </dependency>
    </dependencies>
  9. Handle Multiple Expectations with Specificity Matching

    main

    You can register multiple expectations on a single MockClient. When a request is made, Unirest selects the expectation that matches most closely using a points system:

    1. Each positive match adds points.
    2. Any negative match (mismatch) immediately discards the expectation.
    3. The expectation with the highest number of points wins.

    This allows you to define a generic fallback and more specific overrides (e.g., matching specific headers).

        @Test
        void multipleExpects(){
            MockClient mock = MockClient.register();
    
            mock.expect(HttpMethod.POST, "https://somewhere.bad")
                    .thenReturn("I'm Bad");
    
            mock.expect(HttpMethod.GET, "http://zombo.com")
                    .thenReturn("You can do anything!");
    
            mock.expect(HttpMethod.GET, "http://zombo.com")
                    .header("foo", "bar")
                    .thenReturn("You can do anything with headers!");
    
            assertEquals(
                    "You can do anything with headers!",
                    Unirest.get("http://zombo.com")
                            .header("foo", "bar")
                            .asString().getBody()
            );
    
            assertEquals(
                    "You can do anything!",
                    Unirest.get("http://zombo.com")
                            .asString().getBody()
            );
        }
  10. Configure Unirest via Unirest.config()

    main

    In Unirest 4, all configuration is centralized through the Unirest.config() method. Configuration should ideally be performed once during application startup. Once Unirest has been activated, options involved in client creation cannot be changed without an explicit shutdown or reset.

        Unirest.config()
                .connectTimeout(1000)
                .proxy("proxy.example.com", 8080)
                .setDefaultHeader("Accept", "application/json")
                .followRedirects(false)
                .enableCookieManagement(false)
                .interceptor(new MyCustomInterceptor());
  11. Enable basic response caching

    main

    You can enable Unirest's simple in-memory response caching mechanism by calling Unirest.config().cacheResponses(true). Once enabled, subsequent requests to the same URL will return the cached response instead of making a new network call.

    Unirest.config().cacheResponses(true);
    
    // The first response will be cached, and the second will be retrieved from cache
    Unirest.get("https://somwhere").asString();
    Unirest.get("https://somwhere").asString();