org.javaweb.net.HttpResponseParser.java Source code

Java tutorial

Introduction

Here is the source code for org.javaweb.net.HttpResponseParser.java

Source

/*
 * Copyright yz 2016-01-14  Email:admin@javaweb.org.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.javaweb.net;

import org.apache.commons.collections.map.CaseInsensitiveMap;
import org.javaweb.utils.IOUtils;
import org.javaweb.utils.StringUtils;

import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.DeflaterInputStream;
import java.util.zip.GZIPInputStream;

/**
 * Http??
 * Created by yz on 2017/1/5.
 */
public class HttpResponseParser {

    /**
     * ??Header
     */
    private static final int MAX_HEADER_LENGTH = 1024 * 1000 * 4;

    private static Pattern responsePattern = Pattern.compile("^(HTTP/\\d\\.\\d) (\\d{3}) (.*)$");

    /**
     * Http?
     */
    private String httpVersion;

    /**
     * Http???
     */
    private int httpStatus = -1;

    /**
     * Http???
     */
    private String httpStatusInfo;

    /**
     * Http??Map
     */
    private Map<String, Object> headerMap = new CaseInsensitiveMap();

    /**
     * Http??
     */
    private String header;

    /**
     * ??
     */
    private DataInputStream dis;

    /**
     * ??
     */
    private InputStream httpBodyInputStream;

    public HttpResponseParser(InputStream in) {
        this.dis = new DataInputStream(in);
        parse();
    }

    /**
     * ??Http?
     *
     * @return
     */
    public static int getMaxHeaderLength() {
        return MAX_HEADER_LENGTH;
    }

    /**
     * ?Http?
     *
     * @return
     */
    public String getHttpVersion() {
        return httpVersion;
    }

    /**
     * ?Http???
     *
     * @return
     */
    public int getHttpStatus() {
        return httpStatus;
    }

    /**
     * Http???
     *
     * @return
     */
    public String getHttpStatusInfo() {
        return httpStatusInfo;
    }

    /**
     * ?Http??Map
     *
     * @return
     */
    public Map<String, Object> getHeaderMap() {
        return headerMap;
    }

    /**
     * ?Http??
     *
     * @return
     */
    public String getHeader() {
        return header;
    }

    /**
     * ?Http??
     *
     * @return
     */
    public InputStream getHttpBodyInputStream() {
        return httpBodyInputStream;
    }

    /**
     * ??
     */
    private void parse() {
        try {
            parseHttpResponseHeaderString();
            parseHttpResponseStatus();
            parseHttpResponseHeaderMap();
            parseHttpResponseBodyInputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * ?Http?
     *
     * @throws IOException
     */
    private void parseHttpResponseHeaderString() {
        boolean loop = true;
        int a = 0;
        StringBuilder sb = new StringBuilder();
        try {
            String str = null;
            while (loop && (str = dis.readLine()) != null) {
                a += str.length();// ??

                if (a > MAX_HEADER_LENGTH) {
                    loop = false;
                } else {
                    if (str.length() == 0) {
                        loop = false;
                    } else {
                        sb.append(str).append("\n");
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        this.header = sb.toString();
    }

    /**
     * ?Http?Map
     *
     * @throws IOException
     */
    private void parseHttpResponseHeaderMap() throws IOException {
        if (StringUtils.isNotEmpty(this.header)) {
            BufferedReader br = null;

            try {
                String str = null;
                br = new BufferedReader(new StringReader(this.header));

                while ((str = br.readLine()) != null) {
                    int i = str.indexOf(":");

                    if (i != -1) {
                        String key = i > 0 ? str.substring(0, i) : "";
                        String value = str.length() - 1 > i ? str.substring(i + 1).trim() : "";

                        if (!headerMap.containsKey(key)) {
                            headerMap.put(key, value);
                        } else {
                            Object obj = headerMap.get(key);

                            if (obj instanceof String) {
                                headerMap.put(key, new String[] { (String) obj, value });
                            } else {
                                List<String> list = new ArrayList<String>();
                                list.addAll(Arrays.asList((String[]) obj));
                                list.add(value);
                                headerMap.put(key, list.toArray(new String[list.size()]));
                            }
                        }
                    }
                }
            } catch (IOException e) {
                throw e;
            } finally {
                IOUtils.closeQuietly(br);
            }
        }
    }

    /**
     * ?Http???
     *
     * @throws IOException
     */
    private void parseHttpResponseStatus() throws IOException {
        try {
            if (StringUtils.isNotEmpty(this.header)) {
                StringReader sr = new StringReader(this.header);
                String responseStatusLine = new BufferedReader(sr).readLine();

                if (StringUtils.isNotEmpty(responseStatusLine)) {
                    Matcher m = responsePattern.matcher(responseStatusLine);

                    if (m.find() && m.groupCount() == 3) {
                        this.httpVersion = m.group(1);
                        this.httpStatus = StringUtils.isNum(m.group(2)) ? Integer.parseInt(m.group(2)) : -1;
                        this.httpStatusInfo = m.group(3);
                    }
                }
            }
        } catch (IOException e) {
            throw e;
        }
    }

    /**
     * ?Http?? ??Transfer-Encoding  Content-Encoding ?chunked?
     *
     * @throws IOException
     */
    private void parseHttpResponseBodyInputStream() throws IOException {
        InputStream bodyInputStream = null;

        // ?chunked
        if (this.headerMap.containsKey("Transfer-Encoding")) {
            String transferEncoding = (String) this.headerMap.get("Transfer-Encoding");

            if (StringUtils.isNotEmpty(transferEncoding) && "chunked".equalsIgnoreCase(transferEncoding)) {
                bodyInputStream = new ChunkedInputStream(dis);
            } else {
                bodyInputStream = dis;
            }
        } else {
            bodyInputStream = dis;
        }

        // ?gzipdeflate
        if (this.headerMap.containsKey("Content-Encoding")) {
            String contentEncoding = (String) this.headerMap.get("Content-Encoding");
            InputStream compressInputStream = null;

            try {
                if ("gzip".equalsIgnoreCase(contentEncoding)) {
                    compressInputStream = new GZIPInputStream(bodyInputStream);
                } else if ("deflate".equalsIgnoreCase(contentEncoding)) {
                    compressInputStream = new DeflaterInputStream(bodyInputStream);
                }
            } catch (IOException e) {
                throw e;
            }

            if (compressInputStream != null) {
                bodyInputStream = compressInputStream;
            }
        }

        this.httpBodyInputStream = bodyInputStream;
    }

}