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

org.hcjf.io.net.http.HttpRequest Maven / Gradle / Ivy

package org.hcjf.io.net.http;

import org.hcjf.encoding.MimeType;
import org.hcjf.layers.Layers;
import org.hcjf.log.Log;
import org.hcjf.properties.SystemProperties;
import org.hcjf.utils.Strings;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.*;
import java.util.regex.Matcher;

/**
 * This particular kind of package contains the request information.
 * @author javaito
 */
public class HttpRequest extends HttpPackage {

    private static final int METHOD_INDEX = 0;
    private static final int REQUEST_PATH_INDEX = 1;
    private static final int VERSION_INDEX = 2;

    private String path;
    private String context;
    private HttpMethod method;
    private final Map parameters;
    private final List pathParts;
    private Matcher matcher;

    static {
        Layers.publishLayer(FormUrlEncodedDecoder.class);
        Layers.publishLayer(MultipartFormDataDecoder.class);
    }

    public HttpRequest(String requestPath, HttpMethod method) {
        this.path = requestPath;
        this.method = method;
        this.parameters = new HashMap<>();
        this.pathParts = new ArrayList<>();
    }

    protected HttpRequest(HttpRequest httpRequest) {
        super(httpRequest);
        this.context = httpRequest.context;
        this.path = httpRequest.path;
        this.method = httpRequest.method;
        this.parameters = httpRequest.parameters;
        this.pathParts = httpRequest.pathParts;
    }

    public HttpRequest() {
        this(null, null);
    }

    /**
     * Return the request path
     * @return Request path.
     */
    public final String getPath() {
        return path;
    }

    /**
     * Set the request path.
     * @param path Request path.
     */
    public final void setPath(String path) {
        this.path = path;
    }

    /**
     * Return the request context.
     * @return Request context.
     */
    public final String getContext() {
        return context;
    }

    /**
     * Set the request context.
     * @param context Request context.
     */
    public final void setContext(String context) {
        this.context = context;
        this.path = context;
    }

    /**
     * Return the request method.
     * @return Request method.
     */
    public final HttpMethod getMethod() {
        return method;
    }

    /**
     * Set the request method.
     * @param method Request method.
     */
    public final void setMethod(HttpMethod method) {
        this.method = method;
    }

    /**
     * Returns true if the request contains the parameter indicated.
     * @param name Name of the parameter.
     * @return True if the parameter is present and false in the otherwise.
     */
    public final boolean hasParameter(String name) {
        return parameters.containsKey(name);
    }

    /**
     * Return the request parameters.
     * @return Request parameters.
     */
    public final Map getParameters() {
        return Collections.unmodifiableMap(parameters);
    }

    /**
     * Return the parameter indexed by the argument name.
     * @param parameterName Name of the founding parameter.
     * @param  Expected response type
     * @return Return the parameter.
     */
    public final  O getParameter(String parameterName) {
        return (O) parameters.get(parameterName);
    }

    /**
     * Returns the value that corresponds with the place named with the name indicated.
     * @param placeName Name of the place.
     * @return Value replaced into the place.
     */
    public final String getReplaceableValue(String placeName) {
        return matcher == null ? null : matcher.group(placeName);
    }

    /**
     * This method set the matche that results of the match between the context regex and the url invoked with the request.
     * @param matcher Matcher instance.
     */
    public final void setMatcher(Matcher matcher) {
        this.matcher = matcher;
    }

    /**
     * Add parameter.
     * @param parameterName Parameter name.
     * @param parameterValue Parameter value.
     */
    public final void addHttpParameter(String parameterName, String parameterValue) {
        parameters.put(parameterName, parameterValue);
    }

    /**
     * Return a list with all the parts of the request path.
     * If the path is /path1/path2/pathN, then the method response with
     * a list ad [path1,path2,pathN]
     * @return List with all the parts of the request path.
     */
    public final List getPathParts() {
        return pathParts;
    }

    /**
     * This method process the body of the complete request.
     */
    @Override
    protected void processBody() {
        HttpHeader contentType = getHeader(HttpHeader.CONTENT_TYPE);
        if(contentType != null) {
            try {
                RequestBodyDecoderLayer bodyDecoderLayer = Layers.get(RequestBodyDecoderLayer.class,
                        L -> contentType.getHeaderValue().startsWith(L.getImplName()));
                Map parameters = bodyDecoderLayer.decode(this);
                if(parameters != null) {
                    this.parameters.putAll(parameters);
                }
            } catch (Exception ex){}
        }
    }

    /**
     * Process the first line of the request.
     * @param firstLine First line of the request.
     */
    @Override
    protected void processFirstLine(String firstLine) {
        String[] parts = firstLine.split(LINE_FIELD_SEPARATOR);

        method = HttpMethod.valueOf(parts[METHOD_INDEX]);
        path = parts[REQUEST_PATH_INDEX];
        setHttpVersion(parts[VERSION_INDEX]);

        //Check if there are parameters into request
        if(path.indexOf(HTTP_FIELD_START) >= 0) {
            context = path.substring(0, path.indexOf(HTTP_FIELD_START));
            parseHttpParameters(path.substring(path.indexOf(HTTP_FIELD_START) + 1));
        } else {
            context = path;
        }

        for(String pathPart : context.split(HTTP_CONTEXT_SEPARATOR)) {
            if(!pathPart.isEmpty()) {
                pathParts.add(pathPart);
            }
        }
    }

    /**
     * This method split the parameters body string in each http parameter
     * using the http standard syntax.
     * @param parametersBody String that contains all the parameters.
     */
    private void parseHttpParameters(String parametersBody) {
        String[] params = parametersBody.split(HTTP_FIELD_SEPARATOR);

        String charset = null;
        HttpHeader contentType = getHeader(HttpHeader.CONTENT_TYPE);
        if(contentType != null) {
            //The content-type header should not have more than one group
            //In this case we use the first group.
            charset = contentType.getParameter(
                    contentType.getGroups().iterator().next(), HttpHeader.PARAM_CHARSET);
        }
        if(charset == null) {
            charset = SystemProperties.getDefaultCharset();
        }

        String key;
        String value;
        int insertIndex;
        ArrayList listParameter;
        for(String param : params) {
            if(param.indexOf(HTTP_FIELD_ASSIGNATION) < 0) {
                key = param;
                value = null;
            } else {
                key = param.substring(0, param.indexOf(HTTP_FIELD_ASSIGNATION));
                value = param.substring(param.indexOf(HTTP_FIELD_ASSIGNATION) + 1);
                if(value.length() == 0) {
                    value = null;
                }
            }

            if(key.contains(Strings.START_SUB_GROUP) && key.contains(Strings.END_SUB_GROUP)) {
                insertIndex = -1;
                if(key.indexOf(Strings.START_SUB_GROUP) + 1 == key.indexOf(Strings.END_SUB_GROUP)) {
                } else {
                    insertIndex = Integer.parseInt(key.substring(key.indexOf(Strings.START_SUB_GROUP) + 1, key.indexOf(Strings.END_SUB_GROUP)));
                }

                key = key.substring(0, key.indexOf(Strings.START_SUB_GROUP));
                if(parameters.containsKey(key)) {
                    listParameter = getParameter(key);
                } else {
                    listParameter = new ArrayList<>();
                    parameters.put(key, listParameter);
                }

                if(insertIndex >= 0) {
                    listParameter.add(insertIndex, value);
                } else {
                    listParameter.add(value);
                }
            } else {
                try {
                    parameters.put(URLDecoder.decode(key, charset), value == null ? null : URLDecoder.decode(value, charset));
                } catch (UnsupportedEncodingException e) {
                    Log.w(SystemProperties.get(SystemProperties.Net.Http.LOG_TAG), "Unable to decode http parameter, %s:%s", key, value);
                    parameters.put(key, value);
                }
            }
        }
    }

    /**
     * Return the string that represent the protocol of the package.
     * @return Protocol description.
     */
    private String toStringProtocolHeader() {
        Strings.Builder builder = new Strings.Builder();

        builder.append(getMethod().toString()).append(LINE_FIELD_SEPARATOR).
                append(getPath()).append(LINE_FIELD_SEPARATOR).
                append(getHttpVersion()).append(STRING_LINE_SEPARATOR);
        for(HttpHeader header : getHeaders()) {
            builder.append(header).append(STRING_LINE_SEPARATOR);
        }
        Collection cookies = getCookies();
        if(cookies.size() > 0) {
            builder.append(HttpHeader.COOKIE.toString()).append(": ");
            for (Cookie cookie : cookies) {
                builder.append(cookie, Strings.ARGUMENT_SEPARATOR_2 + Strings.WHITE_SPACE);
            }
        }
        builder.cleanBuffer();
        builder.append(STRING_LINE_SEPARATOR);
        return builder.toString();
    }

    /**
     * Return the bytes that represent the string of the protocol name.
     * @return Protocol name bytes.
     */
    @Override
    public final byte[] getProtocolHeader() {
        return toStringProtocolHeader().getBytes();
    }

    /**
     * Creates the string representation of the package.
     * @return String representation of the package.
     */
    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append(toStringProtocolHeader());
        if(getBody() != null) {
            int maxLength = SystemProperties.getInteger(SystemProperties.Net.Http.INPUT_LOG_BODY_MAX_LENGTH);
            if(maxLength > 0) {
                if (getBody().length > maxLength) {
                    builder.append(new String(getBody(), 0, maxLength));
                    builder.append(" ... [").append(getBody().length - maxLength).append(" more]");
                } else {
                    builder.append(new String(getBody()));
                }
            }
        }

        return builder.toString();
    }

    /**
     * This class represents a file attached into the request.
     */
    public static class AttachFile {

        private final String name;
        private final String fileName;
        private final MimeType mimeType;
        private final byte[] file;

        public AttachFile(String name, String fileName, MimeType mimeType, byte[] file) {
            this.name = name;
            this.fileName = fileName;
            this.mimeType = mimeType;
            this.file = file;
        }

        /**
         * Returns the name of the block of data.
         * @return Name of the block of data.
         */
        public String getName() {
            return name;
        }

        /**
         * Returns the name of the file.
         * @return File name.
         */
        public String getFileName() {
            return fileName;
        }

        public MimeType getMimeType() {
            return mimeType;
        }

        /**
         * Returns the content of the file.
         * @return File content.
         */
        public byte[] getFile() {
            return file;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy