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