URL appendingComponent와 QueryString - Team-HGD/SniffMEET GitHub Wiki

문제

이런 식으로 appendingComponent 메서드를 통해 ?를 넣어주게 되면

absoluteURL = absoluteURL.appendingPathComponent("?" + queryPathString)

예상

https://example.com/user?id=1

실제

https://example.com/user%3Fid=1

그냥 퍼센트 인코딩이라 별 상관없는거 아냐?라고 생각할 수 있지만,

?를 경로로 인식하면서 요청에 실패하게 된다.

해결방법

  1. 문자열로 직접 만들면 된다!
public var absoluteURL: URL  {
        var absoluteURLString: String = baseURL.absoluteString + "/"
        // 의미없는 / 제거
        let pathComponents = path.components(separatedBy: "/")
                                .compactMap{ $0.isEmpty ? nil : $0 }
        let queryPathString: String = query?.map{ "\($0)=\($1)" }.joined(separator: "&") ?? ""
        absoluteURLString += pathComponents.joined(separator: "/")
        if !queryPathString.isEmpty {
            absoluteURLString += "?\(queryPathString)"
        }
    
        return URL(string: absoluteURLString) ?? baseURL
    }
  1. URLComponents를 통해 만들기

URLComponents에서 조금 더 안전하게 처리할 수 있다.

public var absoluteURL: URL  {
        let absoluteURLString: String = baseURL.absoluteString.trimmingCharacters(
            in: CharacterSet(charactersIn: "/")
        )
        var components = URLComponents(string: absoluteURLString)
        components?.queryItems = query?.compactMap {
            URLQueryItem(name: $0, value: $1)
        }
        let previousPath = components?.path ?? ""
        components?.path = previousPath + "/\(path)"
        return components?.url ?? baseURL
    }