WebSub

W3C 권고안

이 문서에 대한 자세한 정보
이 버전:
https://www.w3.org/TR/2026/REC-websub-20260602/
최신 발행 버전:
https://www.w3.org/TR/websub/
최신 편집자 초안:
https://w3c.github.io/websub/
이력:
https://www.w3.org/standards/history/websub/
테스트 스위트:
https://websub.rocks/
구현 보고서:
https://websub.net/implementation-reports
편집자:
Julien Genestoux (초청 전문가)
Aaron Parecki (초청 전문가)
작성자:
Julien Genestoux
피드백:
public-socialweb@w3.org 제목 줄에 [websub] … 메시지 주제 …를 포함 (아카이브)
정오표:
정오표가 있음.
과거 작성자
Brad Fitzpatrick
Brett Slatkin
Martin Atkins
저장소
GitHub
이슈
커밋

다음도 참조: 번역.


초록

WebSub은 HTTP 웹 훅을 기반으로 모든 종류의 웹 콘텐츠 게시자와 그 구독자 간의 통신을 위한 공통 메커니즘을 제공한다. 구독 요청은 허브를 통해 중계되며, 허브는 요청의 유효성을 확인하고 검증한다. 그런 다음 허브는 새 콘텐츠 및 업데이트된 콘텐츠를 사용할 수 있게 되면 이를 구독자에게 배포한다. WebSub은 이전에 PubSubHubbub으로 알려져 있었다.

이 문서의 상태

이 절은 발행 시점의 이 문서 상태를 설명한다. 현재 W3C 발행물 목록과 이 기술 보고서의 최신 개정판은 W3C 표준 및 초안 색인에서 찾을 수 있다.

이 갱신된 명세에는 크로스 사이트 스크립팅(XSS) 위험과 관련된 완화책이 보안 고려사항 절에 추가되었으며, 이를 보고한 사람들에 대한 감사의 말도 함께 포함되어 있다.

이 문서는 Social Web Working Group권고안 트랙을 사용하여 권고안으로 발행하였다.

W3C는 이 명세가 웹의 표준으로 널리 배포될 것을 권고한다.

W3C 권고안은 폭넓은 합의 형성 이후 W3C와 그 회원들이 승인한 명세이며, 구현에 대해 Working Group 구성원들이 로열티 없는 라이선스 약속을 제공한 명세이다.

이 문서는 W3C 특허 정책에 따라 운영되는 그룹이 작성하였다. W3C는 그룹의 산출물과 관련하여 이루어진 모든 특허 공개의 공개 목록을 유지한다. 해당 페이지에는 특허를 공개하기 위한 지침도 포함되어 있다. 개인이 필수 청구항을 포함한다고 믿는 특허에 대해 실제 지식을 가지고 있는 경우, 그 개인은 W3C 특허 정책 제6절에 따라 정보를 공개해야 한다.

이 문서는 2025년 8월 18일 W3C Process Document의 적용을 받는다.

1. 정의

토픽
HTTP [RFC7230] (또는 HTTPS [RFC2818]) 리소스 URL. 변경에 대해 구독할 수 있는 단위.
허브 ("그 허브")
이 프로토콜의 양쪽을 모두 구현하는 서버(URL [URL]). 모든 허브는 누가 이를 사용할 수 있는지에 대해 자체 정책을 구현할 MAY.
게시자
토픽의 소유자. 토픽 피드가 업데이트되었을 때 허브에 알린다. 거의 모든 pubsub 시스템에서와 같이, 게시자는 구독자가 있는지 여부를 알지 못한다. 다른 pubsub 시스템에서는 게시자를 "소스"라고 부를 수 있다.
구독자
토픽의 변경 알림을 받고자 하는 엔티티(사람 또는 프로그램). 구독자는 직접 네트워크 접근이 가능해야 하며, Subscriber Callback URL로 식별된다.
구독
구독자가 해당 토픽에 대한 업데이트를 받아야 함을 나타내는, 토픽에 대한 고유한 관계. 구독의 고유 키는 튜플(Topic URL, Subscriber Callback URL)이다. 구독은 (허브의 결정에 따라) 주기적으로 갱신되어야 하는 DHCP 임대와 유사한 만료 시간을 가질 수 있다.
구독자 콜백 URL
구독자가 콘텐츠 배포 요청을 수신하기를 원하는 URL [URL].
이벤트
여러 토픽에 대한 업데이트를 발생시키는 이벤트. 발생하는 각 이벤트(예: "Brad가 Linux Community에 게시했다.")마다 여러 토픽이 영향을 받을 수 있다(예: "Brad가 게시했다." 및 "Linux community에 새 게시물이 있다"). 게시자 이벤트는 토픽이 업데이트되게 하고, 허브는 영향받은 토픽에 대한 모든 구독을 조회하여 콘텐츠를 구독자에게 전달한다.
콘텐츠 배포 알림 / (콘텐츠 배포 요청)
토픽의 콘텐츠가 어떻게 변경되었는지 설명하는 페이로드, 또는 전체 업데이트된 콘텐츠. 토픽의 콘텐츠 타입에 따라 차이(또는 "델타")는 허브가 계산하여 모든 구독자에게 보낼 수 있다.

2. 상위 수준 프로토콜 흐름

(이 절은 비규범적이다.)

WebSub 흐름 도식 구독자 게시자 허브 구독자는 게시자의 토픽 이 알리는 허브를 발견한다 구독자는 허브 에 POST하여 토픽 업데이트를 구독한다 허브는 GET으로 구독 시도를 검증한다 게시자는 새 콘텐츠를 허브에 알린다 허브는 토픽 콘텐츠를 POST로 각 구독자에게 전달한다

이 프로토콜의 이전 버전은 PubSubHubbub이라고 불렸다:

3. 적합성

이 문서의 핵심 단어 "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY" 및 "OPTIONAL"은 이 문서에서 [RFC2119]에 설명된 대로 해석되어야 한다.

3.1 적합성

비규범적으로 표시된 절뿐 아니라, 이 명세의 모든 작성 지침, 도식, 예제 및 주석은 비규범적이다. 이 명세의 그 밖의 모든 것은 규범적이다.

이 문서의 핵심 단어 MAY, MUST, MUST NOT, OPTIONAL, RECOMMENDED, REQUIRED, SHALL, SHALL NOT, SHOULDSHOULD NOT은 여기에 보이는 것처럼 모두 대문자로 나타나는 경우에, 그리고 오직 그 경우에만 BCP 14 [RFC2119] [RFC8174]에 설명된 대로 해석되어야 한다.

3.1.1 적합성 클래스

WebSub은 세 가지 역할, 즉 게시자, 구독자 및 허브를 설명한다. 이 절은 각 역할에 대한 적합성 기준을 설명한다.

3.1.1.1 게시자
  • 적합한 게시자는 탐색에 설명된 대로 주어진 리소스 URL에 대해 토픽 및 허브 URL을 광고해야 MUST 한다.
3.1.1.2 구독자

적합한 구독자는 다음을 수행한다:

  • 탐색에 설명된 대로 토픽 및 허브 URL을 발견하기 위해 지정된 순서로 각 탐색 메커니즘을 지원해야 MUST 한다.
  • 구독자가 구독 요청을 보냄에 설명된 대로 구독 요청을 보내야 MUST 한다.
  • 특정 임대 기간을 요청할 수 MAY 있다
  • 구독 요청에 비밀값을 포함할 수 MAY 있으며, 포함하는 경우 콘텐츠 배포 요청의 서명을 검증하기 위해 그 비밀값을 사용해야 MUST 한다.
  • HTTP 2xx 상태 코드로 콘텐츠 배포 요청을 확인해야 MUST 한다.
  • "unsubscribe" 메커니즘을 사용하여 구독이 비활성화되도록 요청할 수 MAY 있다.
3.1.1.3 허브

적합한 허브는 다음을 수행한다:

  • hub.callback, hub.modehub.topic 매개변수가 있는 구독 요청을 수락해야 MUST 한다.
  • hub.secret 매개변수가 있는 구독 요청을 수락해야 MUST 한다.
  • 구독 요청에서 요청된 임대 기간을 존중할 수 MAY 있다.
  • 구독자가 이미 활성화된 구독을 다시 요청하는 것을 허용해야 MUST 한다.
  • 구독 해지 요청을 지원해야 MUST 한다.
  • 토픽 URL의 일치하는 콘텐츠 타입으로 콘텐츠 배포 요청을 보내야 MUST 한다. (콘텐츠 협상 참조)
  • 콘텐츠 배포에 설명된 대로 지원되는 형식에 대해 콘텐츠 배포의 페이로드를 콘텐츠의 diff로 줄일 수 MAY 있다.
  • hub.secret으로 구독이 이루어진 경우, 인증된 콘텐츠 배포에 설명된 대로 X-Hub-Signature 헤더를 보내야 MUST 한다.

3.2 후보 권고안 종료 기준

이 명세는 각 기능에 대해 적어도 두 개의 독립적이고 상호 운용 가능한 구현을 갖추고 CR 단계를 종료했다. 각 기능은 서로 다른 제품 집합에 의해 구현되었을 수 있다. 모든 기능이 하나의 제품에 의해 구현되어야 한다는 요구사항은 없었다. 이 기준의 목적상, 다음 용어를 정의한다:

3.2.1 게시자

WebSub 게시자는 하나 이상의 리소스 URL에서 토픽 및 허브 URL을 광고하는 구현이다. 적합성 기준은 위의 적합성 클래스에 설명되어 있다.

3.2.2 구독자

WebSub 구독자는 주어진 리소스 URL에서 허브 및 토픽 URL을 발견하고, 허브에서 업데이트를 구독하며, 허브로부터 콘텐츠 배포 요청을 수락하는 구현이다. 구독자는 인증된 콘텐츠 배포를 지원할 수 MAY 있다. 적합성 기준은 위의 적합성 클래스에 설명되어 있다.

3.2.3 허브

WebSub 허브는 구독 요청을 처리하고 해당 토픽 URL이 업데이트되었을 때 콘텐츠를 구독자에게 배포하는 구현이다. 허브는 비밀값이 있는 구독 요청을 지원하고, 요청된 경우 인증된 요청을 전달해야 MUST 한다. 허브는 요청에서 토픽 URL의 전체 콘텐츠를 전달해야 MUST 하며, 콘텐츠 타입이 이를 지원하는 경우 페이로드를 diff로 줄일 수 MAY 있다. 적합성 기준은 위의 적합성 클래스에 설명되어 있다.

3.2.4 독립적

각 구현은 서로 다른 당사자가 개발해야 하며, 다른 적격 구현에서 사용된 코드를 공유, 재사용하거나 그로부터 파생될 수 없다. 이 명세의 구현과 관련이 없는 코드 절은 이 요구사항에서 제외된다.

3.2.5 상호 운용 가능

특정 기능에 대해 허브가 구독자가 요청한 정의된 동작을 수행하고, 구독자가 해당 기능에 따라 허브로부터 예상된 응답을 받으며, 허브가 구독자에게 예상된 응답을 보내는 경우, 구독자 및 허브 구현은 상호 운용 가능한 것으로 간주된다.

3.2.6 기능

종료 기준을 평가하기 위한 목적상, 다음 각각은 기능으로 간주된다:

  • 리소스 URL의 HTTP 헤더를 살펴보아 허브 및 토픽 URL을 발견하는 것.
  • 리소스 URL의 내용을 XML 문서로 살펴보아 허브 및 토픽 URL을 발견하는 것.
  • 리소스 URL의 내용을 HTML 문서로 살펴보아 허브 및 토픽 URL을 발견하는 것.
  • 콜백 URL로 허브를 구독하는 것.
  • 허브를 구독하고 특정 임대 기간을 요청하는 것.
  • 비밀값으로 허브를 구독하고 인증된 콘텐츠 배포를 처리하는 것.
  • 구독 해지 요청을 보내 구독이 비활성화되도록 요청하는 것.
  • 구독자가 검증 요청에서 대기 중인 구독을 확인하는 것.
  • 구독자가 잘못된 토픽 URL에 대한 구독 검증 요청을 거부하는 것.
  • 구독자가 페이로드가 전달될 때 HTTP 2xx 응답을 반환하는 것.
  • 구독자가 인증된 콘텐츠 배포 요청의 서명을 검증하는 것.
  • 구독자가 서명이 검증되지 않으면 배포 요청을 거부하는 것.
  • 비밀값으로 구독이 이루어졌는데 서명이 없는 경우 구독자가 배포 요청을 거부하는 것.
  • 허브가 구독 요청 중 요청된 임대 기간을 존중하는 것.
  • 허브가 구독자가 이미 활성화된 구독을 다시 요청하여 임대 기간을 연장하는 것을 허용하는 것.
  • 허브가 배포 요청에서 토픽 URL의 전체 콘텐츠를 보내는 것.
  • 허브가 이를 지원하는 형식에 대해 토픽 URL의 diff를 보내는 것.
  • 허브가 비밀값으로 이루어진 구독에 대해 유효한 서명을 보내는 것.

4. 탐색

탐색 메커니즘은 적어도 2개의 URL을 식별하는 것을 목표로 한다.

주석

게시자는 장애 허용성과 중복성을 위해 둘 이상의 허브를 광고하고 게시하기를 원할 수 있다. 한 허브가 문서에 대한 업데이트를 전파하지 못하면, 여러 독립적인 허브를 사용하는 것은 구독자에게 전달될 가능성을 높이는 방법이다. 따라서 구독자는 광고된 허브 중 하나 이상을 구독할 수 있다.

이 프로토콜은 현재 다음 탐색 메커니즘을 지원한다. 게시자는 그중 적어도 하나를 구현해야 MUST 한다:

주석

수년 동안 <link><head> 안에 배치되는 것으로 제한되어 왔기 때문에, 일부 소비 코드가 <head>만 검사할 수 있다. 따라서 <link> 태그를 <body>가 아니라 HTML <head> 안에만 배치하는 것이 더 견고하다.

GET /feed HTTP/1.1
Host: example.com

HTTP/1.1 200 Ok
Content-type: text/html
Link: <https://hub.example.com/>; rel="hub"
Link: <http://example.com/feed>; rel="self"

<!doctype html>
<html>
  <head>
    <link rel="hub" href="https://hub.example.com/">
    <link rel="self" href="http://example.com/feed">
  </head>
  <body>
    ...
  </body>
</html>

탐색을 수행할 때, 구독자는 다음 순서로 두 탐색 메커니즘을 모두 구현해야 하며 MUST, 첫 번째 일치 항목에서 중지한다:

  1. 토픽 URL을 가져오기 위해 GET 또는 HEAD 요청을 보낸다. 구독자는 먼저 HTTP Link 헤더를 검사해야 MUST 한다.
  2. HTTP Link 헤더가 없고, 토픽이 XML 기반 피드 또는 HTML 페이지인 경우, 구독자는 내장 링크 요소를 검사해야 MUST 한다.

4.1 콘텐츠 협상

실용적인 목적상, rel=self URL이 단일 표현만 제공하는 것이 중요하다. 허브는 탐색 시 구독자가 어떤 미디어 타입([RFC6838]) 또는 언어를 요청했을 수 있는지 알 방법이 없기 때문에, 문서의 적절한 표현을 사용하여 콘텐츠를 전달할 수 없다.

그러나 최초 탐색 요청에서 사용된 HTTP 헤더에 따라 적절한 rel=self URL을 반환함으로써 콘텐츠 협상을 수행할 수 있다. 예를 들어, application/json을 포함하는 Accept 헤더와 함께 /feed에 요청하면 /feed.jsonrel=self 값을 반환할 수 있다.

아래 예제는 전송된 Accept 헤더에 따라 토픽 URL이 서로 다른 Link 헤더를 반환할 수 있는 방법을 보여준다.

GET /feed HTTP/1.1
Host: example.com
Accept: application/json

HTTP/1.1 200 Ok
Content-type: application/json
Link: </feed.json>; rel="self"
Link: <https://hub.example.com/>; rel="hub"

{
  "items": [...]
}
GET /feed HTTP/1.1
Host: example.com
Accept: text/html

HTTP/1.1 200 Ok
Content-type: text/html
Link: </feed.html>; rel="self"
Link: <https://hub.example.com/>; rel="hub"

<html>
...

마찬가지로, 이 기법은 Accept-Language 헤더가 요청한 언어에 따라 서로 다른 rel=self URL을 반환하는 데도 사용할 수 있다.

GET /feed HTTP/1.1
Host: example.com
Accept-Language: de-DE

HTTP/1.1 200 Ok
Content-type: application/json

Link: </feed-de.json>; rel="self"
Link: <https://hub.example.com/>; rel="hub"

{
  "items": [...]
}

5. 구독 및 구독 해지

토픽 URL을 구독하는 것은 즉시 순서대로 발생하거나 지연될 수 있는 네 부분으로 구성된다.

구독 해지는 구독 해지 의사를 나타내기 위해 단일 매개변수가 변경된다는 점을 제외하면 같은 방식으로 동작한다. 또한 허브는 게시자와 함께 구독 해지 요청을 검증하지 않는다.

5.1 구독자가 구독 요청을 보냄

구독은 구독자가 허브 URL에 HTTPS 또는 HTTP POST [RFC7231] 요청을 함으로써 시작된다. 이 요청은 application/x-www-form-urlencoded (Section 4.10.22.6 [HTML5]에 설명됨)의 Content-Type 헤더를 가져야 MUST 하며, 문서 문자 인코딩으로 UTF-8 [Encoding]을 사용해야 MUST 하고, 본문에는 다음 매개변수를 그에 맞게 형식화하여 사용해야 MUST 한다:

hub.callback
REQUIRED. 콘텐츠 배포 알림이 전달되어야 하는 구독자의 콜백 URL. 콜백 URL은 구독마다 고유한 추측 불가능한 URL인 것이 좋다 SHOULD. ([capability-urls])
hub.mode
REQUIRED. 요청의 목적에 따라 리터럴 문자열 "subscribe" 또는 "unsubscribe".
hub.topic
REQUIRED. 구독자가 구독하거나 구독 해지하려는 토픽 URL. 이는 탐색 단계에서 발견된 "self" URL이어야 MUST 하며, 탐색 요청을 하기 위해 사용된 URL과 다를 수 있다는 점에 유의한다.
hub.lease_seconds
OPTIONAL. 구독자가 구독을 활성 상태로 유지하고자 하는 초 단위 시간으로, 양의 십진 정수로 제공된다. 허브는 자체 정책에 따라 이 값을 존중하거나 존중하지 않도록 선택할 수 MAY 있으며, 구독자가 매개변수를 생략한 경우 기본값을 설정할 수 MAY 있다. 이 매개변수는 구독 해지 요청에 존재할 수 MAY 있으며, 그 경우 허브는 이를 무시해야 MUST 한다.
hub.secret
OPTIONAL. 승인된 콘텐츠 배포를 위한 HMAC 다이제스트를 계산하는 데 사용될, 구독자가 제공하는 암호학적으로 무작위인 고유 비밀 문자열. 제공되지 않은 경우, 콘텐츠 배포 요청에는 HMAC 다이제스트가 존재하지 않는다. 이 매개변수는 요청이 HTTPS [RFC2818]를 통해 이루어진 경우에만 지정하는 것이 좋다 SHOULD. 이 매개변수는 길이가 200바이트 미만이어야 MUST 한다.

구독자는 허브가 요구하는 경우 추가 HTTP [RFC7230] 요청 매개변수와 HTTP [RFC7230] 헤더도 포함할 수 MAY 있다.

허브는 이해하지 못하는 추가 요청 매개변수를 무시해야 MUST 한다.

허브는 구독자가 이미 활성화된 구독을 다시 요청하는 것을 허용해야 MUST 한다. 구독 또는 구독 해지를 위해 허브에 보내는 각 후속 요청은, 동작이 검증된 후에만 (Section 4.3), 특정 토픽 URL과 콜백 URL 조합에 대한 이전 구독 상태를 재정의해야 MUST 한다. 검증이 실패하면 구독 상태는 변경되지 않은 채로 남아야 MUST 한다. 이는 구독자가 lease seconds 기간이 끝나기 전에 중단 없이 구독을 갱신할 수 있도록 하기 위해 필요하다. 구독자는 이후 구독에서 새로운 hub.secret 값을 사용할 수 MAY 있으며, hub.secret 없이 새 구독을 만들 수 MAY 있다.

5.1.1 구독 매개변수 세부사항

토픽 및 콜백 URL은 HTTP [RFC7230] 또는 HTTPS [RFC2818] 스킴을 사용할 수 MAY 있다. 토픽 URL은 탐색 단계에서 게시자가 Self Link Header로 광고한 것이어야 MUST 한다. (Section 3 참조). 허브는 토픽 URL이 게시자가 광고한 URL과 일치하지 않는 경우 구독을 거부할 수 MAY 있다. 그 밖의 경우 토픽 URL은 URL 명세 [URL]를 따르는 자유 형식일 수 있다. 허브는 이러한 URL 매개변수에 대해 예약되지 않은 문자를 항상 디코드해야 MUST 한다. [URL]의 "Percent-encoded bytes"에 관한 section 1.2를 참조한다.

콜백 URL은 추측 불가능한 고유 URL([capability-urls])인 것이 좋고 SHOULD, HTTPS [RFC7230]를 사용하는 것이 좋다 SHOULD. 콜백 URL은 구독을 확인하고 콘텐츠를 전달할 때 허브에서 구독자로의 인증 역할을 한다. 추가로, 콜백은 고유한 것이 좋으며 SHOULD (여러 허브에 재사용되지 않음), 구독이 갱신될 때 변경되는 것이 좋다.

콜백 URL은 임의의 쿼리 문자열 매개변수(예: ?foo=bar&red=fish)를 포함할 수 MAY 있다. 허브는 구독 검증 중에 &(앰퍼샌드) 문자를 사용하여 목록 끝에 새 매개변수를 추가함으로써 쿼리 문자열을 보존해야 MUST 한다. 검증 요청에서 사용되는 이름과 겹치는 기존 매개변수는 덮어쓰지 않는다. 콘텐츠 배포 요청을 보낼 때, 허브는 POST 본문 매개변수가 아니라 요청의 URL 부분에 모든 쿼리 문자열 매개변수를 포함하여 콜백 URL에 POST 요청을 한다.

5.1.2 구독 응답 세부사항

허브 URL이 WebSub을 지원하고 구독 또는 구독 해지 요청을 처리할 수 있는 경우, 허브는 구독 요청에 대해 HTTP [RFC7231] 202 "Accepted" 응답으로 응답해야 MUST 하며, 이는 요청이 수신되었고 이제 허브에 의해 검증(Section 5.3) 및 유효성 확인(Section 5.2)될 것임을 나타낸다. 허브는 의도의 검증 및 유효성 확인을 가능한 한 빨리 수행하는 것이 좋다 SHOULD.

허브가 구독 요청에서 오류를 발견하면, 적절한 HTTP [RFC7231] 오류 응답 코드(4xx 또는 5xx)를 반환해야 MUST 한다. 오류가 발생한 경우, 허브는 클라이언트 개발자가 오류를 이해하는 데 도움이 되도록 응답 본문에 일반 텍스트로 오류 설명을 반환하는 것이 좋다 SHOULD. 이는 최종 사용자에게 표시하기 위한 것이 아니다. 허브는 자체 정책(예: 도메인 승인, 토픽 URL 포트 번호)에 따라 일부 콜백 URL 또는 토픽 URL을 거부하기로 결정할 수 MAY 있다. 그러나 의도의 검증 및 유효성 확인은 HTTP 응답이 반환된 후 논리적으로 시작되는 비동기 단계이므로, HTTP 응답은 검증 또는 유효성 확인의 과정이나 결과에 의존해서는 안 된다 MUST NOT.

허브 URL이 구독 또는 구독 해지 요청을 처리할 수 없는 경우, WebSub을 지원하는 다른 허브로 리다이렉트할 수 MAY 있다. 이는 HTTP [RFC7231] 307(임시 리다이렉트) 또는 308(영구 리다이렉트) 응답을 반환함으로써 수행한다. 또한 구독자가 사용할 허브의 선호 URL 참조를 포함하는 HTTP [RFC7230] Location Header를 적어도 하나 포함해야 MUST 한다. 구독자는 새 허브 URL에서 구독 또는 구독 해지를 다시 시도할 것으로 기대된다.

5.2 구독 유효성 확인

구독은 구독을 수락하거나 거부하기 위해 더 많은 세부사항을 요구할 수 있는 허브에 의해 유효성이 확인될 수 MAY 있다. 허브는 또한 구독이 수락되어야 하는지 게시자에게 확인할 수 MAY 있다.

구독이 수락된 경우(그리고 수락될 때), 허브는 구독자의 의도 검증을 수행해야 MUST 한다.

구독이 거부된 경우(그리고 거부될 때), 허브는 구독 요청에 제공된 구독자의 콜백 URL로 HTTP [RFC7231] (또는 HTTPS [RFC2818]) GET 요청을 보내 구독자에게 알려야 MUST 한다. 이 요청에는 다음 쿼리 문자열 인수가 추가된다 ([URL]의 Section 4에 설명된 형식):

hub.mode
REQUIRED. 리터럴 문자열 "denied".
hub.topic
REQUIRED. 해당 구독 요청에 제공된 토픽 URL.
hub.reason
OPTIONAL. 허브는 구독이 거부된 이유를 포함할 수 있다.

구독은 어느 시점에서든(이전에 수락되었더라도) 허브에 의해 거부될 수 MAY 있다. 그러면 구독자는 그 구독이 더 이상 가능하지 않다고 간주하는 것이 좋다 SHOULD.

5.3 허브가 구독자의 의도를 검증

공격자가 구독자를 대신하여 원치 않는 구독을 생성하거나(또는 원하는 구독을 해지하는 것)을 방지하기 위해, 허브는 구독자가 실제로 구독 요청을 보냈는지 확인해야 한다.

허브는 구독 요청에 제공된 구독자의 콜백 URL로 HTTP [RFC7231] (또는 HTTPS [RFC2818]) GET 요청을 보내 구독 요청을 검증한다. 이 요청에는 다음 쿼리 문자열 인수가 추가된다([URL]의 Section 4에 설명된 형식):

hub.mode
REQUIRED. 리터럴 문자열 "subscribe" 또는 "unsubscribe"로, 구독자가 허브에 보낸 원래 요청과 일치한다.
hub.topic
REQUIRED. 해당 구독 요청에 제공된 토픽 URL.
hub.challenge
REQUIRED. 구독을 검증하기 위해 구독자가 그대로 반환해야 MUST 하는 허브 생성 무작위 문자열. 이 무작위 문자열은 [#x2B] | [#2D-#x39] | [#x3D] | [#41-#x5A] | [#x5F] | [#x61-#x7A] 집합의 문자로만 구성되어야 MUST 한다.
hub.lease_seconds
REQUIRED/OPTIONAL. 허브에서 구독자에게 검증 요청을 보낸 시점부터 측정하여, 구독이 만료되기 전까지 활성 상태로 유지될 허브가 결정한 초 단위 시간. hub.mode가 "subscribe"로 설정된 경우, 허브는 이 매개변수를 제공해야 MUST 한다. 이 매개변수는 hub.mode가 "unsubscribe"인 경우 존재할 수 MAY 있으며, 그 경우 구독자는 이를 무시해야 MUST 한다.

5.3.1 검증 세부사항

구독자는 hub.topic이 자신이 수행하려는 대기 중인 구독 또는 구독 해지와 일치하는지 확인해야 MUST 한다. 그렇다면 구독자는 응답 본문이 hub.challenge 매개변수와 동일한 HTTP 성공(2xx) 코드로 응답해야 MUST 한다. 구독자가 그 동작에 동의하지 않는 경우, 구독자는 404 "Not Found" 응답으로 응답해야 MUST 한다.

구독자는 반사된 코드 삽입(reflected XSS) 공격을 방지하기 위해 구독 확인 응답에 안전한 미디어 타입을 사용해야 MUST 한다.

허브는 다른 서버 응답 코드(3xx, 4xx, 5xx)를 검증 요청이 실패했음을 의미하는 것으로 간주해야 MUST 한다. 구독자가 HTTP [RFC7231] 성공(2xx)을 반환했지만 콘텐츠 본문이 hub.challenge 매개변수와 일치하지 않는 경우, 허브는 또한 검증이 실패한 것으로 간주해야 MUST 한다.

허브는 hub.lease_seconds를 구독자가 구독 요청에서 전달한 값과 같게 할 수 MAY 있지만, 허브의 정책에 따라 값을 변경할 수 MAY 있다. 구독을 유지하려면, 구독자는 hub.lease_seconds초가 경과하기 전에 허브에 구독을 다시 요청해야 MUST 한다.

허브는 임대 만료를 강제해야 MUST 하며, 영구 임대 기간을 발급해서는 안 된다 MUST NOT.

주석

이 명세는 구독 요청의 확인/거부와 콘텐츠 전달을 구분하기 위해 GET과 POST를 사용한다. 이는 웹 아키텍처 관점에서 "모범 사례"로 간주되지는 않지만, 콜백 URL의 구현을 더 단순하게 만든다. 콘텐츠 배포 요청의 POST 본문은 임의의 콘텐츠 타입일 수 있고 문서의 실제 콘텐츠만 포함하므로, GET과 POST의 구분을 사용하여 이 두 모드의 처리를 전환하면 구현이 더 단순해진다.

6. 게시

게시자는 토픽이 업데이트되었을 때 이전에 지정한 허브에 알려야 MUST 한다. 허브와 게시자는 허브가 결국 업데이트된 페이로드를 구독자에게 보낼 수 있기만 하다면 어떤 메커니즘에도 합의할 수 있다.

주석

게시자가 허브에 알리는 구체적인 메커니즘은 지정하지 않는다. 예를 들어, 일부 기존 공개 허브는 [1] [2] [3] 게시자에게 hub.mode="publish"hub.url=(업데이트된 리소스의 URL) 키와 함께 POST 요청을 보내도록 요구한다.

6.1 구독 마이그레이션

게시자가 기존 구독을 새 토픽 URL로 마이그레이션하려는 경우, HTTP 리다이렉트를 사용하여 그렇게 할 수 있다.

이는 이전 허브의 어떠한 참여도 요구하지 않으며, 게시자가 허브도 변경하는지 여부와 관계없이 동작한다.

7. 콘텐츠 배포

콘텐츠 배포 요청은 토픽 URL에 대해 새 콘텐츠를 사용할 수 있게 되었을 때 허브에서 구독자에게 전송된다. 이 요청은 허브에서 구독자의 콜백 URL로 보내는 HTTP [RFC7231] (또는 HTTPS [RFC2818]) POST 요청이다. POST 요청의 HTTP 본문은 콘텐츠 배포 알림의 페이로드를 포함해야 MUST 한다. 콘텐츠 배포 요청은 토픽의 Content-Type에 대응하는 Content-Type Header를 가져야 MUST 하며, 아래에 설명된 허용 예외를 제외하고 토픽 URL의 전체 콘텐츠를 포함해야 MUST 한다.

Atom ([RFC4287]) 및 RSS ([RSS-2.0]) 피드의 경우, 허브는 피드에서 이미 전달된 atom:entry 또는 rss:item 요소를 제거할 수 MAY 있다.

요청은 업데이트되는 토픽과 연결된 허브를 가리키는 rel=hub를 가진 Link Header [RFC5988]를 적어도 하나 포함해야 MUST 한다. 또한 업데이트되는 토픽의 정식 URL로 설정된 rel=self를 가진 Link Header [RFC5988] 하나를 포함해야 MUST 한다. 허브는 이러한 헤더를 하나의 Link Header [RFC5988]로 결합하는 것이 좋다 SHOULD. 이러한 모든 URL은 탐색 과정(Section 3)의 결과로 얻어진 URL이다. 구독자는 콘텐츠 배포 요청에 대응하는 구독을 식별하기 위해 이러한 Link 헤더를 사용해서는 안 된다 MUST NOT. Link 헤더는 특정 구독이 아니라 토픽 콘텐츠와 연결된 메타데이터이기 때문이다. 예를 들어, 콘텐츠 배포 요청의 토픽 URL은 원래 구독했던 토픽 URL과 다를 수 있다.

구독자의 콜백 URL은 성공을 나타내기 위해 HTTP [RFC7231] 2xx 응답 코드를 반환해야 MUST 한다. 구독자의 콜백 URL은 구독이 삭제되었음을 나타내기 위해 HTTP 410 코드를 반환할 수 MAY 있으며, 허브는 해당 코드를 응답으로 받으면 구독을 종료할 수 MAY 있다. 허브는 그 밖의 모든 구독자 응답 코드를 실패로 간주해야 MUST 한다. 즉, 구독자는 구독 이동을 위해 HTTP 리다이렉트를 사용해서는 안 된다 MUST NOT. 구독자는 콘텐츠 배포 요청에 가능한 한 빨리 응답하는 것이 좋다 SHOULD. 그 성공 응답 코드는 메시지 수신만을 나타내는 것이 좋으며 SHOULD, 구독자가 이를 성공적으로 처리했다는 확인을 나타내서는 안 된다. 구독자의 응답 본문은 허브가 무시해야 MUST 한다. 허브는 횟수와 전체 재시도 기간에 대해 스스로 정한 한도까지 콘텐츠 배포 요청을 재시도하는 것이 좋다 SHOULD. 실패한 전달이 허브의 한도를 초과하면, 허브는 해당 알림 전달 시도를 중지한다. 허브는 임대 기간이 끝날 때까지 구독을 활성 상태로 유지해야 MUST 하며, 토픽에 새 업데이트가 게시되면 이전에 실패했던 구독자에게 전달을 계속 재시도해야 MUST 한다.

7.1 인증된 콘텐츠 배포

구독자가 구독 요청에서 hub.secret 값을 제공한 경우, 허브는 페이로드의 HMAC 서명을 생성하고 해당 서명을 콘텐츠 배포 요청의 요청 헤더에 포함해야 MUST 한다. X-Hub-Signature 헤더의 값은 method=signature 형식이어야 MUST 하며, 여기서 method는 인식되는 알고리즘 이름 중 하나이고 signature는 서명의 16진수 표현이다. 서명은 요청 본문을 데이터로, hub.secret를 키로 하여 HMAC 알고리즘 [RFC6151]을 사용해 계산되어야 MUST 한다.

7.1.1 인식되는 알고리즘 이름

다음 알고리즘은 발행 당시 [FIPS-PUB-180-4] 레지스트리의 내용을 기반으로 최초 등록된 알고리즘 이름이다.

sha1
[FIPS-PUB-180-4]의 Section 6.1에 지정된 SHA-1 알고리즘
sha256
[FIPS-PUB-180-4]의 Section 6.2에 지정된 SHA-256 알고리즘
sha384
[FIPS-PUB-180-4]의 Section 6.5에 지정된 SHA-384 알고리즘
sha512
[FIPS-PUB-180-4]의 Section 6.4에 지정된 SHA-512 알고리즘

향후에는 구독자가 검증에 사용할 수 있는 알고리즘을 표시할 수 있도록 하는 확장이 지정될 수 있다. 이 글을 쓰는 시점에서 대부분의 허브는 알려진 암호학적 약점에도 불구하고, 오래된 구독자와의 상호 운용성을 위해 SHA-1로 서명한다.

7.1.2 서명 검증

구독자가 X-Hub-Signature 헤더가 지정된 콘텐츠 배포 요청을 수신하면, 공유 비밀값을 사용하여 허브와 같은 메서드(X-Hub-Signature 헤더에 제공됨)로 서명을 다시 계산하는 것이 좋다 SHOULD. 서명이 일치하지 않으면, 구독자는 메시지를 유효하지 않은 것으로 로컬에서 무시해야 MUST 한다. 구독자는 메시지를 비동기적으로 처리할 수 있게 하거나 서명에 대한 무차별 대입 시도를 방지하기 위해, 이 요청을 여전히 2xx 응답 코드로 확인할 수 MAY 있다. 이 기법을 구독 요청에 HTTPS [RFC2818]와 함께 사용하면, 단순한 구독자는 HTTPS [RFC2818] 서버를 실행할 필요 없이 허브로부터 인증된 콘텐츠 배포 요청을 받을 수 있다.

그러나 이 서명은 페이로드가 위조되지 않았음을 보장할 뿐이라는 점에 유의한다. 요청에는 헤더도 포함되므로, 구독자가 HTTPS [RFC2818] 콜백을 사용하는 경우가 아니라면 이러한 헤더는 구독자에 의해 안전한 것으로 간주되어서는 안 된다.

8. 보안 고려사항

다음은 보안 고려사항의 요약이다. WebSub은 HTTP에만 의존하는 서버 간 프로토콜이라는 점에 유의하는 것이 중요하다. 모든 요청에 HTTPS를 사용하는 것이 강력히 권장된다.

8.1 탐색

구독자가 페이지의 <body> 내부(<head>와 함께)에 있는 <link> 요소를 찾아야 하는지에 대한 결정은 간단하지 않으며, 현재 명확한 합의도 없다. 탐색 중 <body>를 무시해야 하는 한 가지 이유는, 일부 웹 사이트가 (아마도 우연히) 사용자가 <link> 요소를 포함하는 콘텐츠를 게시하도록 허용할 수 있기 때문이다. 다만 워킹 그룹은 그러한 사이트의 구체적인 예를 알지 못한다. WebSub 탐색이 그러한 <link> 요소를 사용하면, 그러한 사이트에 기여하는 사용자가 잠재적으로 악의적으로 모든 구독자가 대체 허브를 사용하게 만들 수 있고, 그 허브가 나중에 악성 콘텐츠를 전달할 수 있다. 이러한 잠재적 공격을 고려하면, HTML 문서의 <head>에서만 탐색을 수행하는 것이 신중할 수 있다.

8.2 구독

첫째, 구독자는 허브에 대해 항상 HTTPS URL을 선호하는 것이 좋다 SHOULD (해당 URL이 HTTP로 광고되더라도). 둘째, 구독자는 콜백에 고유하고 추측 불가능한 capability URL을 사용하고, 이를 HTTPS를 통해 사용할 수 있게 하는 것이 좋다 SHOULD. 마지막으로, 구독자는 콘텐츠 배포의 서명을 허용하기 위해 구독 시 hub.secret를 사용하는 것이 좋다 SHOULD.

허브는 수명이 짧은 hub.lease_seconds를 강제하는 것이 좋다 SHOULD(10일이 좋은 기본값이다). 의도 검증을 수행할 때, 허브는 무작위의 일회용 hub.challenge를 사용하는 것이 좋다 SHOULD.

의도 검증 절차는 반사된 코드 삽입(reflected XSS) 공격의 위험을 도입한다. 구독자는 이러한 유형의 공격으로부터 보호하기 위해 application/octet-stream 같은 안전한 미디어 타입을 사용하여 의도 검증 응답을 제공해야 MUST 한다. 또한 의도 검증 응답은 Content-Security-Policy 제한을 우회하는 데 악용될 수 있다. 구독자는 이를 완화하기 위해 X-Content-Type-Options: nosniff와 함께 의도 검증 응답을 제공해야 MUST 한다.

의도 검증 절차는 신뢰할 수 있는 구독자로부터 악성 리소스를 다운로드하도록 사용자를 속이는 데 사용될 수 있다. 구독자는 길이 제한 및 바이너리 데이터 거부와 같은 제한을 hub.challenge 매개변수에 부과하는 것이 좋다 SHOULD.

8.3 배포

허브는 구독자가 사용한 정확한 콜백을 사용해야 MUST 한다 (HTTPS 사용을 포함). 허브는 요청된 경우 구독자가 제공한 hub.secret를 사용하여 요청에 서명해야 MUST 한다.

구독자가 구독 요청에 hub.secret을 포함한 경우, 구독자는 허브가 제공한 서명을 검증하는 것이 좋고 SHOULD, 그렇게 하는 경우 서버가 명시한 서명 메커니즘을 사용해야 MUST 하며, 검사를 통과하지 못한 요청은 폐기해야 한다.

구독자가 보안 콜백 URL(HTTPS)을 사용하지 않거나, 허브와 구독자 간의 TLS 전송이 손상되었을 가능성이 의심되는 경우, 콘텐츠 전달 알림의 무결성은 hub.secret와 사용된 해싱 알고리즘에 의해서만 보호된다. 이 경우 애플리케이션의 보안 요구사항을 기반으로 적절한 해싱 알고리즘을 사용해야 한다. 이 발행일 기준으로 SHA-1은 손상되었음이 입증되었으므로, 최소한 SHA-256을 사용해야 한다.

8.4 보안 및 개인정보 보호 검토

다음 질문들은 Self-Review Questionnaire: Security and Privacy ([security-privacy-questionnaire])의 지침에 따라 이 명세에 대한 보안 및 개인정보 보호 고려사항의 개요를 제공한다.

이 명세는 개인 식별 정보와 관련이 있는가?
관련될 수 있는 유일한 잠재적 개인 식별 정보는 토픽 및 콜백 URL이다.
이 명세는 고가치 데이터를 다루는가?
아니오, 인증이나 기타 자격 증명은 관련되지 않는다.
이 명세는 브라우징 세션 간에 지속되는 출처에 대한 새 상태를 도입하는가?
아니오.
이 명세는 지속적인 교차 출처 상태를 웹에 노출하는가?
WebSub 구독자는 자신이 구독하는 토픽에 대한 정보를 가진 리소스를 생성해야 한다.
이 명세는 출처가 현재 접근할 수 없는 다른 데이터를 해당 출처에 노출하는가?
아니오.
이 명세는 새로운 스크립트 실행/로딩 메커니즘을 가능하게 하는가?
아니오.
이 명세는 출처가 사용자의 위치에 접근할 수 있도록 허용하는가?
아니오.
이 명세는 출처가 사용자 기기의 센서에 접근할 수 있도록 허용하는가?
아니오.
이 명세는 출처가 사용자의 로컬 컴퓨팅 환경의 측면에 접근할 수 있도록 허용하는가?
아니오.
이 명세는 출처가 다른 기기에 접근할 수 있도록 허용하는가?
아니오.
이 명세는 출처가 사용자 에이전트의 네이티브 UI에 대해 어느 정도 제어할 수 있도록 허용하는가?
아니오.
이 명세는 임시 식별자를 웹에 노출하는가?
아니오.
이 명세는 일방 당사자 및 제3자 컨텍스트에서의 동작을 구분하는가?
아니오.
이 명세는 사용자 에이전트의 "시크릿" 모드 맥락에서 어떻게 동작해야 하는가?
WebSub은 서버 간 프로토콜이므로, "시크릿" 모드는 의미가 없다.
이 명세는 사용자의 로컬 기기에 데이터를 지속시키는가?
아니오.
이 명세는 기본 보안 특성의 하향 조정을 허용하는가?
아니오.

A. 감사의 말

이 절은 비규범적이다.

편집자들은 PubSubHubbub의 작성자들, IndieWeb 커뮤니티, 그리고 다른 구현자들의 지원, 격려 및 열정에 감사한다. 특히, 편집자들은 Brad Fitzpatrick, Brett Slatkin, Martin Atkins, Amy Guy, Barry Frost, Benjamin Roberts, Eugen Rochko, Jordan Potter, Matthias Pfefferle, Malcolm Blaney, Marten de Vries, Sandro Hawke, Tantek Çelik, 및 Tony Garnock-Jones에게 감사를 표한다.

W3C Team은 XSS를 보고한 Gabriel Corona에게 감사한다

B. 변경 기록

이 절은 비규범적이다.

B.1 2017년 10월 03일 PR에서 이 버전까지의 변경사항

B.2 2017년 4월 11일 CR에서 2017년 10월 03일 PR까지의 변경사항

B.3 11월 24일 WD에서 2017년 4월 11일 CR까지의 변경사항

B.4 10월 20일 FPWD에서 2016년 11월 24일까지의 변경사항

C. 참고문헌

C.1 규범 참고문헌

[capability-urls]
Capability URL에 대한 모범 사례. Jeni Tennison. W3C. 2014년 2월 18일. FPWD. URL: https://www.w3.org/TR/capability-urls/
[Encoding]
Encoding Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://encoding.spec.whatwg.org/
[FIPS-PUB-180-4]
Secure Hash Standard (SHS). National Institute of Standards and Technology. U.S. Department of Commerce. URL: http://dx.doi.org/10.6028/NIST.FIPS.180-4
[HTML5]
HTML5. Ian Hickson; Robin Berjon; Steve Faulkner; Travis Leithead; Erika Doyle Navara; Theresa O'Connor; Silvia Pfeiffer. W3C. 2018년 3월 27일. W3C Recommendation. URL: https://www.w3.org/TR/html5/
[PubSubHubbub-Core-0.3]
PubSubHubbub Core 0.3 -- Working Draft. B. Fitzpatrick; B. Slatkin; M. Atkins. URL: https://pubsubhubbub.github.io/PubSubHubbub/pubsubhubbub-core-0.3.html
[PubSubHubbub-Core-0.4]
PubSubHubbub Core 0.4 -- Working Draft. B. Fitzpatrick; B. Slatkin; M. Atkins; J. Genestoux. URL: https://pubsubhubbub.github.io/PubSubHubbub/pubsubhubbub-core-0.4.html
[RFC2119]
RFC에서 요구 수준을 나타내기 위해 사용하는 핵심 단어. S. Bradner. IETF. 1997년 3월. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc2119
[RFC2818]
TLS 위의 HTTP. E. Rescorla. IETF. 2000년 5월. 정보성. URL: https://httpwg.org/specs/rfc2818.html
[RFC4287]
Atom 배급 형식. M. Nottingham, Ed.; R. Sayre, Ed. IETF. 2005년 12월. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc4287
[RFC5988]
웹 링크. M. Nottingham. IETF. 2010년 10월. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc5988
[RFC6151]
MD5 메시지 다이제스트 및 HMAC-MD5 알고리즘에 대한 업데이트된 보안 고려사항. S. Turner; L. Chen. IETF. 2011년 3월. 정보성. URL: https://www.rfc-editor.org/rfc/rfc6151
[RFC6838]
미디어 타입 명세 및 등록 절차. N. Freed; J. Klensin; T. Hansen. IETF. 2013년 1월. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc6838
[RFC7230]
Hypertext Transfer Protocol (HTTP/1.1): 메시지 구문 및 라우팅. R. Fielding, Ed.; J. Reschke, Ed. IETF. 2014년 6월. Proposed Standard. URL: https://httpwg.org/specs/rfc7230.html
[RFC7231]
Hypertext Transfer Protocol (HTTP/1.1): 의미론 및 콘텐츠. R. Fielding, Ed.; J. Reschke, Ed. IETF. 2014년 6월. Proposed Standard. URL: https://httpwg.org/specs/rfc7231.html
[RFC8174]
RFC 2119 핵심 단어에서 대문자와 소문자의 모호성. B. Leiba. IETF. 2017년 5월. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc8174
[RSS-2.0]
RSS 2.0. Dave Winer. RSS Board. Stable. URL: http://www.rssboard.org/rss-specification
[security-privacy-questionnaire]
자체 검토 질문지: 보안 및 개인정보 보호. Theresa O'Connor; Peter Snyder; Simone Onofri. W3C. 2025년 4월 18일. W3C Working Group Note. URL: https://www.w3.org/TR/security-privacy-questionnaire/
[URL]
URL Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://url.spec.whatwg.org/