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

no.sb1.troxy.http.common.Response Maven / Gradle / Ivy

package no.sb1.troxy.http.common;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.util.List;
import java.util.Map;
import javax.xml.bind.annotation.XmlTransient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A Response is a simple bean with all the data we transmit to a client.

 */
public class Response extends Packet {
    /**
     * Logger for this class.
     */
    private static final Logger log = LoggerFactory.getLogger(Response.class);
    /**
     * Status code for this response.
     */
    private String code = "";

    private String reason = null;
    /**
     * Header for response.
     */
    private String header = "";
    /**
     * Content for response.
     */
    private String content = "";
    /**
     * How long the response should be delayed in milliseconds before it's sent to the client.
     * Used by filters delaying the response.
     */
    private transient long delay;

    /**
     * Empty constructor, needed to create a Response object from a serialized (XML) state.
     */
    public Response() {
    }

    /**
     * Constructor for creating a Response object from a HttpURLConnection.
     * @param remoteConnection A connection to the remote host.
     */
    public Response(HttpURLConnection remoteConnection) {
        /* set status code */
        try {
            code = "" + remoteConnection.getResponseCode();
            reason = remoteConnection.getResponseMessage();
        } catch (IOException e) {
            log.info("Failed reading response code, setting it to {}", HttpURLConnection.HTTP_INTERNAL_ERROR, e);
            code = "" + HttpURLConnection.HTTP_INTERNAL_ERROR;
            reason ="TROXY: Failed to extract responsecode from remoteConnection";
        }

        /* set header */
        StringBuilder sb = new StringBuilder();
        Map> headerFields = remoteConnection.getHeaderFields();
        boolean firstEntry = true;
        for (String key : headerFields.keySet()) {
            if (key == null) {
                /* apparently it sets status code & protocol as a header with key  */
                continue;
            }
            String value = remoteConnection.getHeaderField(key);
            if (!firstEntry)
                sb.append('\n');
            sb.append(key).append(": ").append(value);
            firstEntry = false;
        }
        header = sb.toString();

        /* detect character set */
        String charset = discoverCharset(remoteConnection.getContentType());

        /* set content */
        sb = new StringBuilder();
        try (BufferedReader br = new BufferedReader(new InputStreamReader(remoteConnection.getInputStream(), charset))) {
            char[] buffer = new char[32768];
            int read;
            while ((read = br.read(buffer)) != -1)
                sb.append(buffer, 0, read);
        } catch (IOException e) {
            log.info("Failed reading response content from input stream, reading content from error stream", e);
            try (BufferedReader br = new BufferedReader(new InputStreamReader(remoteConnection.getErrorStream(), charset))) {
                char[] buffer = new char[32768];
                int read;
                while ((read = br.read(buffer)) != -1)
                    sb.append(buffer, 0, read);
            } catch (IOException|NullPointerException e2 ) {
                log.warn("Failed reading response content from error stream, incomplete or no content in response", e2);
            }
        }
        content = sb.toString();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String toString() {
        return "[CODE: " + getCode() + "] [REASON: " + getReason() +"] [HEADER: " + getHeader().length() + " characters] [CONTENT: " + getContent().length() + " characters]";
    }

    /**
     * Set code. Null value is set to "".
     * @param code The code.
     */
    public void setCode(String code) {
        this.code = code == null ? "" : code;
    }

    /**
     * Get code.
     * @return The code.
     */
    public String getCode() {
        return code;
    }

    /**
     * Get the HTTP status reason phrase (if any).
     * @return The reason.
     */
    public String getReason() {
        return reason;
    }

    /**
     * Set header. Null value is set to "".
     * @param header The header.
     */
    public void setHeader(String header) {
        this.header = header == null ? "" : header;
    }

    /**
     * Get header.
     * @return The header.
     */
    public String getHeader() {
        return header;
    }

    /**
     * Set content. Null value is set to "".
     * @param content The content.
     */
    public void setContent(String content) {
        this.content = content == null ? "" : content;
    }

    /**
     * Get content.
     * @return The content.
     */
    public String getContent() {
        return content;
    }

    /**
     * Get how long the response should be delayed in milliseconds before it's sent to client.
     * @return How long the response should be delayed in milliseconds before it's sent to client.
     */
    @XmlTransient
    public long getDelay() {
        return delay;
    }

    /**
     * Set how long the response should be delayed in milliseconds before it's sent to client.
     * @param delay How long the response should be delayed in milliseconds before it's sent to client.
     */
    public void setDelay(long delay) {
        this.delay = delay;
    }

    /**
     * Discover the character set of this request.
     * @return The character set name or "iso-8859-1" if character set name wasn't found.
     */
    public String discoverCharset() {
        return discoverCharset(header);
    }

    @Override
    public boolean equals(Object obj) {
        Response r = obj instanceof Response ? (Response) obj : null;
        return r != null && code.equals(r.code) && header.equals(r.header) && content.equals(r.content);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy