-
[Ktor] tailcard로 URL 파라미터 수집하기Ktor 2023. 1. 25. 22:53
오브젝트 스토리지 api를 개발하면서 슬래시가 포함된 URL 경로를 하나의 파라미터로 수집해야 하는 상황이 생겼다.
버킷 내 폴더(실제로 폴더는 아니지만 path형식으로 구분하므로 이 글에서만 폴더라고 지칭)가 있는 경우, path형식의 오브젝트 키를 파라미터로 수집해서 넘겨야하는데, 보통 URL 파라미터는 슬래시로 구분되어 path parameter를 사용해도 해당 엔드포인트에 매칭이 되지 않았다.
예를들어 오브젝트 키가
one/two/three
인 경우,get("/{objectKey}") { val objectKey = call.parameters["objectKey"] }
그냥 path parameter를 쓸 경우 매칭되는 URL을 찾지 못해 예외가 발생한다.
Ktor에서는 이런 상황을 해결하기 위해 tailcard문자를 지원한다.
가변인자를 a... 이라고 표시하는 것과 비슷하게, tailcard문자를 쓰면 나머지 경로들까지 모두 해당 파라미터로 수집할 수 있다.
사용예시는 다음과 같다.
get("/{objectKey...}") { val objectKey = call.parameters.getAll["objectKey"] } // objectKey: List<String>?
objectKey뒤에 ...을 붙여서 나머지 모든 URL 경로를 수집한다.
이 때는 call.parameters.getAll로 수집하고, 타입은 문자열 리스트가 된다.
물론 인자가 한 개여도 정상 수집된다.
그러나 내 경우, 수집해온 파라미터들을 다시 하나의 완성된 문자열로 만들어야 한다.
여기까지만 하면 objectKey는 one, two, three가 담긴 리스트인데, 내가 원하는 결과는 one/two/three 문자열이다.
따라서 다시 path형식으로 합쳐주는 과정이 필요하다. 코틀린의 문자열 메소드를 사용했다.
get("/{objectKey...}") { val objectKeyList = call.parameters.getAll["objectKey"] val objectKey = objectKeyList.joinToString("/") } // result: one/two/three
joinToString은 배열을 하나의 문자열로 합칠 때 사용하고, seperator, prefix, suffix를 지정할 수 있다.
구분자에 슬래시를 지정했다.
이렇게 하면 스토리지의 폴더구조에 상관없이 요청으로부터 오브젝트 키를 정확히 수집할 수 있다.
추가로, 테일카드만 단독으로 쓸 경우 나머지 path에 관계없이 직전의 URL에 매칭시켜준다.
예를들어 /user/{...} 은 /user, 그리고 /user/other/theOther 모두에 매칭된다.
이는 와일드카드문자(*)과 미묘한 차이가 있다. 와일드카드를 쓸 경우
/user/*은 /user/other/theOther과 매칭되지만 /user에는 매치되지 않는다.