Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Implementing a Lightweight HTTP Client Wrapper with Apache HttpComponents

Tech 1

The subsequent implementation transitions from scattered utility functions to a centralized routing architecture. By consolidating network operations into a single dispatcher, duplicate connnection setup and teardown logic are eliminated. The design employs a factory approach to instantiate distinct HTTP verbs based on invocation context, while leveraging standard try-with-resources guarantees to prevent socket leaks during both successful transactions and abrupt network failures.

import org.apache.http.Header;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.*;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class HttpTransportHelper {

    private static final RequestConfig SAFE_CONFIG = RequestConfig.custom()
            .setConnectTimeout(5000)
            .setSocketTimeout(5000)
            .build();

    public static String sendStandardGet(String address) {
        return dispatch(address, null, null, "GET");
    }

    public static String sendPostWithData(String address, Map<String, String> fields) {
        return dispatch(address, null, fields, "POST");
    }

    public static String sendGetWithQueries(String address, Map<String, String> queries) {
        return dispatch(address, queries, null, "GET");
    }

    private static String dispatch(String url, Map<String, String> queryMap, Map<String, String> payloadMap, String verb) {
        String output = "";
        try (CloseableHttpClient channel = HttpClients.custom().setDefaultRequestConfig(SAFE_CONFIG).build()) {
            URI finalUri = assembleUri(url, queryMap);
            HttpUriRequest action = createOperation(verb, finalUri, payloadMap);
            
            try (CloseableHttpResponse response = channel.execute(action)) {
                HttpEntity content = response.getEntity();
                if (content != null) {
                    output = EntityUtils.toString(content, "UTF-8");
                }
            }
        } catch (Exception interruption) {
            System.err.println("Request failed: " + interruption.getMessage());
        }
        return output;
    }

    private static URI assembleUri(String base, Map<String, String> map) throws Exception {
        if (map == null || map.isEmpty()) return new URI(base);
        URIBuilder builder = new URIBuilder(base);
        map.forEach(builder::setParameter);
        return builder.build();
    }

    private static HttpUriRequest createOperation(String command, URI uri, Map<String, String> data) {
        if ("POST".equalsIgnoreCase(command)) {
            HttpPost request = new HttpPost(uri);
            if (data != null && !data.isEmpty()) {
                List<BasicNameValuePair> params = new ArrayList<>(data.size());
                data.forEach((k, v) -> params.add(new BasicNameValuePair(k, v)));
                request.setEntity(new UrlEncodedFormEntity(params, ContentType.TEXT_PLAIN));
            }
            return request;
        }
        return new HttpGet(uri);
    }
}

Key architectural decisions in this revision include embedding explicit connectivity thresholds to mitigate hanging threads during high-latency scenarios. The URI assembly routine dynamically mutates query string mappings rather than relying on external builders, ensuring predictable parameter injection. Furthermore, response payload extraction is isolated into a dedicated validation layer, decoupling business logic from raw byte-stream conversion. When adapting this pattern to legacy environments, the diamond operator and functional idioms may require explicit type declarations depending on the target compiler specification.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.