WebSub

W3C 권고안

이 버전:
https://www.w3.org/TR/2018/REC-websub-20180123/
최신 공개 버전:
https://www.w3.org/TR/websub/
최신 편집본:
https://websub.net/draft
테스트 스위트:
https://websub.rocks/
구현 보고서:
https://websub.net/implementation-reports
이전 버전:
https://www.w3.org/TR/2017/PR-websub-20171003/
에디터:
Julien Genestoux, 초청 전문가
Aaron Parecki, 초청 전문가
저자:
Julien Genestoux
이전 저자:
Brad Fitzpatrick
Brett Slatkin
Martin Atkins
저장소:
Github
이슈
커밋

발행 이후 보고된 오류나 이슈는 정오표를 확인해 주세요.

또한 번역도 참고하세요.


초록

WebSub은 HTTP 웹 훅 기반으로, 모든 종류의 웹 콘텐츠 게시자와 구독자 간 통신을 위한 공통 메커니즘을 제공합니다. 구독 요청은 허브를 통해 전달되며, 허브는 해당 요청을 검증하고 확인합니다. 허브는 새로운 내용이나 갱신된 콘텐츠가 이용 가능해질 때 이를 구독자에게 배포합니다. WebSub은 이전에는 PubSubHubbub으로 알려져 있었습니다.

이 문서의 상태

이 섹션은 이 문서가 발행될 당시의 상태를 설명합니다. 다른 문서가 이 문서를 대체할 수 있습니다. 현재 W3C 발행물 목록 및 이 기술 보고서의 최신 개정판은 W3C 기술 보고서 인덱스 https://www.w3.org/TR/에서 확인하실 수 있습니다.

이 문서는 소셜 웹 워킹 그룹에 의해 권고안으로 발행되었습니다. 본 문서에 대한 의견은 언제든 환영합니다. 모든 관심 있는 분들은 워킹 그룹의 이슈 트래커를 통해 구현 및 버그 제보와 의견을 남길 수 있습니다. 이 의견들은 소셜 웹 커뮤니티 그룹에서 논의되며, 향후 사양의 버전에 반영될 수 있습니다.

워킹 그룹의 구현 보고서를 참조하십시오.

본 문서는 W3C 회원, 소프트웨어 개발자, 기타 W3C 그룹 및 관심자들의 검토를 받고, W3C 이사의 승인 하에 W3C 권고안으로 채택되었습니다. 이 문서는 안정적인 문서로, 참고 자료나 다른 문서에서 인용되어도 좋습니다. W3C의 권고안 마련 목적은 사양의 주목도를 높이고 광범위한 배포를 촉진하는 것입니다. 이는 웹의 기능성과 상호 운용성을 강화합니다.

본 문서는 W3C 특허 정책에 따라 운영되는 그룹에서 제작되었습니다. W3C는 그룹 납품물과 관련하여 공개된 공개 특허 공개 목록을 유지하고 있습니다. 해당 페이지에는 특허 공개 방법에 대한 안내도 포함되어 있습니다. 타당한 특허를 실제로 알고 있으며, 그 특허가 필수 청구항을 포함한다고 생각할 경우, W3C 특허 정책 6조에 따라 공개해야 합니다.

이 문서는 2017년 3월 1일 W3C 프로세스 문서에 의해 관리됩니다.

1. 정의

토픽
HTTP [RFC7230] (또는 HTTPS [RFC2818]) 리소스 URL. 변경 사항을 구독할 수 있는 단위입니다.
허브 ("hub")
이 프로토콜의 양쪽을 모두 구현하는 서버(URL [URL])입니다. 모든 허브는 정책에 따라 사용자를 제한할 수 있습니다.
게시자
토픽의 소유자입니다. 토픽 피드가 업데이트될 때 허브에 알립니다. 대부분의 pubsub 시스템과 마찬가지로, 게시자는(구독자가 있더라도) 구독자에 대해 알지 못합니다. 다른 pubsub 시스템에서는 게시자를 "소스"라고 할 수도 있습니다.
구독자
토픽의 변경 내용을 통지받고자 하는 엔터티(사람 또는 프로그램)입니다. 구독자는 네트워크로 직접 접근 가능해야 하며, 구독자 콜백 URL로 식별됩니다.
구독
구독자가 토픽에 대한 업데이트를 받아야 함을 나타내는, 토픽에 대한 고유한 관계입니다. 구독의 고유 키는 (토픽 URL, 구독자 콜백 URL) 튜플입니다. 구독은(허브의 결정에 따라) DHCP 임대와 유사하게 만료 시간을 가질 수 있으며, 정기적으로 갱신해야 합니다.
구독자 콜백 URL
구독자가 콘텐츠 배포 요청을 수신하고자 하는 URL [URL]입니다.
이벤트
여러 토픽의 업데이트를 발생시키는 사건입니다. (예: "Brad가 리눅스 커뮤니티에 게시함")와 같이, 한 이벤트는 여러 토픽("Brad가 게시함", "리눅스 커뮤니티에 새 글")에 영향을 끼칠 수 있습니다. 게시자 이벤트는 토픽을 업데이트하며, 허브는 영향을 받은 토픽의 모든 구독을 조회하여 콘텐츠를 구독자에게 전달합니다.
콘텐츠 배포 알림 / (콘텐츠 배포 요청)
토픽의 내용이 어떻게 변했는지 설명하는 페이로드 또는 전체 업데이트된 내용입니다. 토픽의 콘텐츠 유형에 따라, 허브는 차이("델타")를 계산하여 모든 구독자에게 전송할 수 있습니다.

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

(이 섹션은 비규범적입니다.)

WebSub 프로토콜 흐름 다이어그램

이 프로토콜의 이전 버전은 PubSubHubbub으로 불렸습니다:

3. 적합성

이 문서에서 "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", 그리고 "OPTIONAL" 등의 키워드는 [RFC2119]에 설명된 대로 해석해야 합니다.

3.1 적합성 클래스

WebSub은 세 가지 역할(게시자, 구독자, 허브)을 정의합니다. 이 섹션에서는 각 역할의 적합성 기준을 설명합니다.

게시자

구독자

적합한 구독자는 다음을 해야 합니다:

허브

적합한 허브는 다음을 만족해야 합니다:

3.2 권고안 후보 종료 기준

이 명세는 각 기능에 대해 독립적이고 상호 운용되는 두 가지 이상의 구현이 존재할 때 CR 단계를 종료합니다. 각 기능은 서로 다른 제품군에서 구현될 수 있습니다. 모든 기능이 하나의 제품에 모두 구현될 필요는 없습니다. 본 기준의 목적으로 다음 용어를 정의합니다:

3.2.1 게시자

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

3.2.2 구독자

WebSub 구독자는 리소스 URL을 바탕으로 허브와 토픽 URL을 찾고, 허브에 구독을 신청하며, 허브로부터 콘텐츠 배포 요청을 수락하는 구현체입니다. 구독자는 선택적으로 인증된 콘텐츠 배포를 지원할 수 있습니다. 적합성 기준은 위의 적합성 클래스에 설명되어 있습니다.

3.2.3 허브

WebSub 허브는 구독 요청을 처리하고, 해당 토픽 URL이 업데이트될 때 구독자에게 콘텐츠를 배포하는 구현체입니다. 허브는 반드시 secret이 포함된 구독 요청을 지원하고, 요청 시 인증된 요청을 제공해야 합니다. 허브는 반드시 요청에 전체 토픽 URL 내용을 전달해야 하며, 선택적으로 콘텐츠 유형이 지원되는 경우 diff로 페이로드를 줄일 수 있습니다. 적합성 기준은 적합성 클래스에 설명되어 있습니다.

3.2.4 독립

각 구현은 서로 다른 주체에 의해 개발되어야 하며, 다른 자격 구현의 코드를 공유, 재사용 또는 파생해서는 안 됩니다. 본 명세의 구현과 무관한 코드 섹션은 이 요구사항에서 예외입니다.

3.2.5 상호 운용

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

3.2.6 기능

종료 기준 평가 시, 아래 각각을 기능으로 간주합니다:

  • 리소스 URL의 HTTP 헤더를 조회하여 허브와 토픽 URL을 발견하는 것
  • 리소스 URL이 XML 문서일 때, 그 내용을 조회하여 허브와 토픽 URL을 발견하는 것
  • 리소스 URL이 HTML 문서일 때, 그 내용을 조회하여 허브와 토픽 URL을 발견하는 것
  • 콜백 URL로 허브에 구독 신청
  • 특정 임대 기간을 요청하며 허브에 구독 신청
  • secret과 함께 허브에 구독 신청 및 인증된 콘텐츠 배포 처리
  • 구독 해지 요청을 전송하여 구독 비활성 요청
  • 구독자가 확인 요청에 대해 보류 중인 구독을 승인
  • 구독자가 잘못된 토픽 URL에 대해 구독 검증 요청을 거부
  • 페이로드가 전달될 때 구독자가 HTTP 2xx 응답 반환
  • 인증된 콘텐츠 배포 요청에서 구독자가 서명 검증
  • 서명이 유효하지 않은 경우 구독자가 배포 요청 거부
  • 구독에 secret이 사용된 경우 서명이 없는 배포 요청을 구독자가 거부
  • 허브가 구독 요청 시 요청 임대 기간을 존중
  • 허브가 이미 활성 구독 재요청을 허용해 임대 기간을 연장
  • 허브가 배포 요청에 토픽 URL의 전체 콘텐츠 전송
  • 허브가 지원하는 포맷의 경우 토픽 URL의 차이만(diff) 전송
  • secret이 사용된 구독에 대해 허브가 올바른 서명을 전송

4. 발견

발견 메커니즘은 적어도 2개의 URL을 식별하는 것을 목표로 합니다.

참고

게시자는 장애 허용 및 이중화(fault tolerance & redundancy) 목적으로 하나 이상의 허브를 광고하고 발행할 수 있습니다. 한 허브가 문서의 업데이트 전파에 실패할 경우, 여러 독립 허브를 통해 구독자에게 전달될 가능성을 높일 수 있습니다. 따라서, 구독자는 광고된 허브 중 하나 혹은 여러 곳에 구독할 수 있습니다.

현재 프로토콜은 다음과 같은 발견 메커니즘을 지원합니다. 게시자는 반드시 이 중 하나 이상을 구현해야 합니다:

참고

<link>는 수년 동안 <head> 안에만 둘 수 있었기 때문에, 일부 소비 코드가 <head>만을 검사할 수 있습니다. 따라서 <link> 태그는 HTML <head>에만 두는 것이 더 견고합니다.

예시 1
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>

발견 시, 구독자는 다음 순서대로 세 가지 모든 발견 메커니즘을 구현해야 하며, 처음 일치하는 곳에서 중지해야 합니다:

  1. 토픽 URL에 대해 GET 또는 HEAD 요청을 보냅니다. 구독자는 반드시 먼저 HTTP Link 헤더를 확인해야 합니다.
  2. HTTP Link 헤더가 없고, 토픽이 XML 기반 피드 또는 HTML 페이지라면, 구독자는 반드시 임베디드 링크 요소를 확인해야 합니다.

4.1 콘텐츠 협상

실용적인 측면에서, rel=self URL이 단일 표현만을 제공하는 것이 중요합니다. 허브는 구독자가 발견 요청 시 어떤 미디어 유형([RFC6838])이나 언어를 요청했는지 알 길이 없으므로, 해당 문서의 올바른 표현 방식으로 콘텐츠를 제공할 수 없습니다.

그러나, 초기 발견 요청의 HTTP 헤더에 따라 적절한 rel=self URL을 반환함으로써 콘텐츠 협상을 수행할 수 있습니다. 예를 들어, /feedAccept 헤더가 application/json을 포함하면 rel=self 값이 /feed.json으로 반환될 수 있습니다.

아래 예시는, Accept 헤더에 따라 토픽 URL이 어떻게 다른 Link 헤더를 반환할 수 있는지 보여줍니다.

예시 2
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": [...]
}
예시 3
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을 반환할 수도 있습니다.

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

HTTP/1.1 200 Ok
Content-type: text/html

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 헤더를 가져야 하며, 반드시 문서 문자 인코딩으로 UTF-8 [Encoding] 을, 그리고 아래와 같이 본문에 다음의 매개변수를 사용해야 합니다:

hub.callback
필수. 콘텐츠 배포 알림을 전달받을 구독자의 콜백 URL입니다. 콜백 URL은 권장적으로 각 구독마다 추측 불가능하고 고유해야 합니다. ([capability-urls])
hub.mode
필수. 요청의 목적에 따라 "subscribe" 또는 "unsubscribe"라는 리터럴 문자열 중 하나.
hub.topic
필수. 구독자가 구독 또는 구독 해지하고자 하는 토픽 URL입니다. 이 값은 반드시 발견 단계에서 얻은 "self" URL이어야 하며, 발견 요청에 사용된 URL과 다를 수 있습니다.
hub.lease_seconds
선택. 구독자가 구독을 유지하길 원하는 시간(초)로, 양의 10진수 정수로 기입합니다. 허브는 선택적으로 이 값을 수용하거나 자체 정책에 따라 무시할 수 있으며, 구독자가 이 파라미터를 생략한 경우 기본값을 설정할 수 있습니다. 이 파라미터는 구독 해지 요청에도 포함될 수 있으나, 그런 경우 허브는 반드시 무시해야 합니다.
hub.secret
선택. 인증된 콘텐츠 배포에 사용할, 구독자가 제공하는 암호학적으로 무작위적인 고유 비밀 문자열입니다. 제공되지 않으면 콘텐츠 배포 요청에 HMAC 다이제스트가 포함되지 않습니다. 이 파라미터는 권장적으로 HTTPS 요청에서만 명시되어야 하며, 반드시 200바이트 미만이어야 합니다.

구독자는 선택적으로 HTTP [RFC7230] 요청 파라미터와, 허브가 요구하는 경우 HTTP [RFC7230] 헤더도 추가로 포함할 수 있습니다.

허브는 반드시 이해하지 못하는 추가 요청 파라미터를 무시해야 합니다.

허브는 반드시 이미 활성화된 구독에 대해 구독자가 재요청할 수 있도록 허용해야 합니다. 특정 토픽 URL과 콜백 URL 조합마다, 허브로 구독 또는 해지 요청이 올 때마다 이전 구독 상태가(동작이 검증될 때만) 덮어써져야 하며, 검증이 실패하면 구독 상태는 반드시 변경되지 않아야 합니다. 이를 통해 구독자는 임대 시간 만료 전 갱신을 끊김 없이 수행할 수 있습니다. 구독자는 추후 구독에서 새로운 hub.secret 값을 사용할 수도 있고, hub.secret 없이 새로 구독할 수도 있습니다.

5.1.1 구독 파라미터 상세

토픽 및 콜백 URL은 선택적으로 HTTP [RFC7230] 또는 HTTPS [RFC2818] 스킴을 사용할 수 있습니다. 토픽 URL은 반드시 발견 단계에서 게시자가 Self Link Header로 광고한 값이어야 합니다. ( 3장 참조) 허브는 선택적으로 게시자가 광고한 값과 일치하지 않는 토픽 URL의 구독을 거부할 수 있습니다. 그렇지 않으면 토픽 URL은 URL 규격 [URL] 을 따르는 자유 형식이어도 됩니다. 허브는 반드시 이들 URL 파라미터의 비예약 문자를 항상 디코딩해야 합니다. ("Percent-encoded bytes"에 대한 section 1.2 참고 [URL].)

콜백 URL은 권장적으로 추측 불가능한 고유 주소([capability-urls])이어야 하고, 권장적으로 HTTPS [RFC7230]를 사용해야 합니다. 콜백 URL은 허브가 구독을 확인하고 콘텐츠를 전달할 때 구독자를 인증하는 역할도 합니다. 콜백은 권장적으로(여러 허브에서 재사용하지 않고) 고유해야 하며, 구독 갱신 시 변경하는 것이 좋습니다.

콜백 URL은 선택적으로 임의의 쿼리 문자열 파라미터(예: ?foo=bar&red=fish)를 포함할 수 있습니다. 허브는 반드시 구독 검증 과정에서 쿼리 문자열을 보존해야 하며, 검증용 새 파라미터는 기존 파라미터 뒤에 &로 추가합니다. 검증 요청에서 사용되는 이름과 겹치는 기존 파라미터는 덮어쓰지 않습니다. 콘텐츠 배포 요청을 보낼 때, 허브는 POST 호출의 URL 부분에 쿼리 문자열 파라미터를 포함시켜 요청을 보내야 하며, POST 본문 파라미터로 포함해서는 안 됩니다.

5.1.2 구독 응답 상세

허브 URL이 WebSub을 지원하고 구독 또는 구독 해지 요청을 처리할 수 있으면, 반드시 구독 요청에 대해 HTTP [RFC7231] 202 "Accepted" 응답을 반환해야 하며, 이로써 허브가 요청을 수신했고 곧 (4.3장) 검증과 (4.2장) 에 명시된 검증을 실시함을 나타냅니다. 허브는 되도록 빨리 검증과 의도 확인을 수행해야 합니다.

허브가 구독 요청에서 오류를 발견한 경우, 적절한 HTTP [RFC7231] 오류 응답 코드(4xx 또는 5xx) 반드시 반환해야 합니다. 오류 발생 시 허브는 권장적으로 plain text로 오류 설명을 응답 본문에 반환해 클라이언트 개발자가 원인을 쉽게 알도록 해야 합니다. 이는 최종 사용자가 보는 용도가 아닙니다. 허브는 선택적으로 자체 정책(예: 도메인 허가, 토픽 URL 포트 등)에 따라 일부 콜백/토픽 URL을 거부할 수 있습니다. 단, 검증 및 의도확인은 논리적으로 HTTP 응답 후 비동기로 시작되는 단계이므로, HTTP 응답은 그 처리나 결과에 절대 의존해서는 안 됩니다.

허브 URL이 구독/구독 해지 요청을 처리할 수 없다면 선택적으로 WebSub을 지원하는 다른 허브로 리디렉션할 수 있습니다. 이 경우 HTTP [RFC7231] 307(임시 리디렉션) 또는 308(영구 리디렉션) 응답을 반환하며, 반드시 HTTP [RFC7230] Location 헤더에 구독자가 사용할 허브 URL을 포함해야 합니다. 구독자는 새 허브 URL로 요청을 재시도해야 합니다.

5.2 구독 검증

구독은 허브에 의해 추가 정보가 필요한 경우 선택적으로 검증될 수 있습니다. 허브는 선택적으로 게시자에게 구독 허용 여부를 확인할 수도 있습니다.

구독이 수락되면 허브는 반드시 구독자의 의도 검증을 수행해야 합니다.

구독이 거부되면 허브는 반드시 구독자의 콜백 URL로 HTTP [RFC7231] (또는 HTTPS [RFC2818]) GET 요청을 보내, 구독자가 알 수 있도록 해야 합니다. 이 요청은 다음 쿼리 문자열 인자를 추가합니다 (형식은 [URL] 4장 참고):

hub.mode
필수. "denied"라는 리터럴 문자열입니다.
hub.topic
필수. 해당 구독 요청에 사용된 토픽 URL입니다.
hub.reason
선택. 허브가 구독을 거부한 이유를 포함할 수 있습니다.

구독은 언제든(과거에 승인된 경우에도) 허브에서 거부될 수 있습니다. 구독자는 이 경우 구독이 더 이상 불가능하다고 간주해야 합니다.

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

공격자가 구독자 대신 원치 않는 구독을 만들거나(혹은 원하는 구독을 해지하는 등) 하는 것을 막기 위해, 허브는 실제로 구독자가 구독(또는 해지) 요청을 보냈는지 확인해야 합니다.

허브는 구독(또는 해지) 요청을 받은 이후, 구독자가 요청에 포함한 콜백 URL로 HTTP [RFC7231] (또는 HTTPS [RFC2818]) GET 요청을 보냅니다. 이 요청의 쿼리 문자열에는 다음 파라미터가 추가됩니다 ([URL] 4장 형식):

hub.mode
필수. "subscribe" 또는 "unsubscribe" 리터럴 문자열로, 구독자가 허브에 보낸 원래 요청을 반영합니다.
hub.topic
필수. 해당 구독 요청에 사용된 토픽 URL입니다.
hub.challenge
필수. 허브가 생성한 임의의 문자열로, 구독자가 이 값을 응답에 그대로 넣어(에코) 인증함을 확인해야 합니다.
hub.lease_seconds
필수/선택. 구독이 만료되기 전까지 허브가 판단한 유지 시간(초)입니다. hub.mode 값이 "subscribe"일 때 반드시 이 파라미터가 포함되어야 합니다. 이 파라미터는 "unsubscribe"인 경우 포함될 수 있으나, 구독자는 반드시 무시해야 합니다.

5.3.1 검증 상세

구독자는 반드시 hub.topic이 현재 보류 중인 구독(또는 해지) 요청과 일치하는지 확인해야 합니다. 일치하는 경우, 구독자는 반드시 hub.challenge 파라미터와 같은 응답 본문을 포함하는 HTTP 성공(2xx) 코드를 반환해야 합니다. 구독자가 행동에 동의하지 않으면, 반드시 404 "Not Found" 응답을 반환해야 합니다.

허브는 반드시 기타 서버 응답 코드(3xx, 4xx, 5xx)는 검증 실패로 간주해야 합니다. 구독자가 HTTP [RFC7231] 성공(2xx) 코드를 반환하지만 응답 본문이 hub.challenge와 일치하지 않으면, 허브는 반드시 역시 검증 실패로 간주해야 합니다.

허브는 선택적으로 hub.lease_seconds 값을 구독자가 요청에 전달한 값과 동일하게 설정할 수도 있으나, 허브 정책에 따라 변경할 수도 있습니다. 구독을 계속 유지하려면, 구독자는 반드시 hub.lease_seconds 만료 전 허브에 구독을 재요청해야 합니다.

허브는 반드시 임대 기간 만료를 적용해야 하며, 절대 영구적인 임대 기간을 허용해서는 안 됩니다.

참고

이 명세서는 구독(확인/거절)과 콘텐츠 전달을 구분하기 위해 GET과 POST를 사용합니다. 이는 웹 아키텍처 관점에서 "최선의 관례"는 아니지만, 콜백 URL 구현을 단순화합니다. 콘텐츠 배포 요청의 POST 본문은 임의의 콘텐츠 타입이 될 수 있고, 실제 문서의 콘텐츠만 포함하므로, 두 동작을 GET과 POST로 구분하는 것이 구현이 쉬워집니다.

6. 게시

게시자는 반드시 이전에 지정한 허브에 토픽이 업데이트되었음을 알려야 합니다. 허브와 게시자는 허브가 결국 구독자에게 갱신된 내용을 전달할 수만 있다면, 어떤 메커니즘에 합의해도 됩니다.

참고

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

6.1 구독 마이그레이션

게시자가 기존 구독을 새로운 토픽 URL로 이전하고자 할 경우, HTTP 리디렉션을 이용할 수 있습니다.

이 과정에는 이전 허브의 참여가 필요 없으며, 게시자가 허브를 변경했는지 여부와 관계없이 작동합니다.

7. 콘텐츠 배포

콘텐츠 배포 요청은 토픽 URL에 새 콘텐츠가 생길 때 허브에서 구독자에게 전송됩니다. 이 요청은 허브가 구독자의 콜백 URL로 보내는 HTTP [RFC7231] (또는 HTTPS [RFC2818]) POST 요청입니다. POST 요청의 HTTP 본문은 반드시 콘텐츠 배포 알림의 페이로드를 포함해야 합니다. 콘텐츠 배포 요청은 반드시 토픽의 Content-Type에 해당하는 Content-Type 헤더를 가져야 하며, 아래에 예시된 경우를 제외하면 반드시 토픽 URL의 전체 콘텐츠를 포함해야 합니다.

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

요청에는 반드시 rel=hub 허브 URL이 포함된 Link Header [RFC5988]가 적어도 하나 이상 있어야 하며, 반드시 업데이트된 토픽의 정형 URL이 rel=self로 포함된 Link Header [RFC5988]도 하나 이상 있어야 합니다. 허브는 가능하면 이 헤더를 하나의 Link Header로 합쳐서 보낼 것을 권장합니다. 이들 URL은 모두 발견 단계 (3장)에서 결정된 값입니다. 구독자는 절대 이 Link 헤더로 콘텐츠 배포 요청에 대한 구독을 매칭해서는 안 됩니다. 이 Link 헤더는 구독별 메타데이터가 아니라 토픽 콘텐츠의 메타데이터이기 때문입니다. 즉, 콘텐츠 배포 요청의 토픽 URL은 최초 구독 요청 시의 토픽 URL과 다를 수도 있습니다.

구독자의 콜백 URL은 반드시 HTTP [RFC7231] 2xx 응답 코드를 반환해야 성공으로 간주됩니다. 구독자 콜백 URL은 선택적으로 HTTP 410 코드를 반환해 구독이 삭제되었음을 알릴 수 있으며, 허브는 선택적으로 이 응답을 수신하면 구독을 종료할 수 있습니다. 허브는 반드시 그 밖의 구독자 응답 코드는 전부 실패로 간주해야 하므로, 구독자는 절대 구독 이전을 위해 HTTP 리디렉션을 사용해서는 안 됩니다. 구독자는 가급적 빨리 콘텐츠 배포 요청에 응답해야 하며, 성공 응답 코드는 메시지를 받았음을 알릴 뿐 구독자가 실제로 성공적으로 처리했다는 뜻은 아닙니다. 구독자의 응답 본문은 허브가 반드시 무시합니다. 허브는 정해진 횟수 한도와 시간 한도 내에서 콘텐츠 배포 요청을 재시도해야 하며, 실패한 전달이 한계를 넘으면 더 이상 전달을 시도하지 않아야 합니다. 허브는 반드시 임대 기간이 끝날 때까지 구독을 유지해야 하고, 새 업데이트가 게시되어도 반드시 이전에 실패한 구독자에게도 계속 전달을 재시도해야 합니다.

7.1 인증된 콘텐츠 배포

구독자가 구독 요청에 hub.secret 값을 포함했을 경우, 허브는 반드시 페이로드의 HMAC 서명을 생성해서 콘텐츠 배포 요청의 헤더로 포함해야 합니다. X-Hub-Signature 헤더 값은 반드시 method=signature 형식이어야 하며, 여기서 method는 인식된 알고리즘 명이고 signature는 16진 서명값입니다. 서명은 반드시 HMAC 알고리즘 [RFC6151] 으로, 데이터는 요청 본문, 키는 hub.secret로 계산해야 합니다.

7.1.1 인정하는 알고리즘 명칭

아래 알고리즘은 명세 당시에 [FIPS-PUB-180-4] 레지스트리에 등록된 주요 알고리즘 명입니다.

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

향후에는 구독자가 검증에 사용할 수 있는 알고리즘을 명시할 수 있도록 확장될 수 있습니다. 현재 시점 대부분의 허브는 호환성을 위해 취약성이 알려진 SHA-1을 사용해 서명합니다.

7.1.2 서명 검증

구독자가 X-Hub-Signature 헤더가 포함된 콘텐츠 배포 요청을 수신했을 때, 권장적으로 구독자는 허브가 사용한 것과 동일한 방식(헤더에 명시된 메소드와 secret)으로 서명을 다시 계산해 비교해야 합니다. 서명이 일치하지 않으면, 구독자는 반드시 이 메시지를 무효로 간주하고 무시해야 합니다. 구독자는 선택적으로 요청을 2xx 응답 코드로 수락해, 메시지를 비동기로 처리하거나 혹은 서명에 대한 무차별 대입 공격을 막기 위해 응답할 수 있습니다. 이 방법과 HTTPS [RFC2818]를 함께 사용하면, 단순 구독자도 HTTPS 서버를 실행하지 않고 허브로부터 인증된 콘텐츠 배포 요청을 수신할 수 있습니다.

단, 이 서명은 페이로드가 위조되지 않았음을 보장할 뿐입니다. 요청에 포함된 헤더까지 안전하다고 간주해서는 안 되며, 구독자가 HTTPS [RFC2818] 콜백을 사용할 경우에만 신뢰할 수 있습니다.

8. 보안 고려사항

다음은 보안 고려 사항 요약입니다. WebSub은 오로지 HTTP에 의존하는 서버 간 프로토콜임을 주목해야 하며, 모든 요청에 HTTPS 사용을 강력히 권장합니다.

8.1 발견

구독자가 <head>뿐만 아니라 페이지의 <body> 안의 <link> 요소도 검색해야 하는지 여부는 명확하지 않으며 현재 컨센서스가 없습니다. <body>를 무시하는 한 가지 이유는, 일부 사이트가 (실수로) <link> 요소가 포함된 사용자의 콘텐츠 등록을 허용할 수도 있기 때문입니다(비록 작업 그룹이 실제로 존재하는 사례를 아는 것은 아닙니다). WebSub 발견이 이러한 <link> 요소를 활용한다면, 한 사용자가 악의적으로 모든 구독자가 대체 허브를 이용하게 하여 이후 악성 콘텐츠를 배포하도록 할 수도 있습니다. 이러한 잠재 공격을 고려해, HTML 문서의 <head>에서만 발견을 수행하는 것이 안전할 수 있습니다.

8.2 구독

첫째로, 구독자는 허브의 URL이 HTTP로 광고된다 해도 항상 HTTPS URL을 우선으로 사용해야 합니다. 둘째로, 구독자는 콜백용으로 추측 불가능한 고유 capability URL을 사용하고, HTTPS로 접근할 수 있도록 해야 합니다. 마지막으로, 구독자는 콘텐츠 배포의 서명을 위해 구독 시 hub.secret을 사용하는 것이 권장됩니다.

허브는 권장적으로 짧은 hub.lease_seconds (10일 내외 권장)를 적용해야 합니다. 의도 검증 시, 허브는 권장적으로 임의의 1회용 hub.challenge를 사용해야 합니다.

8.3 배포

허브는 반드시 구독자가 실제로 사용한 콜백 주소(HTTPS 포함)를 사용해야 하며, 허브는 반드시 구독자의 요청에 hub.secret이 포함되어 있으면 해당 secret을 이용해 요청에 서명해야 합니다.

구독자가 hub.secret을 구독 요청에 포함시켰다면, 구독자는 허브가 제공한 서명을 검증하고, 검증 시에는 반드시 허브가 명시한 서명 메커니즘을 사용해, 실패할 경우 해당 요청을 무시해야 합니다.

구독자가 안전한 콜백 URL(HTTPS)을 사용하지 않거나, 허브-구독자 간 TLS 구간이 손상된 경우, 콘텐츠 전달 알림의 무결성은 hub.secret과 해시 알고리즘만으로 보호되니, 목적에 맞는 충분히 강력한 해시를 선택해야 합니다. SHA-1이 이미 깨졌으므로, 최소한 SHA-256 이상을 써야 합니다.

8.4 보안 및 개인정보 리뷰

아래 질문은 Self-Review Questionnaire: Security and Privacy ([security-privacy-questionnaire]) 가이드에 따라 이 명세서의 보안 및 개인 정보 이슈를 개관합니다.

이 명세는 개인식별 정보(PII)를 다루는가?
유일하게 관련될 수 있는 것은 토픽과 콜백 URL입니다.
이 명세는 고가치 데이터를 다루는가?
아니요, 인증이나 기타 자격증명은 포함되지 않습니다.
이 명세는 브라우저 세션 간 지속되는 새로운 상태를 도입하는가?
아니요.
이 명세는 웹에 지속적이고 크로스 오리진 상태를 노출하는가?
WebSub 구독자는 자신이 구독하는 토픽 정보를 포함하는 리소스를 생성해야 합니다.
이 명세는 현재 접근할 수 없는 데이터를 오리진에 노출하는가?
아니요.
이 명세는 새로운 스크립트 실행 또는 로딩 메커니즘을 도입하는가?
아니요.
이 명세는 오리진이 사용자의 위치 정보에 접근할 수 있도록 허용하는가?
아니요.
이 명세는 오리진이 사용자의 기기 센서에 접근할 수 있도록 허용하는가?
아니요.
이 명세는 오리진이 사용자의 로컬 컴퓨팅 환경의 일부에 접근할 수 있도록 허용하는가?
아니요.
이 명세는 오리진이 다른 기기에 접근하도록 허용하는가?
아니요.
이 명세는 오리진이 사용자 에이전트의 기본 UI를 제어할 수 있게 하는가?
아니요.
이 명세는 임시 식별자를 웹에 노출하는가?
아니요.
이 명세는 1st-party, 3rd-party 맥락에서 다른 거동을 구분하는가?
아니요.
이 명세는 브라우저 "시크릿 모드"에서 어떻게 동작해야 하는가?
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 에게 특별한 감사를 전합니다.

B. 변경 이력

이 섹션은 비규범적입니다.

B.1 2017년 10월 3일 PR에서 이 버전까지의 변경점

B.2 2017년 4월 11일 CR에서 2017년 10월 3일 PR까지의 변경점

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

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

C. 참고 문헌

C.1 규범적 참고문헌

[Encoding]
Encoding Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://encoding.spec.whatwg.org/
[HTML5]
HTML5. Ian Hickson; Robin Berjon; Steve Faulkner; Travis Leithead; Erika Doyle Navara; Theresa O'Connor; Silvia Pfeiffer. W3C. 2014년 10월 28일. W3C 권고안. URL: https://www.w3.org/TR/html5/
[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels. S. Bradner. IETF. 1997년 3월. Best Current Practice. URL: https://tools.ietf.org/html/rfc2119
[RFC2818]
HTTP Over TLS. E. Rescorla. IETF. 2000년 5월. Informational. URL: https://tools.ietf.org/html/rfc2818
[RFC5988]
Web Linking. M. Nottingham. IETF. 2010년 10월. Proposed Standard. URL: https://tools.ietf.org/html/rfc5988
[RFC6151]
Updated Security Considerations for the MD5 Message-Digest and the HMAC-MD5 Algorithms. S. Turner; L. Chen. IETF. 2011년 3월. Informational. URL: https://tools.ietf.org/html/rfc6151
[RFC7230]
Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing. R. Fielding, Ed.; J. Reschke, Ed.. IETF. 2014년 6월. Proposed Standard. URL: https://tools.ietf.org/html/rfc7230
[RFC7231]
Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content. R. Fielding, Ed.; J. Reschke, Ed.. IETF. 2014년 6월. Proposed Standard. URL: https://tools.ietf.org/html/rfc7231
[URL]
URL Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://url.spec.whatwg.org/

C.2 참고용 참고문헌

[capability-urls]
Good Practices for Capability URLs. Jeni Tennison. W3C. 2014년 2월 18일. W3C Working Draft. URL: https://www.w3.org/TR/capability-urls/
[FIPS-PUB-180-4]
Secure Hash Standard (SHS). National Institute of Standards and Technology. 미국 상무부. URL: http://dx.doi.org/10.6028/NIST.FIPS.180-4
[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
[RFC4287]
The Atom Syndication Format. M. Nottingham, Ed.; R. Sayre, Ed.. IETF. 2005년 12월. Proposed Standard. URL: https://tools.ietf.org/html/rfc4287
[RFC6838]
Media Type Specifications and Registration Procedures. N. Freed; J. Klensin; T. Hansen. IETF. 2013년 1월. Best Current Practice. URL: https://tools.ietf.org/html/rfc6838
[RSS-2.0]
RSS 2.0. Dave Winer. RSS Board. Stable. URL: http://www.rssboard.org/rss-specification
[security-privacy-questionnaire]
Self-Review Questionnaire: Security and Privacy. Mike West. W3C. 2015년 12월 10일. W3C Note. URL: https://www.w3.org/TR/security-privacy-questionnaire/