본문으로 건너뛰기

선택자

선택자는 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은 (모호하므로) 와일드카드 선택자를 거부합니다 → 400
  • POST와 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::*:-1co.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 세션에는 선택자가 필요하지 않습니다

WebSocket 연결에서는 사용자 자신이 곧 세션입니다. configure 및 commands 항목은 현재 세션의 장치를 자동으로 대상으로 합니다. 세션 선택자는 HTTP 요청(세션 간 원격 제어 포함, 세션 참조)에서만 필요합니다.