Sept 15, 2021, TIL (Today I Learned) - HTTPURLResponse, MIMEType, TroubleShooting

Inwoo Hwang·2021년 9월 14일
0

TIL

목록 보기
6/8
post-thumbnail

Trouble: 네트워크 응답을 왜 받지 못하니...

상세 페이지 우측 상단의 버튼을 클릭 후 alert창에서 패스워드 입력을 한 뒤 입력한 값이 서버에 존재하는 password값과 일치할 경우 수정페이지로 화면을 전환하는 작업을 하는 중이었습니다.

isPasswordValid() 메서드를 활용해서 말이죠

private func isPasswordValid(_ passwordKeyAndValue: [String: String?]) {
        networkManager.patchSingleItem(url: "\(OpenMarketAPI.urlForSingleItemToGetPatchOrDelete)\(itemID)", texts: passwordKeyAndValue, images: nil) { response in
            if (200...299).contains(response.statusCode) {
                print("valid password")
                // 수정페이지로 전환
            } else {
                print("invalid password")
                // 패스워드 재입력 alert창 띄우기
            }
        }
    }

그런데....죽어도 response 코드가 안불리는거에요...

그래서 해당 메서드 안에 있는 networkManager 의 메서드도 살펴보았죠.

func patchSingleItem(url: String, texts: [String : Any?], images: [UIImage]?, completionHandler: @escaping (HTTPURLResponse) -> Void) {
        openMarketItemMultipartFormDataTask(httpMethod: .patch, url: url, texts: texts, imageList: images, completionHandler: { result in
            switch result {
            case .success(let response):
                NSLog("item patch succeeded with response code: \(response.statusCode)")
                completionHandler(response)
            case .failure(let networkError):
                NSLog(networkError.description)
            }
        })
    }

흠.. patch 메서드는 정상적으로 HTTPURLSession 을 가져오는 것 같은데. 더 밑으로 들어가 봐야겠습니다. openMarketItemMultipartFormDataTask() 가 문제일까요?

private func openMarketItemMultipartFormDataTask(httpMethod: HTTPMethods, url: String, texts: [String : Any?], imageList: [UIImage]?, completionHandler: @escaping(_ result: Result <HTTPURLResponse, NetworkResponseError>) -> Void) {
        
        guard let validURL = URL(string: url) else { return }
        
        var request = URLRequest(url: validURL)
        request.httpMethod = httpMethod.description
        request.httpBody = buildMultipartFormData(texts, imageList)
        
        request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
        
        dataTask = urlSession.dataTask(with: request) { data, response, error in
            if let error = error {
                NSLog(error.localizedDescription)
            }
            
            guard let successfulResponse = response as? HTTPURLResponse,
                  (200...299).contains(successfulResponse.statusCode) else {
                let failedResponse = response as? HTTPURLResponse
                
                completionHandler(.failure(NetworkResponseError.failed))
                return
            }
            
            if let mimeType = successfulResponse.mimeType,
               mimeType == "multipart/form-data" {
                completionHandler(.success(successfulResponse))
            }
        }
        dataTask?.resume()
    }

이 메서드가 문제인 것 같아서 한 번 디버깅을 해 봤습니다. breakpoint를 한 번 도배 해 보겠습니다😆

TroubleShooting: API문서를 잘 읽자

오마이갓; mime Type을 체크하는 부분에서 서버에서 보내온 mimeType은 application/json 타입인데 저는 서버에서 보내주는 데이터가 multipart/form-data 인 줄 알고 있었네요..

그래서 오랜만에 서버 API문서를 확인 해 봤습니다...

역시나 좌측의 request body는 multipart/form-data 가 맞지만...우측에 보이는 response 같은 경우 json object네요.

Common MIME types 문서를 확인 해 보니 역시나 mimetype이 application/json이어야겠네요.

if let mimeType = successfulResponse.mimeType,
               mimeType == "application/json" {
                completionHandler(.success(successfulResponse))
            }

mimeType이 application.json 타입인지 확인 하도록 로직을 수정하니 정상적으로 completionHandler가 호출이 되면서 응답을 정상적으로 받아 올 수 있었습니다.

마치며...

API문서를 제대로 숙지하지 않은 제 탓입니다 ㅠㅜ. 반성 많이하였고 앞으로는 더 꼼꼼하게 API문서를 읽고 개발하는 개발자가 되도록 노력하겠습니다.

profile
james, the enthusiastic developer

0개의 댓글