cokr.xit.foundation.web.Http 추가
parent
1556ce7ad6
commit
1c5556c038
@ -0,0 +1,293 @@
|
||||
package cokr.xit.foundation.web;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import cokr.xit.foundation.AbstractComponent;
|
||||
|
||||
/**Http 통신 유틸리티
|
||||
* <p>다음은 사용례이다.
|
||||
* <pre><code> new Http().get(
|
||||
* "https://...",
|
||||
* new Http.Conf()
|
||||
* // .header("Content-Type", "application/x-www-form-urlencoded")
|
||||
* .param("param0", "value0")
|
||||
* .param("param1", "value1")
|
||||
* .onResponse(resp -> System.out.println(resp));
|
||||
* );</code></pre>
|
||||
* @author mjkhan
|
||||
*/
|
||||
public class Http extends AbstractComponent {
|
||||
/**http 통신 시 설정하는 옵션
|
||||
* @author mjkhan
|
||||
*/
|
||||
public static class Conf {
|
||||
private String charset;
|
||||
private String url;
|
||||
private String method;
|
||||
private LinkedHashMap<String, String>
|
||||
params,
|
||||
headers;
|
||||
private int timeout;
|
||||
private Consumer<Response> handler = System.out::println;
|
||||
|
||||
/**파라미터 인코딩에 사용하는 문자셋의 이름을 반환한다.
|
||||
* @return 파라미터 인코딩에 사용하는 문자셋의 이름
|
||||
*/
|
||||
protected String charset() {
|
||||
return ifEmpty(charset, () -> "UTF-8");
|
||||
}
|
||||
|
||||
/**파라미터 인코딩에 사용하는 문자셋의 이름을 설정한다.
|
||||
* @param charset 파라미터 인코딩에 사용하는 문자셋의 이름
|
||||
* @return 현재 Conf
|
||||
*/
|
||||
public Conf charset(String charset) {
|
||||
this.charset = charset;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**http로 접속할 URL을 반환한다.
|
||||
* @return URL
|
||||
* @throws Exception
|
||||
*/
|
||||
protected URL url() throws Exception {
|
||||
return new URL(url);
|
||||
}
|
||||
|
||||
/**http 연결 방법을 반환한다. 디폴트는 "GET"
|
||||
* @return http 연결 방법
|
||||
*/
|
||||
protected String method() {
|
||||
return ifEmpty(method, "GET");
|
||||
}
|
||||
|
||||
/**설정한 파라미터 이름과 값들을 인코딩하여 반환한다.
|
||||
* @return 인코딩한 파라미터 이름과 값
|
||||
*/
|
||||
protected String params() {
|
||||
return !isEmpty(params) ? params.entrySet().stream().map(this::encode).collect(Collectors.joining("&")) : "";
|
||||
}
|
||||
|
||||
/**주어진 맵의 엔트리를 설정한 문자셋으로 인코딩하여 반환한다.
|
||||
* @param entry 맵 엔트리
|
||||
* @return 인코딩한 맵 엔트리
|
||||
*/
|
||||
protected String encode(Map.Entry<String, String> entry) {
|
||||
try {
|
||||
return URLEncoder.encode(entry.getKey(), charset()) + "=" + URLEncoder.encode(entry.getValue(), charset());
|
||||
} catch (Exception e) {
|
||||
throw runtimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**파라미터를 설정한다.
|
||||
* @param name 파라미터 이름
|
||||
* @param value 파라미터 값
|
||||
* @return
|
||||
*/
|
||||
public Conf param(String name, String value) {
|
||||
if (params == null)
|
||||
params = new LinkedHashMap<>();
|
||||
params.put(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**헤더를 설정한다.
|
||||
* @param name 헤더 이름
|
||||
* @param value 헤더 값
|
||||
* @return
|
||||
*/
|
||||
public Conf header(String name, String value) {
|
||||
if (headers == null)
|
||||
headers = new LinkedHashMap<>();
|
||||
headers.put(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**설정한 헤더들을 http에 설정한다.
|
||||
* @param http HttpURLConnection
|
||||
*/
|
||||
protected void setHeaders(HttpURLConnection http) {
|
||||
if (isEmpty(headers)) return;
|
||||
|
||||
headers.forEach(http::setRequestProperty);
|
||||
}
|
||||
|
||||
/**http 접속 시 타임아웃을 반환한다. 디폴트는 10000
|
||||
* @return http 접속 시 타임아웃
|
||||
*/
|
||||
protected int timeout() {
|
||||
return Math.max(timeout, 10000);
|
||||
}
|
||||
|
||||
/**http 접속 시 타임아웃을 설정한다.
|
||||
* @param timeout http 접속 시 타임아웃
|
||||
* @return 현재 Conf
|
||||
*/
|
||||
public Conf timeout(int timeout) {
|
||||
this.timeout = timeout;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**http 요청의 응답을 처리할 핸들러를 설정한다.
|
||||
* @param handler http 요청의 응답을 처리할 핸들러
|
||||
* @return 현재 Conf
|
||||
*/
|
||||
public Conf onResponse(Consumer<Response> handler) {
|
||||
this.handler = handler;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/**http 요청의 응답
|
||||
* @author mjkhan
|
||||
*/
|
||||
public static class Response {
|
||||
private int status;
|
||||
private String response;
|
||||
|
||||
/**http 요청의 응답 상태를 반환한다.
|
||||
* @return http 요청의 응답 상태
|
||||
*/
|
||||
public int getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
/**http 요청이 정상처리 응답을 받았는지 반환한다.
|
||||
* @return 정상처리 여부
|
||||
* <ul><li>정상처리 됐으면 true</li>
|
||||
* <li>그렇지 않으면 false</li>
|
||||
* </ul>
|
||||
*/
|
||||
public boolean isSuccess() {
|
||||
return status <= 299;
|
||||
}
|
||||
|
||||
/**http 요청의 응답을 반환한다.
|
||||
* @return http 요청의 응답
|
||||
*/
|
||||
public String getResponse() {
|
||||
return response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("status: %d, success: %s, response: %s", status, isSuccess(), response);
|
||||
}
|
||||
}
|
||||
|
||||
/**지정한 url로 GET 요청을 한다.
|
||||
* @param url url
|
||||
* @param conf 요청 시 설정할 옵션
|
||||
*/
|
||||
public void get(String url, Conf conf) {
|
||||
if (conf == null)
|
||||
conf = new Conf();
|
||||
conf.method = "GET";
|
||||
request(url, conf);
|
||||
}
|
||||
|
||||
/**지정한 url로 POST 요청을 한다.
|
||||
* @param url url
|
||||
* @param conf 요청 시 설정할 옵션
|
||||
*/
|
||||
public void post(String url, Conf conf) {
|
||||
if (conf == null)
|
||||
conf = new Conf();
|
||||
conf.method = "POST";
|
||||
request(url, conf);
|
||||
}
|
||||
|
||||
/**지정한 url로 요청을 보내고, 이 때 conf를 옵션으로 설정한다.
|
||||
* @param url url
|
||||
* @param conf 요청 시 설정할 옵션
|
||||
*/
|
||||
protected void request(String url, Conf conf) {
|
||||
HttpURLConnection http = null;
|
||||
try {
|
||||
conf.url = url;
|
||||
http = (HttpURLConnection)conf.url().openConnection();
|
||||
http.setRequestMethod(conf.method());
|
||||
http.setUseCaches(false);
|
||||
conf.setHeaders(http);
|
||||
http.setConnectTimeout(conf.timeout());
|
||||
http.setReadTimeout(conf.timeout());
|
||||
|
||||
setParams(conf, http);
|
||||
|
||||
Response resp = getResponse(http);
|
||||
if (conf.handler != null)
|
||||
conf.handler.accept(resp);
|
||||
} catch (Exception e) {
|
||||
if (conf.handler != null) {
|
||||
conf.handler.accept(getResponse(e));
|
||||
}
|
||||
} finally {
|
||||
if (http != null)
|
||||
http.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
/**http 요청을 할 때 파라미터를 설정한다.
|
||||
* @param conf Http.Conf
|
||||
* @param http HttpURLConnection
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void setParams(Conf conf, HttpURLConnection http) throws Exception {
|
||||
String params = conf.params();
|
||||
if (!isEmpty(params)) {
|
||||
http.setDoOutput(true);
|
||||
DataOutputStream out = new DataOutputStream(http.getOutputStream());
|
||||
out.writeBytes(params);
|
||||
out.flush();
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**http 요청의 응답을 추출한다.
|
||||
* @param http HttpURLConnection
|
||||
* @return http 요청의 응답
|
||||
* @throws Exception
|
||||
*/
|
||||
protected Response getResponse(HttpURLConnection http) throws Exception {
|
||||
Response resp = new Response();
|
||||
resp.status = http.getResponseCode();
|
||||
|
||||
try (
|
||||
InputStream input = resp.isSuccess() ? http.getInputStream() : http.getErrorStream();
|
||||
InputStreamReader inputStreamReader = new InputStreamReader(input);
|
||||
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
|
||||
) {
|
||||
String str = "";
|
||||
StringBuilder buff = new StringBuilder();
|
||||
while ((str = bufferedReader.readLine()) != null) {
|
||||
buff.append(str);
|
||||
}
|
||||
resp.response = buff.toString();
|
||||
return resp;
|
||||
} catch (Exception e) {
|
||||
return getResponse(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**http 요청 중 오류가 발생했을 때 응답을 반환한다.
|
||||
* @param t Throwable
|
||||
* @return http 요청 중 오류가 발생했을 때 응답
|
||||
*/
|
||||
protected Response getResponse(Throwable t) {
|
||||
Response resp = new Response();
|
||||
resp.status = 500;
|
||||
resp.response = rootCause(t).getMessage();
|
||||
return resp;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue