선택자
선택자는 HTTP 요청 또는 WebSocket 명령이 어떤 장치와 어떤 세션을 대상으로 하는지 식별합니다.
장치 선택자 — URL 경로
모든 장치 수준의 HTTP 경로에서 /{device_type}/{id_or_index}/… 형식으로 사용됩니다.
| 경로 예시 | 선택자 의미 |
|---|---|
inverse3/0 | 인덱스(0부터 시작) 기준 첫 번째 Inverse3 |
inverse3/A14 | 장치 ID가 A14인 Inverse3 |
inverse3/* | 모든 Inverse3 장치(와일드카드) |
*inverse/* | 모든 Inverse 계열 장치(Inverse3, Inverse3x, Minverse) |
inverse3:left/0 | 인덱스 기준 첫 번째 왼손잡이 Inverse3 |
*inverse:right/0 | 인덱스 기준 첫 번째 오른손잡이 Inverse 계열 장치 |
verse_grip/0 | 인덱스 기준 첫 번째 유선 VerseGrip |
wireless_verse_grip/* | 모든 무선 VerseGrip |
*verse_grip/* | 모든 VerseGrip 계열 장치(유선, 무선, 커스텀) |
*verse_grip:custom/0 | 인덱스 기준 첫 번째 커스텀 VerseGrip(custom_verse_grip/0과 동일) |
클래스 필터는 인덱싱 이전에 적용됩니다
<type>:<class>/<N> 선택자는 먼저 클래스 필터를 적용한 다음, 필터링된 집합을 대상으로 인덱싱합니다. <N>은 원본 장치 목록이 아니라 필터링된 목록에서의 위치를 가리킵니다:
*inverse:left/0— 왼손잡이 Inverse 계열 장치 중 0번째 장치입니다. Inverse 장치 세 대가 연결되어 있다면(오른손, 왼손, 오른손 순서) 이 선택자는 두 번째 장치로 해석됩니다. 인덱스0인 장치를 먼저 고른 뒤 "왼손잡이여야 함"으로 거르는 방식이 아닙니다.inverse3:right/0— 오른손잡이 Inverse3 중 0번째 장치.*inverse:left/3— 왼손잡이 Inverse 계열 장치가 네 대 미만 연결되어 있으면, 전체 Inverse 장치가 네 대를 넘더라도404를 반환합니다.
같은 규칙이 와일드카드 선택자에도 적용됩니다. *inverse/*와 *verse_grip/*는 해당 계열의 모든 장치와 일치하며, 이러한 선택자를 대상으로 하는 POST 및 DELETE 요청은 첫 번째 장치만이 아니라 일치하는 모든 장치에 작업을 적용합니다.
규칙:
GET은 (모호하므로) 와일드카드 선택자를 거부합니다 →400POST와DELETE는 와일드카드를 허용합니다 — 작업은 일치하는 모든 장치에 적용됩니다404응답은no device matches selector '<sel>'형식을 사용합니다. 여기서<sel>은 수신된 원래 선택자 표현식입니다
지원되는 {device_type} 값: inverse3, verse_grip, wireless_verse_grip, 또는 계열 와일드카드 *inverse, *verse_grip.
세션 선택자 — ?session=<expr> 쿼리 매개변수
세션 범위의 HTTP 엔드포인트(basis, mount, preset, filters, navigation, SDF)는 어떤 세션의 컨텍스트에서 작업할지 식별하기 위해 ?session=<expr> 쿼리 매개변수가 필요합니다.
| 표현식 | 의미 |
|---|---|
| (생략) | 모든 세션(DELETE에서만 허용) |
#123 또는 123 | 숫자 ID가 123인 세션 |
:0 | 인덱스 기준 첫 번째 세션 |
:-1 | 인덱스 기준 마지막 세션 |
profile_name | 이 프로필을 가진 첫 번째 세션(모호할 수 있음) |
profile_name:0 | 이 프로필을 가진 세션 중 인덱스 0번 세션 |
:default:0 | 프로필 default를 가진 세션 중 인덱스 0번 세션 |
co.haply.hub::*:0 | 프로필이 co.haply.hub::로 시작하는 첫 번째 세션(glob 와일드카드) |
:co.haply.hub::*:-1 | co.haply.hub:: 네임스페이스의 마지막 세션 |
예시:
GET /inverse3/0/config/navigation?session=:default:0
프로필 이름 와일드카드
프로필 패턴은 두 가지 glob 메타문자를 허용합니다:
| 메타문자 | 의미 |
|---|---|
* | 임의의 문자 시퀀스와 일치합니다(빈 문자열 포함) |
? | 정확히 한 문자와 일치합니다 |
그 밖의 모든 문자(:, ., -, [, ] 포함)는 문자 그대로 일치합니다([abc]와 같은 문자 클래스는 지원되지 않습니다). 일치 여부는 대소문자를 구분합니다.
단독 *(또는 all)은 기존과 같이 모든 세션을 의미합니다. 이름이 *로 시작하는 프로필과 일치시키려면 다른 문자를 하나 이상 포함하십시오(예: *foo).
유용한 패턴:
co.haply.hub::*—co.haply.hub::네임스페이스에 속한 모든 프로필*-update—-update로 끝나는 모든 프로필co.haply.*:*— 네임스페이스가co.haply.로 시작하는 모든 프로필defaul?—defaul로 시작하는 7자 길이의 모든 프로필
와일드카드 패턴은 단독으로는 모호합니다(둘 이상의 세션과 일치할 수 있습니다). GET / POST 엔드포인트에서 사용하려면 끝에 :<index>를 붙여 대상을 명확히 지정합니다:
# First session in the Haply Hub namespace
GET /inverse3/0/config/basis?session=co.haply.hub::*:0
# Last session in a Unity namespace
GET /inverse3/0/config/mount?session=:co.haply.unity::*:-1
인덱스가 없는 모호한 와일드카드는 GET/POST에서 400으로 거부됩니다. 여러 세션과의 일치를 명시적으로 허용하는 경로에서는 허용되며, 이는 GET /sessions/<sel>(일치하는 모든 항목을 반환)과 DELETE 엔드포인트(일치하는 모든 대상에 적용)입니다.
세션 선택자 — URL 경로
/sessions/{selector} 엔드포인트는 경로 매개변수와 동일한 표현식을 허용합니다. 단일 세션을 조회하거나 해당 세션이 존재하는지 확인할 때 유용합니다:
GET /sessions # list all active sessions
GET /sessions/:default:0 # one session by profile + index
GET /sessions/:-1 # last active session
GET /sessions/#42 # session id 42
GET /sessions/co.haply.hub::* # every session in the co.haply.hub:: namespace
GET /sessions/co.haply.hub::*:0 # first session in that namespace
이는 GET /sessions?session=<selector>와 기능적으로 동일합니다. 두 경로는 같은 핸들러를 호출합니다. GET /sessions/<sel>은 :<index> 접미사 없이 모호한 와일드카드 패턴을 허용하는 몇 안 되는 엔드포인트 중 하나이며, GET /sessions와 같은 목록 래퍼 형식으로 일치하는 모든 항목을 반환합니다.
#42와 *가 포함된 프로필 패턴을 포함해 위의 모든 선택자 형식은 표준 HTTP 클라이언트(Python requests, libhv, curl, fetch)가 그대로 전송합니다. 클라이언트 측 URL 인코딩은 필요하지 않습니다. 셸에서는 # 또는 *가 포함된 토큰을 따옴표로 묶으십시오(예: --session "#42", --session "co.haply.hub::*:0"). 그렇게 하면 셸이 이를 주석으로 처리하거나 로컬 파일에 대해 glob 확장을 수행하지 않습니다.
한 가지 예외: ? glob 메타문자는 경로에서 URL 쿼리의 구분자입니다. 경로 형식 선택자(예: /sessions/defaul?:0)에서는 %3F로 퍼센트 인코딩해야 합니다 — GET /sessions/defaul%3F:0. 쿼리 형식 선택자(?session=defaul?:0)에서는 첫 번째 ?만 쿼리를 나누며, 이후의 ? 문자는 변경 없이 그대로 전달됩니다.
WebSocket 연결에서는 사용자 자신이 곧 세션입니다. configure 및 commands 항목은 현재 세션의 장치를 자동으로 대상으로 합니다. 세션 선택자는 HTTP 요청(세션 간 원격 제어 포함, 세션 참조)에서만 필요합니다.