All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.iwbfly.myhttp.reflection.MyhttpRequest Maven / Gradle / Ivy

The newest version!
package com.iwbfly.myhttp.reflection;

import com.iwbfly.myhttp.Client;
import com.iwbfly.myhttp.HttpMethod;
import com.iwbfly.myhttp.Myhttp;
import com.iwbfly.myhttp.converter.json.JsonConverter;
import com.iwbfly.myhttp.exceptions.MyhttpRuntimeException;
import com.iwbfly.myhttp.exceptions.RetryableException;
import com.iwbfly.myhttp.http.*;
import com.iwbfly.myhttp.interceptor.Interceptor;
import com.iwbfly.myhttp.interceptor.InterceptorChain;
import com.iwbfly.myhttp.logging.Logger;
import com.iwbfly.myhttp.mapping.MappingTemplate;
import com.iwbfly.myhttp.retry.Retryer;
import com.iwbfly.myhttp.utils.DataType;
import com.iwbfly.myhttp.utils.RequestNameValue;
import com.iwbfly.myhttp.utils.StringUtils;
import okhttp3.MediaType;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Type;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.*;
import java.util.concurrent.TimeUnit;

import  com.iwbfly.myhttp.mapping.MappingParameter.*;

import static com.iwbfly.myhttp.mapping.MappingParameter.*;
import static java.lang.String.format;

/**
 * @author pangyajun
 * @since 2021/10/14 15:43
 **/
public class MyhttpRequest {

    private Myhttp.Builder configuration;

    private String protocol;

    private String url;

    private Map query = new LinkedHashMap<>();

    private final Object[] arguments;

    private MyhttpHeaderMap headers = new MyhttpHeaderMap();

    private Map data = new LinkedHashMap();

    private List bodyList = new LinkedList<>();

    private MyhttpRequestType type;

    private String requestBody;

    private String charset;

    private String responseEncode = "UTF-8";

    private boolean async;

    private DataType dataType;

    private int timeout;

    private Logger.Level loggerLevel;

    private Logger logger;

    private JsonConverter jsonConverter;

    private Type returnClass;

    private Request.Options options;

    private InterceptorChain interceptorChain = new InterceptorChain();
    public final  String TYPE_APPLICATION_X_WWW_FORM_URLENCODED = "application/x-www-form-urlencoded";
    public final  String TYPE_APPLICATION_JSON = "application/json";
    public final  String TYPE_MULTIPART_FORM_DATA = "multipart/form-data";
    private  Charset DEFAULT_CHARSET = Charset.forName("UTF-8");

    public MyhttpRequest(Myhttp.Builder configuration, Object[] arguments) {
        this.configuration = configuration;
        this.arguments = arguments;
    }
    public MyhttpRequest(Myhttp.Builder configuration) {
        this(configuration, new Object[0]);
    }

    public JsonConverter getJsonConverter() {
        return jsonConverter;
    }

    public MyhttpRequest setJsonConverter(JsonConverter jsonConverter) {
        this.jsonConverter = jsonConverter;
        return this;
    }

    public Type getReturnClass() {
        return returnClass;
    }

    public MyhttpRequest setReturnClass(Type returnClass) {
        this.returnClass = returnClass;
        return this;
    }

    public Myhttp.Builder getConfiguration() {
        return configuration;
    }

    public String getProtocol() {
        return protocol;
    }

    public String getUrl() {
        return url;
    }

    public Map getQuery() {
        return query;
    }

    public Object[] getArguments() {
        return arguments;
    }

    public MyhttpHeaderMap getHeaders() {
        return headers;
    }

    public MyhttpRequestType getType() {
        return type;
    }

    public String getCharset() {
        return charset;
    }

    public String getResponseEncode() {
        return responseEncode;
    }

    public boolean isAsync() {
        return async;
    }

    public DataType getDataType() {
        return dataType;
    }

    public InterceptorChain getInterceptorChain() {
        return interceptorChain;
    }

    public MyhttpRequest setConfiguration(Myhttp.Builder configuration) {
        this.configuration = configuration;
        return this;
    }

    public MyhttpRequest setProtocol(String protocol) {
        this.protocol = protocol;
        return this;
    }

    public MyhttpRequest setUrl(String url) {
        this.url = url;
        return this;
    }

    public MyhttpRequest setQuery(Map query) {
        this.query = query;
        return this;
    }

    public MyhttpRequest setHeaders(MyhttpHeaderMap headers) {
        this.headers = headers;
        return this;
    }

    public MyhttpRequest addHeader(String name, Object value) {
        if (StringUtils.isEmpty(name)) {
            return this;
        }
        this.headers.setHeader(name, String.valueOf(value));
        return this;
    }

    public MyhttpRequest addHeader(RequestNameValue nameValue) {
        this.addHeader(nameValue.getName(), nameValue.getValue());
        return this;
    }


    public MyhttpRequest addHeaders(List nameValues) {
        for (RequestNameValue nameValue : nameValues) {
            this.addHeader(nameValue.getName(), nameValue.getValue());
        }
        return this;
    }
    public MyhttpRequest setType(MyhttpRequestType type) {
        this.type = type;
        return this;
    }

    public MyhttpRequest setCharset(String charset) {
        this.charset = charset;
        return this;
    }

    public MyhttpRequest setResponseEncode(String responseEncode) {
        this.responseEncode = responseEncode;
        return this;
    }

    public MyhttpRequest setAsync(boolean async) {
        this.async = async;
        return this;
    }

    public MyhttpRequest setDataType(DataType dataType) {
        this.dataType = dataType;
        return this;
    }

    public int getTimeout() {
        return timeout;
    }

    public MyhttpRequest setTimeout(int timeout) {
        this.timeout = timeout;
        return this;
    }

    public Logger getLogger() {
        return logger;
    }

    public MyhttpRequest setLogger(Logger logger) {
        this.logger = logger;
        return this;
    }

    public MyhttpRequest setInterceptorChain(InterceptorChain interceptorChain) {
        this.interceptorChain = interceptorChain;
        return this;
    }

    public List getBodyList() {
        return bodyList;
    }

    public MyhttpRequest setBodyList(List bodyList) {
        this.bodyList = bodyList;
        return this;
    }
    public String getContentType() {
        return headers.getValue("Content-Type");
    }

    public MyhttpRequest setContentType(String contentType) {
        addHeader("Content-Type", contentType);
        return this;
    }

    public String getContentEncoding() {
        return headers.getValue("Content-Encoding");
    }

    public MyhttpRequest setContentEncoding(String contentEncoding) {
        addHeader("Content-Encoding", contentEncoding);
        return this;
    }

    public String getUserAgent() {
        return headers.getValue("User-Agent");
    }

    public MyhttpRequest setUserAgent(String userAgent) {
        addHeader("User-Agent", userAgent);
        return this;
    }
    public Map getData() {
        return data;
    }

    public MyhttpRequest setData(Map data) {
        this.data = data;
        return this;
    }

    public String getRequestBody() {
        return requestBody;
    }

    public MyhttpRequest setRequestBody(String requestBody) {
        this.requestBody = requestBody;
        return this;
    }

    public MyhttpRequest addData(List data) {
        putMapAddList(this.data, data);
        return this;
    }

    public MyhttpRequest addData(RequestNameValue nameValue) {
        if (nameValue.isInQuery()) {
            addQuery(nameValue.getName(), nameValue.getValue());
        } else if (nameValue.isInBody()) {
            this.data.put(nameValue.getName(), nameValue.getValue());
        }
        return this;
    }

    public Logger.Level getLoggerLevel() {
        return loggerLevel;
    }

    public MyhttpRequest setLoggerLevel(Logger.Level loggerLevel) {
        this.loggerLevel = loggerLevel;
        return this;
    }

    public Request.Options getOptions() {
        return options;
    }

    public MyhttpRequest setOptions(Request.Options options) {
        this.options = options;
        return this;
    }

    private void putMapAddList(Map map, List source) {
        for (int i = 0; i < source.size(); i++) {
            RequestNameValue nameValue = source.get(i);
            if (nameValue.isInQuery()) {
                addQuery(nameValue.getName(), nameValue.getValue());
            } else if (nameValue.isInBody()) {
                map.put(nameValue.getName(), nameValue.getValue());
            }
        }
    }

    public MyhttpRequest addQuery(String name, Object value) {
        this.query.put(name, value);
        return this;
    }
    public List getQueryNameValueList() {
        List nameValueList = new ArrayList<>();
        for (Iterator> iterator = query.entrySet().iterator(); iterator.hasNext(); ) {
            Map.Entry entry = iterator.next();
            String name = entry.getKey();
            Object value = entry.getValue();
            if (value != null) {
                RequestNameValue nameValue = new RequestNameValue(name, value, TARGET_QUERY);
                nameValueList.add(nameValue);
            }
        }
        return nameValueList;

    }
    public List getHeaderNameValueList() {
        List nameValueList = new ArrayList();
        for (Iterator iterator = headers.headerIterator(); iterator.hasNext(); ) {
            MyhttpHeader header = iterator.next();
            RequestNameValue nameValue = new RequestNameValue(header.getName(), header.getValue(), TARGET_HEADER);
            nameValueList.add(nameValue);
        }
        return nameValueList;
    }

    public List getDataNameValueList() {
        List nameValueList = new ArrayList<>();
        for (Iterator> iterator = data.entrySet().iterator(); iterator.hasNext(); ) {
            Map.Entry entry = iterator.next();
            String name = entry.getKey();
            Object value = entry.getValue();
            if (value != null) {
                RequestNameValue nameValue = new RequestNameValue(name, value, TARGET_BODY);
                nameValueList.add(nameValue);
            }
        }
        return nameValueList;
    }

    public MyhttpRequest addInterceptor(Interceptor interceptor) {
        interceptorChain.addInterceptor(interceptor);
        return this;
    }
    public String buildUrl() {

        String query = paramBuild(getQueryNameValueList());
        if (StringUtils.isNotEmpty(query)) {
            return url + "?" + query;
        }
        return url;
    }

    public  String paramBuild(List data){
        StringBuilder paramBuilder = new StringBuilder();
        for (int i = 0; i < data.size(); i++) {
            RequestNameValue nameValue = data.get(i);
            /*if (!nameValue.isInQuery()) {
                continue;
            }*/
            paramBuilder.append(nameValue.getName());
            String value = MappingTemplate.getParameterValue(jsonConverter, nameValue.getValue());
            paramBuilder.append('=');
            if (StringUtils.isNotEmpty(value) && getCharset() != null) {
                String encodedValue = null;
                try {
                    encodedValue = URLEncoder.encode(value, getCharset());
                } catch (UnsupportedEncodingException e) {
                }
                if (encodedValue != null) {
                    paramBuilder.append(encodedValue);
                }
            }
            if (i < data.size() - 1) {
                paramBuilder.append('&');
            }
        }
        return paramBuilder.toString();
    }
    public  Map> buildHeaders(){
        Map> headers = new HashMap<>();
        List headerList = getHeaderNameValueList();
        String contentType = getContentType();
        String contentEncoding = getContentEncoding();
        List valueList ;
        if (headerList != null && !headerList.isEmpty()) {
            for (RequestNameValue nameValue : headerList) {
                String name = nameValue.getName();
                if (!name.equalsIgnoreCase("Content-Type")
                        && !name.equalsIgnoreCase("Content-Encoding")) {
                    String value = MappingTemplate.getParameterValue(jsonConverter, nameValue.getValue());
                    if(headers.containsKey(name)) {
                        headers.get(name).add(value);

                    }else {
                        valueList = new ArrayList<>();
                        valueList.add(value);
                        headers.put(name,valueList);
                    }
                }
            }
        }
        if (StringUtils.isNotEmpty(contentType) && !contentType.startsWith("multipart/form-data")) {
            valueList = new ArrayList<>();
            valueList.add(contentType) ;
            headers.put("Content-Type", valueList);
        }
        if (StringUtils.isNotEmpty(contentEncoding)) {
            valueList = new ArrayList<>();
            valueList.add(contentEncoding) ;
            headers.put("Content-Type", valueList);
        }
        return headers;
    }

    public  byte[] buildBody() {
        boolean isMethodWithBody = getType().match(HttpMethod.POST.name())||
                getType().match(HttpMethod.PUT.name() ) ||getType().match(HttpMethod.PATCH.name());
        if(!isMethodWithBody)
            return null;
        String contentType = getContentType();
        if (StringUtils.isEmpty(contentType)) {
            String value = getHeaders().getValue("Content-Type");
            if (value != null) {
                if (value.length() > 0) {
                    contentType = value;
                }
//                getHeaders().remove("Content-Type");
            }
        }

        if (StringUtils.isEmpty(contentType)) {
            contentType = TYPE_APPLICATION_X_WWW_FORM_URLENCODED;
            setContentType(contentType);
        }

        String[] typeGroup = contentType.split(";[ ]*charset=");
        String mineType = typeGroup[0];
        String charset = getCharset();
        boolean mergeCharset = false;
        if (StringUtils.isEmpty(charset)) {
            if (typeGroup.length > 1) {
                charset = typeGroup[1];
                mergeCharset = true;
            } else {
                charset = "UTF-8";
            }
        }
        String requestBody = getRequestBody();
        if (StringUtils.isEmpty(mineType)) {
            mineType = TYPE_APPLICATION_X_WWW_FORM_URLENCODED;
        }

        if (requestBody != null) {
            return setStringBody(requestBody, charset, contentType, mergeCharset);

        }
        List nameValueList = getDataNameValueList();
        if (mineType.equals(TYPE_APPLICATION_X_WWW_FORM_URLENCODED)
                && nameValueList.size() > 0) {
            return setFormBody();
        }
        else if (mineType.equals(TYPE_APPLICATION_JSON)) {

            List bodyList = getBodyList();
            Map map = convertNameValueListToMap( nameValueList);
            if (map != null && !map.isEmpty()) {
                bodyList.add(map);
            }
            Object toJsonObj = bodyList;
            if (bodyList.size() == 1) {
                toJsonObj = bodyList.get(0);
            }
            String text = jsonConverter.encode(toJsonObj);
            return setStringBody(text, charset, contentType, mergeCharset);
        }

        else  {
            Map map = convertNameValueListToMap(nameValueList);
            StringBuilder builder = new StringBuilder();
            for (Iterator> iterator = map.entrySet().iterator(); iterator.hasNext(); ) {
                Map.Entry entry = iterator.next();
                Object value = entry.getValue();
                builder.append(value);
            }
            List bodyList = getBodyList();
            for (Object bodyItem : bodyList) {
                builder.append(bodyItem.toString());
            }
            return setStringBody( builder.toString(), charset, contentType, mergeCharset);
        }
    }
    private  Map convertNameValueListToMap(List nameValueList) {
        Map map = new LinkedHashMap<>();
        for (int i = 0; i < nameValueList.size(); i++) {
            RequestNameValue nameValue = nameValueList.get(i);
            String name = nameValue.getName();
            Object value = nameValue.getValue();
            if (value instanceof Date) {
                value = MappingTemplate.getParameterValue(jsonConverter, value);
            }
            if (value == null && StringUtils.isNotEmpty(name)) {
                if (name.charAt(0) == '{') {
                    Map nameMap = jsonConverter.decode(name, Map.class);
                    if (nameMap != null && nameMap.size() > 0) {
                        map.putAll(nameMap);
                    } else {
                        map.put(name, value);
                    }
                }
            }
            else {
                map.put(name, value);
            }
        }
        return map;
    }
    protected  byte[] setFormBody() {
        String s = paramBuild(getDataNameValueList());
        if (StringUtils.isEmpty(s))
            return null;
        return s.getBytes();
    }
    protected  byte[] setStringBody(String text, String charset, String contentType, boolean mergeCharset) {
        MediaType mediaType = MediaType.parse(contentType);
        Charset cs = DEFAULT_CHARSET;
        if (StringUtils.isNotEmpty(charset)) {
            try {
                cs = Charset.forName(charset);
            } catch (Throwable th) {
                throw new MyhttpRuntimeException("[Myhttp] '" + charset + "' is not a valid charset", th);
            }
        }
        if (contentType != null) {
            Charset mtcs = mediaType.charset();
            if (mtcs == null) {
                if (StringUtils.isNotEmpty(charset) && mergeCharset) {
                    mediaType = MediaType.parse(contentType + "; charset=" + charset.toLowerCase());
                }
            }
        }
        return text.getBytes(cs);

    }
    long elapsedTime(long start) {
        return TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);
    }
    public Request create(){
        interceptorChain.beforeExecute(this);
        String method = type.getName();
        Charset charset = Charset.forName(getCharset());
        String url = buildUrl();
        byte[] bytes = buildBody();
        Map> headers = buildHeaders();
        return Request.create(method,url,headers,bytes,charset);
    }
    public Object execute(Request request){
        if (loggerLevel != Logger.Level.NONE)
        logger.logRequest(request,this);
        Client client = configuration.getClient();
        String result = null;
        Object decode = null;
        Response response = null;
        long start = System.nanoTime();
        try {
            response = client.execute(request, options);
        } catch (IOException e) {
            if (loggerLevel != Logger.Level.NONE)
                logger.logIOException( e, elapsedTime(start));
            throw new RetryableException(e, format("%s %s executing  %s",  request.httpMethod(), request.url(),e.getMessage()));
        }
        try {
            long elapsedTime = elapsedTime(start);
            if (loggerLevel != Logger.Level.NONE)
                response = logger.logAndRebufferResponse(response, elapsedTime,this);
            if (response != null) {
                if (returnClass == Response.class) {
                    return response;
                }
                result = response.body().string();
                decode = jsonConverter.decode(result, returnClass);
            }
        } catch (Throwable e) {
            return result;
        }

        return decode;
    }


}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy