[Go]

[Go] 고랭으로 간단한 HTTP Server 작성 (Writing a simple HTTP Server with Golang)

dogfootman 2023. 7. 23. 23:33

개요

고랭으로 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 형식으로 결과를 반환

결과 확인

 

 

사용툴: https://www.postman.com/