개요
고랭으로 HTTP 서버 작성
1. Hello World
func main() {
http.HandleFunc("/", handler)
fmt.Println("Start Http Server: http://localhost:8080")
err := http.ListenAndServe(":8080", nil)
if err != nil {
fmt.Println("Error:", err)
}
}
http.DefaultServeMux에 기본적으로 핸들러가 등록
포트를 지정해서 대기
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello World")
}
핸들러 작성
결과 값 확인
2. 임의 로그인 api 작성
func main() {
...
http.HandleFunc("/login", loginHandler)
...
}
같은 방법으로 로그인 핸들러도 추가
// 임시 유저 정보
var users = map[string]string{
"user1": "1234",
}
// LoginRequest 구조체
type LoginRequest struct {
Username string `json:"username"`
Password string `json:"password"`
}
// LoginResponse 구조체
type LoginResponse struct {
Token string `json:"token"`
}
// login API 핸들러
func loginHandler(w http.ResponseWriter, r *http.Request) {
// JSON 형식의 요청을 디코딩
var request LoginRequest
err := json.NewDecoder(r.Body).Decode(&request)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
fmt.Fprintln(w, "잘못된 JSON 요청")
return
}
// 사용자 인증
password, ok := users[request.Username]
if !ok || password != request.Password {
w.WriteHeader(http.StatusUnauthorized)
fmt.Fprintln(w, "인증 실패")
return
}
// 인증 성공 시 토큰을 반환
// 테스트용으로 token"으로 반환
response := LoginResponse{Token: "token"}
// JSON 형식으로 응답을 반환
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(response)
}
요청을 JSON형식으로 읽어 들여 임의의 유저 값과 비교
인증 성공시 토큰 값 반환
결과값 확인
3. 임의의 인증정보를 필요로 하는 API작성
func main() {
...
http.HandleFunc("/shoplist", authHandler(shopListHandler))
...
}
인증이 필요한 경우 authHandler를 통해서 실제 처리 할 핸들러를 전달
func authHandler(handler func(http.ResponseWriter, *http.Request)) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// Authorization" 필드 취득
authHeader := r.Header.Get("Authorization")
if authHeader == "" {
w.WriteHeader(http.StatusUnauthorized)
fmt.Fprintln(w, "토큰이 필요")
return
}
// Bearer 토큰을 추출
splitToken := strings.Split(authHeader, " ")
if len(splitToken) != 2 || splitToken[0] != "Bearer" {
w.WriteHeader(http.StatusUnauthorized)
fmt.Fprintln(w, "잘못된 헤더")
return
}
token := splitToken[1]
// 임시 토큰값 확인
if token != "token" {
w.WriteHeader(http.StatusUnauthorized)
fmt.Fprintln(w, "잘못된 토큰")
return
}
handler(w, r)
}
}
헤드값에서 키 Aurhorization를 취득해 존재하는지 확인
-> 실제 토큰 값 취득
-> 토큰 값 비교
-> 실제 핸들러 처리
// Shop 구조체
type Shop struct {
ShopName string `json:"shop_name"`
Category string `json:"category"`
}
// ShopListResponse 구조체
type ShopListResponse struct {
ShopList []*Shop `json:"shop_list"`
}
// ShopList API 핸들러
func shopListHandler(w http.ResponseWriter, r *http.Request) {
// 상점 목록
shopList := []*Shop{
{ShopName: "상점1", Category: "의류"},
{ShopName: "상점2", Category: "전자제품"},
{ShopName: "상점3", Category: "서적"},
{ShopName: "상점4", Category: "식품"},
}
// 결과
response := &ShopListResponse{
ShopList: shopList,
}
// JSON 형식으로 반환
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(response)
}
JSON 형식으로 결과를 반환
결과 확인