[WebApp] Protocal22-API 사용예제 (GoLang)
[WebApp] Protocal22-API 사용예제2
시작하기 전에
이 문서는 Dabory OwnerKey API for WebApp을 사용해 main app과 guest app 개발시 필요한 참고 정보를 안내합니다.
WebApp 사용예제
2. WebApp 사용 예제
📌 GateToken 발급 스케줄러
package main
func main() {
// 새로운 고루틴(Goroutine) 실행: 백그라운드에서 주기적으로 실행됨
go func() {
for {
// 1. UpdateGateTokenIfNeeded() 함수 호출 (GateToken 발급 및 업데이트)
err := controllers_func.UpdateGateTokenIfNeeded()
// 2. 만약 에러가 발생하면 로그를 남김
if err != nil {
e.ErrLog("UpdateGateTokenIfNeeded Error", err)
}
// 3. 2초 동안 대기 후 반복 (즉, 2초마다 실행됨)
time.Sleep(2 * time.Second)
}
}()
// 주의: main 함수가 종료되면 고루틴도 종료됨
select {} // main 함수가 종료되지 않도록 무한 대기
}
📌 "OwnerKey"를 활용한 GateToken, BackUrl 반환
Host의 dabory-app/gate-token-get을 호출 -> Host -> main_api (GateToken) 반환
// GateToken을 요청하는 함수
func UpdateGateTokenIfNeeded() error {
myOwnerKey := "My_OwnerKey" //OwnerKey (GateToken 발급 주체 선정을 위해 사용)
// GateToken을 요청 (OwnerKey를 사용하여 요청)
err := locals.GuestGateTokenGets(myOwnerKey)
if err != nil {
fmt.Println("GateToken 요청 실패:", err)
return err
}
return nil
}
type AppApi struct {
ApiUrl string
GateToken string
}
var GAppApis [2]AppApi // GateToken, ApiUrl 저장 장소
func GuestGateTokenGets(myOnwerKey string) error {
appType := 0 //Dbupdate
// 0:keypair, 1:Dbu // "SsoConnString" Must be Deprecated
var err error
if myOnwerKey != "" {
// e.LogStr("lskdjqfals", e.LogFuncName()+"; GuestGateTokenOwner with OwnerKey: "+myOnwerKey)
_, _, err = GuestGateTokenOwner(appType, "https://host_domain_URL.com", myOnwerKey) // app type -> OwnerCode
// Host Domain URL, OwnerKey를 매개변수로 던짐
if err != nil {
return e.ErrLog(e.FuncRun("23rfsr3qrase", e.CurrFuncName()), err)
}
}
return nil
}
func GuestGateTokenOwner(appType int, pivotUrl string, ownerKey string) (string, string, error) { // HOST URL/dabory-app -> pivot URL
var appTypeCode string
if appType == 0 {
appTypeCode = "keypair"
} else if appType == 1 {
appTypeCode = "dbupdate"
}
if GAppApis[appType].GateToken != "" { // 할당되어 있는 경우 (이미 GateToken이 있는 경우)
// fmt.Println("34092ujfa : "+"Using GateToken in ARRAY to access : ", GAppApis[0].GateToken)
} else { // (GateToken이 없는 경우 발급 로직)
fmt.Println("34092ujfa : " + "isn't exist GateToken in ARRAY to access ")
vGt := &GateTokenGetReq{
OwnerKey: ownerKey,
}
bodyBytes, _ := json.Marshal(vGt)
frontUrl := pivotUrl + "/dabory-app/gate-token-get"
msgBytes, staInt, err := HttpResponseSimplePost("POST", frontUrl, bodyBytes)
// Strong -> Host Lalavel로 Http 요청 -> Lalavel -> main_api로 GateToken 요청
e.LogStr("23rfsr3qr-GateTokenGetReq", e.LogFuncName()+"; Raravel frontUrl : "+frontUrl)
if err != nil {
return "", "", e.ErrLog(e.FuncRun("45425fd34sd-The HTTP request "+frontUrl, e.CurrFuncName()), err)
}
if staInt != 200 {
TrackFailure() // 요청 실패 시 실패 기록 추가
fmt.Println("GateToken 요청 실패:", err, "(최근 1시간 내 실패 횟수:", len(failTimestamps), ")", "반환 Code : ", staInt)
// 최근 1시간 동안 실패 횟수가 maxFailures(3) 이상이면 프로그램 종료
if len(failTimestamps) >= maxFailures {
fmt.Println("1시간 내 GateToken 요청이", maxFailures, "번 실패 -> 스케줄러를 종료")
os.Exit(1) // 프로그램 종료
}
return "", "", errors.New(e.FuncRun("87ty344ra3-Request Fail "+string(msgBytes), e.CurrFuncName()))
}
failTimestamps = []int64{} // 성공 시 실패 기록 초기화
ret := &struct {
ApiUrl string
GateToken string
}{}
if err := json.Unmarshal(msgBytes, ret); err != nil { // GateToken과 BackendUrl을 ret 구조체에 할당
return "", "", e.ErrLog(e.FuncRun("45425fd34sd-Json Format "+frontUrl, e.CurrFuncName()), err)
}
// 새로 받은 GateToken을 전역 변수에 저장
GAppApis[appType].ApiUrl = ret.ApiUrl
GAppApis[appType].GateToken = ret.GateToken
e.OkLog("Just Added GateToken in ARRAY to access AppType: " + appTypeCode)
e.OkLog("Just Added GateToken in ARRAY to access AppType: " + ret.GateToken)
e.OkLog("Just Added GateToken in ARRAY to access AppType: " + ret.ApiUrl) // main_api URL
}
return GAppApis[appType].ApiUrl, GAppApis[appType].GateToken, nil
}
📌 발급받은 GateToken을 사용하여 main_api 요청
// 🔹 API 요청을 수행하는 함수
func process() {
// 1. GateToken과 API URL 가져오기
apiUrl := locals.GAppApis[0].ApiUrl // API 요청을 보낼 기본 URL
gateToken := locals.GAppApis[0].GateToken // API 요청 시 필요한 인증 토큰
// 2. 요청할 API 엔드포인트 설정 (credit-page 요청)
mainApiURL := apiUrl + "/credit-page"
// 3. 요청 바디 구성 (전달할 데이터)
requestBody := map[string]interface{}{
"PageVars": map[string]interface{}{
"Fields": "credit_no",
"Limit": 1,
"Desc": "id",
"MyFilter": "",
"QueryCnt": 0,
"Query": "",
"Asc": "",
"Offset": 0,
"ReturnJson": "",
},
}
// 4. API 요청 실행 (GateToken 포함)
Body, err := RequestWithGateToken(mainApiURL, gateToken, requestBody)
if err != nil {
// 요청 실패 시 에러 로그 출력
e.ErrLog("API 요청 실패: ", err)
return
}
// 5. 응답 데이터 출력
fmt.Println("API 응답 데이터:", string(Body))
}
📌 저장된 GateToken으로 요청 (만료된 GateToken 재 발급)
// GateToken을 사용하여 API 요청을 보내는 함수
func RequestWithGateToken(mainApiURL string, gateToken string, requestBody map[string]interface{}) ([]byte, error) {
// 1. HTTP 요청 보내기 (기존 GateToken 사용)
resp, body, err := SendHttpRequest(mainApiURL, gateToken, requestBody)
if err != nil {
fmt.Println("HTTP 요청 실패:", err)
return nil, err
}
defer resp.Body.Close()
fmt.Println("응답 본문:", string(body)) // API 응답 출력
// 2. 응답 코드가 505라면 -> GateToken 만료 (새로운 GateToken 발급 필요)
if resp.StatusCode == 505 {
fmt.Println("GateToken 만료! 새로운 GateToken 발급 시도..")
// 기존 만료된 GateToken 초기화
locals.GAppApis[0] = locals.AppApi{}
// 스케줄러가 새로운 GateToken이 얻어올 때까지 대기 (최대 5초마다 확인)
for locals.GAppApis[0].GateToken == "" {
fmt.Println("새로운 GateToken 발급 중..")
time.Sleep(5 * time.Second)
}
fmt.Println("새로운 GateToken 발급 완료!")
// 새로운 GateToken으로 API 재요청
newGateToken := locals.GAppApis[0].GateToken
resp, body, err := SendHttpRequest(mainApiURL, newGateToken, requestBody)
if err != nil {
fmt.Println("HTTP 요청 실패:", err)
return nil, err
}
defer resp.Body.Close()
// 새로운 요청 응답 확인
if resp.StatusCode == 200 {
e.OkLog("새로운 GateToken을 사용한 HTTP 요청 성공!")
return body, nil
} else {
return nil, fmt.Errorf("새로운 GateToken 요청 실패, 상태 코드: %d", resp.StatusCode)
}
}
// 기존 GateToken으로 요청 성공한 경우
e.OkLog("기존 GateToken을 사용한 HTTP 요청 성공!")
return body, nil
}
// HTTP 요청을 보내는 함수
func SendHttpRequest(mainApiURL string, gateToken string, requestBody map[string]interface{}) (*http.Response, []byte, error) {
// 1. JSON 데이터로 변환
jsonData, err := json.Marshal(requestBody)
if err != nil {
fmt.Println("JSON 변환 실패:", err)
return nil, nil, err
}
// 2. HTTP 요청 생성 (POST 요청)
req, err := http.NewRequest("POST", mainApiURL, bytes.NewBuffer(jsonData))
if err != nil {
fmt.Println("HTTP 요청 생성 실패:", err)
return nil, nil, err
}
// 3. HTTP 헤더 설정 (GateToken 포함)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("GateToken", gateToken)
// 4. HTTP 요청 실행
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
fmt.Println("HTTP 요청 실패:", err)
return nil, nil, err
}
// 5. 응답 데이터 읽기
body, err := io.ReadAll(resp.Body)
if err != nil {
fmt.Println("응답 본문 읽기 실패:", err)
return nil, nil, err
}
// 6. 응답 로그 출력
fmt.Println("응답 코드:", resp.StatusCode)
fmt.Println("응답 본문:", string(body))
return resp, body, nil
}
No Comments