-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: 함수형 인터페이스를 활용한 http 호출 추상화 (#9)
* docs: update README.md * refactor: 기존 requestProduct 로직 개선 * feat: 함수형 인터페이스를 활용한 http 호출 추상화 * feat: httpClient5 호출부 로직 각 클래스 단위로 분리 * chore: github action 불필요 JDK initialize 로직 삭제
- Loading branch information
Showing
17 changed files
with
263 additions
and
160 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,86 +1,76 @@ | ||
package io.codef.api; | ||
|
||
import com.alibaba.fastjson2.JSON; | ||
import com.alibaba.fastjson2.JSONObject; | ||
import io.codef.api.constants.CodefHost; | ||
import io.codef.api.constants.CodefPath; | ||
import io.codef.api.dto.EasyCodefRequest; | ||
import io.codef.api.dto.EasyCodefResponse; | ||
import io.codef.api.error.CodefError; | ||
import io.codef.api.error.CodefException; | ||
import io.codef.api.util.HttpClientUtil; | ||
import org.apache.hc.client5.http.classic.methods.HttpPost; | ||
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; | ||
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; | ||
import org.apache.hc.core5.http.io.entity.EntityUtils; | ||
import org.apache.hc.core5.http.io.entity.StringEntity; | ||
|
||
import java.net.URLDecoder; | ||
import java.nio.charset.StandardCharsets; | ||
|
||
import static org.apache.hc.client5.http.auth.StandardAuthScheme.BASIC; | ||
import static org.apache.hc.client5.http.auth.StandardAuthScheme.BEARER; | ||
import static io.codef.api.dto.EasyCodefRequest.BASIC_TOKEN_FORMAT; | ||
import static io.codef.api.dto.EasyCodefRequest.BEARER_TOKEN_FORMAT; | ||
import static org.apache.hc.core5.http.HttpHeaders.AUTHORIZATION; | ||
|
||
final class EasyCodefConnector { | ||
public final class EasyCodefConnector { | ||
private static final ResponseHandler responseHandler = new ResponseHandler(); | ||
|
||
static String issueToken(String codefOAuthToken) { | ||
System.out.println("issue Token !!!\n\n"); | ||
final String BASIC_TOKEN_FORMAT = BASIC + " %s"; | ||
final String accessTokenParameter = "access_token"; | ||
|
||
try (CloseableHttpClient httpClient = HttpClientBuilder.create().build()) { | ||
HttpPost httpPost = new HttpPost(CodefHost.CODEF_OAUTH_SERVER + CodefPath.ISSUE_TOKEN); | ||
httpPost.addHeader(AUTHORIZATION, String.format(BASIC_TOKEN_FORMAT, codefOAuthToken)); | ||
private EasyCodefConnector() { | ||
throw new IllegalStateException("Utility class"); | ||
} | ||
|
||
return httpClient.execute(httpPost, response -> { | ||
switch (response.getCode()) { | ||
case 200: | ||
break; | ||
case 401: | ||
throw CodefException.from(CodefError.OAUTH_UNAUTHORIZED); | ||
case 500: | ||
default: | ||
throw CodefException.from(CodefError.OAUTH_INTERNAL_ERROR); | ||
} | ||
public static String requestToken( | ||
String codefOAuthToken | ||
) throws CodefException { | ||
HttpPost request = createTokenRequest(codefOAuthToken); | ||
return executeRequest(request, responseHandler::handleTokenResponse); | ||
} | ||
|
||
String httpResponse = EntityUtils.toString(response.getEntity()); | ||
public static EasyCodefResponse requestProduct( | ||
EasyCodefRequest request, | ||
EasyCodefToken token, | ||
String requestUrl | ||
) throws CodefException { | ||
HttpPost httpRequest = createProductRequest(request, token, requestUrl); | ||
return executeRequest(httpRequest, responseHandler::handleProductResponse); | ||
} | ||
|
||
return JSON.parseObject(httpResponse).getString(accessTokenParameter); | ||
}); | ||
} catch (CodefException exception) { | ||
throw exception; | ||
} catch (Exception exception) { | ||
throw CodefException.of(CodefError.OAUTH_CONNECTION_ERROR, exception); | ||
} | ||
private static HttpPost createTokenRequest(String codefOAuthToken) { | ||
HttpPost httpPost = new HttpPost(CodefHost.CODEF_OAUTH_SERVER + CodefPath.ISSUE_TOKEN); | ||
httpPost.addHeader(AUTHORIZATION, String.format(BASIC_TOKEN_FORMAT, codefOAuthToken)); | ||
return httpPost; | ||
} | ||
|
||
static EasyCodefResponse requestProduct( | ||
private static HttpPost createProductRequest( | ||
EasyCodefRequest request, | ||
EasyCodefToken token, | ||
String requestUrl | ||
) { | ||
final String BEARER_TOKEN_FORMAT = BEARER + " %s"; | ||
|
||
try (CloseableHttpClient httpClient = HttpClientBuilder.create().build()) { | ||
HttpPost httpPost = new HttpPost(requestUrl); | ||
httpPost.addHeader(AUTHORIZATION, String.format(BEARER_TOKEN_FORMAT, token.getAccessToken())); | ||
String rawRequest = JSON.toJSONString(request.requestParams()); | ||
httpPost.setEntity(new StringEntity(rawRequest)); | ||
HttpPost httpPost = new HttpPost(requestUrl); | ||
httpPost.addHeader(AUTHORIZATION, String.format(BEARER_TOKEN_FORMAT, token.getAccessToken())); | ||
|
||
return httpClient.execute(httpPost, response -> { | ||
String httpResponse = EntityUtils.toString(response.getEntity()); | ||
String decodedResponse = URLDecoder.decode(httpResponse, "UTF-8"); | ||
String rawRequest = JSON.toJSONString(request.requestBody()); | ||
httpPost.setEntity(new StringEntity(rawRequest, StandardCharsets.UTF_8)); | ||
|
||
// TODO {"error":"invalid_token","error_description":"Cannot convert access token to JSON","code":"CF-09990","message":"OAUTH2.0 토큰 에러입니다. 메시지를 확인하세요."} | ||
JSONObject jsonResponseObject = JSON.parseObject(decodedResponse); | ||
return httpPost; | ||
} | ||
|
||
EasyCodefResponse.Result resultResponse = jsonResponseObject.getJSONObject("result").to(EasyCodefResponse.Result.class); | ||
Object dataResponse = jsonResponseObject.getJSONObject("data").to(Object.class); | ||
return new EasyCodefResponse(resultResponse, dataResponse); | ||
}); | ||
} catch (CodefException exception) { | ||
throw exception; | ||
} catch (Exception exception) { | ||
throw CodefException.of(CodefError.OAUTH_CONNECTION_ERROR, exception); | ||
private static <T> T executeRequest( | ||
HttpPost request, | ||
ResponseProcessor<T> processor | ||
) { | ||
try (CloseableHttpClient httpClient = HttpClientUtil.createClient()) { | ||
return httpClient.execute(request, processor::process); | ||
} catch (CodefException e) { | ||
throw e; | ||
} catch (Exception e) { | ||
throw CodefException.of(CodefError.INTERNAL_SERVER_ERROR, e); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
package io.codef.api; | ||
|
||
import com.alibaba.fastjson2.JSON; | ||
import com.alibaba.fastjson2.JSONObject; | ||
import io.codef.api.dto.EasyCodefResponse; | ||
import io.codef.api.error.CodefError; | ||
import io.codef.api.error.CodefException; | ||
import org.apache.hc.core5.http.ClassicHttpResponse; | ||
import org.apache.hc.core5.http.HttpStatus; | ||
import org.apache.hc.core5.http.ParseException; | ||
import org.apache.hc.core5.http.io.entity.EntityUtils; | ||
|
||
import java.io.IOException; | ||
import java.net.URLDecoder; | ||
import java.nio.charset.StandardCharsets; | ||
|
||
import static io.codef.api.dto.EasyCodefRequest.ACCESS_TOKEN; | ||
import static io.codef.api.dto.EasyCodefResponse.DATA; | ||
import static io.codef.api.dto.EasyCodefResponse.RESULT; | ||
|
||
public class ResponseHandler { | ||
public ResponseHandler() { | ||
} | ||
|
||
public String handleTokenResponse(ClassicHttpResponse response) { | ||
try { | ||
final String responseBody = EntityUtils.toString(response.getEntity()); | ||
|
||
return switch (response.getCode()) { | ||
case HttpStatus.SC_OK -> JSON.parseObject(responseBody).getString(ACCESS_TOKEN); | ||
case HttpStatus.SC_UNAUTHORIZED -> throw CodefException.of(CodefError.OAUTH_UNAUTHORIZED, responseBody); | ||
default -> throw CodefException.of(CodefError.OAUTH_INTERNAL_ERROR, responseBody); | ||
}; | ||
} catch (IOException exception) { | ||
throw CodefException.of(CodefError.IO_ERROR, exception); | ||
} catch (ParseException exception) { | ||
throw CodefException.of(CodefError.PARSE_ERROR, exception); | ||
} | ||
} | ||
|
||
public EasyCodefResponse handleProductResponse( | ||
ClassicHttpResponse response | ||
) throws CodefException { | ||
try { | ||
final String httpResponse = EntityUtils.toString(response.getEntity()); | ||
final int httpStatusCode = response.getCode(); | ||
|
||
return switch (httpStatusCode) { | ||
case HttpStatus.SC_OK -> { | ||
final String decodedResponse = URLDecoder.decode(httpResponse, StandardCharsets.UTF_8); | ||
yield parseProductResponse(decodedResponse); | ||
} | ||
case HttpStatus.SC_UNAUTHORIZED -> throw CodefException.of(CodefError.OAUTH_UNAUTHORIZED, httpResponse); | ||
default -> throw CodefException.of(CodefError.OAUTH_INTERNAL_ERROR, httpResponse); | ||
}; | ||
} catch (IOException exception) { | ||
throw CodefException.of(CodefError.IO_ERROR, exception); | ||
} catch (ParseException exception) { | ||
throw CodefException.of(CodefError.PARSE_ERROR, exception); | ||
} | ||
} | ||
|
||
private EasyCodefResponse parseProductResponse(String decodedResponse) { | ||
JSONObject jsonResponseObject = JSON.parseObject(decodedResponse); | ||
|
||
EasyCodefResponse.Result resultResponse = jsonResponseObject.getJSONObject(RESULT).to(EasyCodefResponse.Result.class); | ||
|
||
Object dataResponse = jsonResponseObject.getJSONObject(DATA).to(Object.class); | ||
|
||
return new EasyCodefResponse(resultResponse, dataResponse); | ||
} | ||
} |
Oops, something went wrong.