Package com.xiaoleilu.hutool

Source Code of com.xiaoleilu.hutool.HttpUtil

package com.xiaoleilu.hutool;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;

import com.xiaoleilu.hutool.exceptions.UtilException;

/**
* Http请求工具类
*
* @author xiaoleilu
*/
public class HttpUtil {

  /** 未知的标识 */
  public final static String UNKNOW = "unknown";
 
  public final static Pattern CHARSET_PATTERN =  Pattern.compile("charset=(.*?)\"");
 
  private static Map<String, String> cookies = new HashMap<String, String>();

  /**
   * 编码字符为 application/x-www-form-urlencoded
   *
   * @param content 被编码内容
   * @return 编码后的字符
   */
  public static String encode(String content, String charset) {
    if (StrUtil.isBlank(content)) return content;

    String encodeContent = null;
    try {
      encodeContent = URLEncoder.encode(content, charset);
    } catch (UnsupportedEncodingException e) {
      throw new UtilException(StrUtil.format("Unsupported encoding: [{}]", charset), e);
    }
    return encodeContent;
  }

  /**
   * 解码application/x-www-form-urlencoded字符
   *
   * @param content 被编码内容
   * @return 编码后的字符
   */
  public static String decode(String content, String charset) {
    if (StrUtil.isBlank(content)) return content;
    String encodeContnt = null;
    try {
      encodeContnt = URLDecoder.decode(content, charset);
    } catch (UnsupportedEncodingException e) {
      throw new UtilException(StrUtil.format("Unsupported encoding: [{}]", charset), e);
    }
    return encodeContnt;
  }

  /**
   * 获取客户端IP
   *
   * @param request 请求对象
   * @return IP地址
   */
  public static String getClientIP(HttpServletRequest request) {
    String ip = request.getHeader("X-Forwarded-For");
    if (isUnknow(ip)) {
      ip = request.getHeader("Proxy-Client-IP");
    }
    if (isUnknow(ip)) {
      ip = request.getHeader("WL-Proxy-Client-IP");
    }
    if (isUnknow(ip)) {
      ip = request.getHeader("X-Real-IP");
    }
    if (isUnknow(ip)) {
      ip = request.getRemoteAddr();
    }
    // 多级反向代理检测
    if (ip != null && ip.indexOf(",") > 0) {
      ip = ip.trim().split(",")[0];
    }
    return ip;
  }

  /**
   * 发送get请求
   *
   * @param urlString 网址
   * @param customCharset 自定义请求字符集,如果字符集获取不到,使用此字符集
   * @param isPassCodeError 是否跳过非200异常
   * @return 返回内容,如果只检查状态码,正常只返回 "",不正常返回 null
   * @throws IOException
   */
  public static String get(String urlString, String customCharset, boolean isPassCodeError) throws IOException {
    final URL url = new URL(urlString);
    final String host = url.getHost();
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
   
    conn.addRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.83 Safari/537.1");
    final String cookie = cookies.get(host);
    if(cookie != null) conn.addRequestProperty("Cookie", cookie);

    conn.setRequestMethod("GET");
    conn.setDoInput(true);
   
    if(conn.getResponseCode() != 200) {
      if(! isPassCodeError) {
        throw new IOException("Status code not 200!");
      }
    }
   
    final String setCookie = conn.getHeaderField("Set-Cookie");
    if(StrUtil.isBlank(setCookie) == false) {
      Log.debug("Set cookie: [{}]", setCookie);
      cookies.put(host, setCookie);
    }
   
    /* 获取内容 */
    String charset = getCharsetFromConn(conn);
    boolean isGetCharsetFromContent = false;
    if(StrUtil.isBlank(charset)) {
      charset = customCharset;
      isGetCharsetFromContent = true;
    }
    String content = getString(conn.getInputStream(), charset, isGetCharsetFromContent);
    conn.disconnect();

    return content;
  }
 
  /**
   * 发送post请求
   * @param urlString 网址
   * @param paramMap post表单数据
   * @param customCharset 自定义请求字符集,发送时使用此字符集,获取返回内容如果字符集获取不到,使用此字符集
   * @param isPassCodeError 是否跳过非200异常
   * @return 返回数据
   * @throws IOException
   */
  public static String post(String urlString, Map<String, Object> paramMap, String customCharset, boolean isPassCodeError) throws IOException {
    return post(urlString, toParams(paramMap), customCharset, isPassCodeError);
  }
 
  /**
   * 发送post请求
   * @param urlString 网址
   * @param params post表单数据
   * @param customCharset 自定义请求字符集,发送时使用此字符集,获取返回内容如果字符集获取不到,使用此字符集
   * @param isPassCodeError 是否跳过非200异常
   * @return 返回数据
   * @throws IOException
   */
  public static String post(String urlString, String params, String customCharset, boolean isPassCodeError) throws IOException {
    URL url = new URL(urlString);
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
   
    conn.setRequestMethod("POST");
    conn.setDoOutput(true);
    conn.setDoInput(true);
    conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
   
    IoUtil.write(conn.getOutputStream(), customCharset, true, params);
   
    if(conn.getResponseCode() != 200) {
      if(! isPassCodeError) {
        throw new IOException("Status code not 200!");
      }
    }
   
    /* 获取内容 */
    String charset = getCharsetFromConn(conn);
    String content = IoUtil.getString(conn.getInputStream(), StrUtil.isBlank(charset) ? customCharset : charset);
    conn.disconnect();

    return content;
  }
 
  /**
   * 获得远程String
   * @param url 请求的url
   * @param customCharset 自定义的字符集
   * @return 文本
   * @throws IOException
   */
  public static String downloadString(String url, String customCharset) throws IOException {
    InputStream inputStream = new URL(url).openStream();
    return IoUtil.getString(inputStream, customCharset);
  }
 
  /**
   * 将Map形式的Form表单数据转换为Url参数形式
   * @param paramMap 表单数据
   * @return url参数
   */
  public static String toParams(Map<String, Object> paramMap) {
    return CollectionUtil.join(paramMap.entrySet(), "&");
  }
 
  //----------------------------------------------------------------------------------------- Private method start
  /**
   * 从Http连接的头信息中获得字符集
   *
   * @param conn HTTP连接对象
   * @return 字符集
   */
  private static String getCharsetFromConn(HttpURLConnection conn) {
    String charset = conn.getContentEncoding();
    if (charset == null || "".equals(charset.trim())) {
      String contentType = conn.getContentType();
      charset = ReUtil.get("charset=(.*)", contentType, 1);
    }
    return charset;
  }

  /**
   * 检测给定字符串是否为未知,多用于检测HTTP请求相关<br/>
   *
   * @param checkString 被检测的字符串
   * @return 是否未知
   */
  private static boolean isUnknow(String checkString) {
    return StrUtil.isBlank(checkString) || UNKNOW.equalsIgnoreCase(checkString);
  }
 
  /**
   * 从流中读取内容
   *
   * @param in 输入流
   * @param charset 字符集
   * @return 内容
   * @throws IOException
   */
  private static String getString(InputStream in, String charset, boolean isGetCharsetFromContent) throws IOException {
    StringBuilder content = new StringBuilder(); // 存储返回的内容

    // 从返回的内容中读取所需内容
    BufferedReader reader = new BufferedReader(new InputStreamReader(in, charset));
    String line = null;
    while ((line = reader.readLine()) != null) {
      content.append(line).append('\n');
      if(isGetCharsetFromContent) {
        String charsetInContent = ReUtil.get(CHARSET_PATTERN, line, 1);
        if(StrUtil.isBlank(charsetInContent) == false) {
          charset = charsetInContent;
          reader = new BufferedReader(new InputStreamReader(in, charset));
          isGetCharsetFromContent = true;
        }
      }
    }

    return content.toString();
  }
  //----------------------------------------------------------------------------------------- Private method start end
}
TOP

Related Classes of com.xiaoleilu.hutool.HttpUtil

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.