Professional Documents
Culture Documents
Chương
Chương
bất kỳ tài liệu XML nào. Nhưng tôi nghi ngờ đó không phải là điều bạn đang nghĩ tới. Bạn có thể muốn thứ gì
Nếu bạn muốn cung cấp các biểu diễn JSON và XML có cùng ngữ nghĩa, bạn nên chọn một tiêu chuẩn hypermedia
cung cấp cả hai “hương vị”. Hiện tại điều đó có nghĩa là HAL hoặc OData, mặc dù phiên bản XML của Siren đã
Nếu API của bạn ở chế độ chỉ đọc—nghĩa là sơ đồ trạng thái của bạn không bao gồm bất kỳ chuyển đổi không an
toàn nào—bạn có rất nhiều lựa chọn tốt. Tôi đề xuất HTML, HAL hoặc JSON-LD.
Nếu API của bạn bao gồm các chuyển đổi không an toàn thì điều đó sẽ hạn chế các lựa chọn của bạn. JSON-LD
không thể tự biểu thị các chuyển đổi trạng thái không an toàn; bạn sẽ cần thêm Hydra (xem Chương 12). HAL hỗ
trợ các quá trình chuyển đổi không an toàn, nhưng theo một cách nào đó, tôi nghĩ nó hoạt động không hiệu quả.
Bộ sưu tập+JSON hỗ trợ ba chuyển đổi không an toàn cụ thể: thêm mục mới vào bộ sưu tập, chỉnh sửa mục và xóa
mục. Đó là nó. Bạn không thể sử dụng bất kỳ chuyển đổi không an toàn nào ngoài ba chuyển tiếp được xác định
của bạn gửi một biểu diễn, nó sẽ bao gồm tiêu đề Kiểu nội dung , cho khách hàng biết cách phân tích cú pháp
biểu diễn. Bạn cũng sẽ bao gồm một liên kết đến một hoặc nhiều cấu hình, điều này sẽ giải thích ngữ nghĩa
Ở bước 3, bạn có thể sẽ tìm thấy một số cấu hình hiện có bao hàm một số ngữ nghĩa ứng dụng của mình, nhưng
có thể bạn sẽ không thể bao quát được mọi thứ. Sẽ có điều gì đó đặc biệt về API của bạn. Bạn sẽ mô tả những
Đoạn mã đánh dấu này cho trò chơi mê cung của Chương 7 nhập hai cấu hình ALPS—một cấu hình từ Alps.io mang
ngữ nghĩa của Mê cung+XML và một cấu hình tùy chỉnh giải thích bổ sung duy nhất tôi đã thực hiện cho Mê
Hồ sơ của bạn có thể là tài liệu ALPS, ngữ cảnh JSON-LD hoặc trang web sử dụng vi định dạng XMDP. Nếu không
có lựa chọn nào trong số này phù hợp với bạn, bạn có thể từ bỏ ý tưởng về một hồ sơ có thể đọc được bằng máy
và thay vào đó viết một hồ sơ có thể đọc được bằng con người.
Hồ sơ mà con người có thể đọc được trông giống như tài liệu API truyền thống. Đó là một trang web trình bày
ý nghĩa của tất cả các mối quan hệ liên kết và mô tả ngữ nghĩa. Bạn vẫn có thể sử dụng lại các mối quan hệ
liên kết và mô tả từ Alps.io và các hồ sơ khác—chỉ cần sao chép và dán văn bản, đồng thời đảm bảo liên kết
lớn thời gian cho bước này và tôi không có nhiều lời khuyên vì nó phụ thuộc vào framework và ngôn ngữ lập
có một sơ đồ trạng thái và một hồ sơ mà bạn hài lòng thì đó không hẳn là một công việc dễ dàng
may mắn và tìm thấy một tiêu chuẩn dành riêng cho miền hiện có thực hiện chính xác những gì bạn
cần mà không cần tiện ích mở rộng cần thiết thì bạn đã bỏ qua ngay đến bước 6 và giờ bạn đã hoàn
tất. Tài liệu API của bạn bao gồm một URL ("URL bảng quảng cáo" của API của bạn) và một giá trị
cho tiêu đề Kiểu nội dung .
Nhưng điều đó gần như không bao giờ xảy ra. Việc đáp ứng các yêu cầu kinh doanh của bạn chắc
chắn đòi hỏi bạn phải mở rộng tiêu chuẩn hiện có hoặc thiết kế một tiêu chuẩn hoàn toàn mới.
Tại thời điểm này trong quy trình, bạn đã thiết kế phần “mới” và mô tả nó bằng cách sử dụng một
số kết hợp giữa cấu trúc máy có thể đọc được (như cấu hình ALPS) và văn bản con người có thể
đọc được (như định nghĩa về loại phương tiện) . Việc duy nhất còn lại là công bố thông tin đó.
Điều này phức tạp hơn việc chỉ đưa một số tài liệu API lên trang web của bạn, nhưng nó cũng
không phức tạp hơn nhiều . Tôi chỉ trình bày tất cả để bạn không vô tình bỏ qua một bước.
cáo của bạn Quay lại bước 2, tôi đã nói rằng bạn nên có một hộp trên sơ đồ trạng thái có một
mũi tên bất ngờ xuất hiện. Hộp này đại diện cho trang chủ của bạn: một cổng siêu phương tiện
tới tất cả các tài nguyên khác của bạn. Mọi người muốn viết ứng dụng khách cho API của bạn đều
phải biết URL trang chủ của bạn. Phần còn lại có thể thương lượng.
Nếu bạn đã vượt qua bước 2 mà không thiết kế tài nguyên “trang chủ”, tôi khuyên bạn nên quay
lại bước 2 và thiết kế một tài nguyên. URL biển quảng cáo là phần thông tin quan trọng nhất về
API của bạn, vì đó là cửa ngõ dẫn đến mọi thứ khác.
bạn Tài liệu hồ sơ của bạn xuất hiện trên trang web của bạn, cùng với phần còn lại của thông
tin về API. Nếu bạn đã viết hồ sơ ALPS, tôi sẽ đánh giá cao nếu bạn cũng đăng ký hồ sơ đó với
Cơ quan đăng ký ALPS tại Alps.io. Điều này sẽ giúp người khác tìm và sử dụng lại các mối quan
mới Có thể bạn sẽ không cần thiết kế loại phương tiện mới, vì vậy tôi sẽ không chiếm chỗ ở đây
để giải thích những việc cần làm sau khi bạn thiết kế xong. (Thay vào đó, tôi sẽ đề cập đến vấn
đề này sau, trong phần “Nếu bạn thiết kế một loại phương tiện truyền thông” ở trang 183). Đủ để
nói rằng sau khi triển khai hoạt động, bạn phải đủ tự tin vào thiết kế của mình để đăng ký loại
mới Nếu các quan hệ liên kết của bạn là URL (RFC 5988 gọi là “các loại quan hệ mở rộng”), bạn không cần
phải làm bất kỳ điều gì đặc biệt ở đây. Không ai có thể xác định mối quan hệ liên kết xung đột với mối
quan hệ của bạn, bởi vì bạn đã đặt tên cho các mối quan hệ của mình theo tên miền mà bạn kiểm soát. Nếu
bạn không nghĩ rằng bất kỳ nhà cung cấp API nào khác sẽ muốn sử dụng lại các mối quan hệ liên kết của
mình, bạn cũng có thể tránh cho mình một số rắc rối và sử dụng các mối quan hệ mở rộng.
Nhưng xuyên suốt cuốn sách này, tôi đã tránh xa các mối quan hệ liên kết mở rộng. Chúng quá dài
để sử dụng đi sử dụng lại trong bản in. Thay vào đó, tôi đã sử dụng các mối quan hệ liên kết là
các chuỗi ngắn, như west và flip. RFC 5988 gọi đây là “các loại quan hệ đã đăng ký” và để tránh
xung đột, chúng cần phải được đăng ký ở đâu đó. Nếu bạn đọc một tài liệu HTML sử dụng
rel="current", thì phải rõ ràng liệu hiện tại đề cập đến mục gần đây nhất trong bộ sưu tập hay
đến phép đo dòng điện.
RFC 5988 không nói chính xác cách đăng ký mối quan hệ liên kết, nhưng tôi muốn nói có bốn cách:
• Nó có thể được tìm thấy trong sổ đăng ký quan hệ liên kết của IANA. Bất kỳ nhà cung cấp API nào cũng được
phép sử dụng các mối quan hệ liên kết đã đăng ký IANA trong các biểu diễn của mình mà không cần xác định chúng.
Một ví dụ hữu ích là mối quan hệ trả lời được xác định trong RFC 4685.
Phần 6.2 của RFC 5988 mô tả quy trình đăng ký IANA. Việc đưa mối quan hệ liên kết vào sổ
đăng ký này yêu cầu phải viết RFC (hoặc tài liệu tương đương) và chỉ những mối quan hệ hữu
ích nói chung mới được chấp nhận, vì vậy tương đối ít nhà phát triển sẽ đi theo con đường
này.
• Mối quan hệ liên kết có thể được xác định cùng với loại phương tiện, theo cách Maze+XML xác
định hướng tây và lối ra. Một số loại phương tiện khác có thể định nghĩa mối quan hệ thoát
khác nhau, nhưng ai quan tâm? Một tài liệu chỉ có thể có một loại phương tiện nên luôn rõ
Nếu loại phương tiện xác định mối quan hệ liên kết xung đột với mối quan hệ đã đăng ký với
IANA thì định nghĩa của loại phương tiện đó sẽ được ưu tiên. Đừng cố ý làm điều này!
Tôi đang đánh vần quy tắc này để ngữ nghĩa ứng dụng API của bạn không thay đổi vì loại phương
tiện của nó sử dụng mối quan hệ liên kết mà ai đó vừa đăng ký với
IANA.
• Mối quan hệ liên kết có thể được xác định trong một cấu hình máy có thể đọc được chẳng hạn
như tài liệu ALPS. Một số hồ sơ khác có thể định nghĩa mọi thứ khác nhau, nhưng ai quan tâm?
Nếu một cấu hình xác định mối quan hệ liên kết xung đột với mối quan hệ được xác định bởi
loại phương tiện hoặc mối quan hệ đã đăng ký IANA thì định nghĩa của cấu hình sẽ được ưu tiên.
Một lần nữa, đừng cố ý làm điều này. Đây là quy tắc “trong trường hợp khẩn cấp”.
• Mối quan hệ liên kết có thể được đăng ký với Microformats wiki.1 Trang wiki không độc quyền lắm; nó cố gắng lập
danh mục mọi mối quan hệ liên kết từng thấy hoặc được đề xuất sử dụng trong HTML.
Wiki Microformats tạo ra một nền tảng thử nghiệm tốt cho các mối quan hệ liên kết mà một ngày nào đó có thể được
đưa vào sổ đăng ký IANA. Nếu bạn muốn người khác sử dụng mối quan hệ liên kết mà bạn đã phát minh ra, việc đưa
nó lên wiki này là một cách hay để kiểm tra nó. Nếu không, tôi khuyên bạn nên sử dụng mối quan hệ mở rộng thay
thế.
Với ALPS, bạn có thể chia đôi sự khác biệt. Bạn có thể sử dụng URL đầy đủ cho bất kỳ mối quan hệ liên kết nào được xác
định trong tài liệu ALPS dưới dạng mối quan hệ liên kết mở rộng (ví dụ: http://alps.io/example/ maze#exit), ngay cả
khi bạn chưa đưa tài liệu ALPS đó làm hồ sơ. Khi bạn đưa tài liệu ALPS làm hồ sơ, bạn có thể xử lý các quan hệ liên
Còn rất nhiều tài liệu nữa sẽ được xuất bản, nhưng tất cả đều là tài liệu dành riêng cho API của bạn mà con người có
thể đọc được: tóm tắt, ví dụ, mã mẫu, hướng dẫn thiết lập ủy quyền, bản sao tiếp thị giải thích API của bạn khác với
Nội dung này quan trọng nhưng bạn không cần sự khuyến khích của tôi để xuất bản nó. Đây là thứ chúng tôi nghĩ đến khi
nghĩ về tài liệu API. Tôi đã hạ thấp tầm quan trọng của tài liệu mà con người có thể đọc được trong suốt quá trình
này, vì theo kinh nghiệm của tôi, nó thường được sử dụng để thay thế cho các điều khiển siêu phương tiện.
Máy khách phần mềm có khả năng hạn chế trong việc thích ứng với những thay đổi trong tài liệu hypermedia.
Phần mềm dựa trên các tài liệu con người có thể đọc được không có khả năng thích ứng. Nếu một API chỉ được mô tả bằng
văn xuôi thì việc thay đổi văn xuôi có nghĩa là viết lại tất cả các ứng dụng khách. Đó là một vấn đề lớn với các API
hiện tại và đó là vấn đề mà tôi đang cố gắng giải quyết bằng cuốn sách này.
Tôi muốn kéo dài khả năng thích ứng của khách hàng càng nhiều càng tốt. Điều này có nghĩa là một quy trình thiết kế
tập trung chặt chẽ vào việc tạo ra các tài liệu có thể đọc được bằng máy, trong đó các tài liệu mà con người có thể
đọc được chỉ nhằm mục đích mang lại sự thuận tiện cho con người.
Đây là một suy nghĩ: điều gì sẽ xảy ra nếu bạn không cần quảng cáo URL biển quảng cáo của mình? Điều gì sẽ xảy ra nếu
khách hàng của bạn biết cách tìm điểm vào API của bạn? Đó là lời hứa về “URI nổi tiếng” của IANA được thành lập vào
Nếu máy chủ trình bày các biểu diễn ở Định dạng Liên kết CoRE (được đề cập trong Chương 13), thì không cần phải thắc
URL (tương đối) đó được đăng ký với IANA. Thay vì tìm hiểu một URL biển quảng cáo khác nhau cho mỗi máy chủ, máy khách
core và nhận danh sách các liên kết hypermedia đến các tài nguyên khác được lưu trữ trên máy
chủ đó. Máy chủ phân phát tài liệu siêu dữ liệu máy chủ web (Chương 12) phải luôn phân phối
tài liệu đó từ /.well-known/host-meta hoặc /well-known/host-meta.json.
Đây là một điều khá nhỏ, nhưng nó đóng lại phần cuối cùng của khoảng cách ngữ nghĩa. Nhờ Cơ
quan đăng ký URI nổi tiếng, về mặt lý thuyết, khách hàng có thể khám phá và tìm hiểu một API
mới, chỉ cần cung cấp tên máy chủ.
Điều đáng chú ý là các URI nổi tiếng thường được liên kết với các loại phương tiện cụ thể.
Khi tôi viết bài này, nếu bạn không sử dụng Định dạng liên kết CoRE hoặc siêu dữ liệu máy
chủ web, bạn không thể xuất bản API của mình tại một URI nổi tiếng. Đó là hai định dạng duy
nhất trong Sổ đăng ký URI nổi tiếng hữu ích cho API.
Phải mất một thời gian để chạy trò chơi mê cung của Chương 7 trong suốt quá trình thiết kế của tôi,
bởi vì tôi đã giải thích từng bước của quy trình khi thực hiện. Đây là một ví dụ khác ngắn hơn
nhiều. Tôi sẽ chỉ đưa ra các quyết định của mình thay vì giải thích tất cả các bước. Miền vấn đề
của tôi sẽ là trang web “Bạn gõ nó, chúng tôi đăng nó” từ Chương 1. Tôi sẽ thực hiện năm bước đầu
tiên và kết thúc bằng một thiết kế và một hồ sơ, nhưng không thực hiện.
Nhìn vào mô tả của trang web từ Chương 1, tôi đã xác định được các mô tả ngữ nghĩa sau:
• Trang chủ
Sau đó, tôi nhóm các phần mô tả theo cách mà tôi cho là hợp lý. Kết quả là trong Hình 9-9.
Tôi có ba loại trình bày riêng biệt: văn bản “về trang web này”, danh sách thư và một thư
riêng lẻ. Tôi quyết định sử dụng danh sách tin nhắn làm “trang chủ” thay vì có một trang chủ
riêng chỉ liên kết đến danh sách tin nhắn và “về trang web này”.
Hình 9-9. Các bộ mô tả ngữ nghĩa cho You Type It…, được nhóm thành các biểu diễn
Hình 9-10. Sơ đồ trạng thái ban đầu cho API You Type It…
Sử dụng các liên kết trên trang web You Type It… làm hướng dẫn, tôi đã kết nối ba loại tài
nguyên với các chuyển đổi trạng thái an toàn. Tôi cũng đã tạo một quá trình chuyển đổi trạng
thái không an toàn, tương ứng với biểu mẫu HTTP POST trên trang web tạo thông báo mới.
tên đã đăng ký IANA: about, sưu tập và mục. Văn bản “về trang web này” là một tài liệu mà con
người có thể đọc được, vì vậy tôi sẽ không lo lắng về các phần mô tả ngữ nghĩa của nó.
Còn lại sáu thứ cần đặt tên mà IANA không giúp được gì: “danh sách tin nhắn”, “tin nhắn”,
“tạo”, “ID”, “văn bản” và “ngày xuất bản”. Xem qua “Sở thú ngữ nghĩa” ở trang 230 sẽ giúp ích
cho năm vấn đề trong số đó.
Có một mục vi dữ liệu lược đồ.org có tên là BlogPosting (http://schema.org/BlogPost ing), mục
này xác định các bộ mô tả ngữ nghĩa được gọi là ArticleBody và dateCreated. Cái đó
quản lý “tin nhắn”, “văn bản” và “ngày xuất bản”. Một tập hợp các bài đăng trên blog của Schema.org
Tôi sẽ đặt tên cho bài chuyển tiếp trạng thái không an toàn của mình. Tôi lấy tên đó từ tiêu chuẩn
Luồng hoạt động, trong đó nó có nghĩa là “Hành động tạo một đối tượng và sau đó xuất bản nó trực tuyến”.
Không ai từng dự định các động từ vi dữ liệu lược đồ.org và Luồng hoạt động sẽ hoạt động cùng nhau,
nhưng ALPS cho phép tôi kết hợp ngữ nghĩa ứng dụng của chúng.
Điều đó để lại ID tin nhắn. Tôi quyết định tôi thực sự không cần phải cung cấp thông tin này. Mỗi tin
nhắn đã có một ID duy nhất: URL của nó. Tại sao khách hàng nên quan tâm đến ID nội bộ mà máy chủ sử
Hình 9-11 hiển thị sơ đồ trạng thái của tôi sau khi tôi đối chiếu các tên. Lưu ý rằng liên kết mục
hiện có hai quan hệ liên kết: item và blogPost. Mối quan hệ liên kết thứ hai xuất phát từ mục Blog
của lược đồ.org , mục này xác định blogPost là mối quan hệ giữa một Blog và một BlogPost. Điều này
hơi dư thừa với mối quan hệ mục chung chung hơn của IANA , nhưng không có lý do gì tôi không thể gắn
cả hai mối quan hệ liên kết vào một liên kết duy nhất. Bằng cách đó, những khách hàng hiểu Blog và
BlogPost của lược đồ cũng sẽ không cần hiểu mục của IANA.
Hình 9-11. Sơ đồ trạng thái cho API You Type It…, sau khi đối chiếu tên.
Tôi có đang tạo API tiểu blog thứ 58 trên thế giới không? Theo một nghĩa nào đó, đúng vậy. Nhưng tôi
không định nghĩa điều gì mới cả. Tôi đã lấy mọi thứ từ IANA, Schema.org và Luồng hoạt động. Một khách
hàng đã hiểu các bộ mô tả ngữ nghĩa và các mối quan hệ liên kết này sẽ hiểu API của tôi. Không có
nhiều khả năng một khách hàng như vậy tồn tại, nhưng có nhiều khả năng một phần của khách hàng đó tồn
tại hơn là nếu tôi thiết kế lại những khái niệm cơ bản này lần thứ 58.
thể chọn từ rất nhiều loại phương tiện. Sơ đồ trạng thái của tôi giống như Hình 9-7, vì vậy loại
phương tiện triển khai mẫu bộ sưu tập sẽ giúp ích rất nhiều. API YouTypeItWePostIt.com thực tế, như
được trình bày trong Chương 2, sử dụng Collection+JSON. Tôi cũng có thể đi theo con đường hypermedia
HTML. Và tôi thậm chí có thể chọn một tiêu chuẩn dành riêng cho tên miền. Trong Chương 6, tôi
coi AtomPub như một tiêu chuẩn chung về “mẫu bộ sưu tập”, nhưng ban đầu nó được xác định cụ thể
Sự lựa chọn của tôi có thể thay đổi từ vựng tôi sử dụng. Nếu tôi chọn Atom làm định dạng trình
bày của mình, tôi cần ngừng gọi nội dung của thông báo là ArticleBody và bắt đầu gọi nó là nội
dung, vì đó là cách Atom gọi nó.
Để đa dạng hơn, tôi sẽ chọn HAL. Biểu diễn HAL+XML của danh sách thư có thể trông như thế này:
<resource href="/">
<link rel="profile" href="http://alps.io/schema.org/Blog"/> <link
rel="profile" href="http://alps. io/schema.org/BlogPost"/> <link rel="profile"
href="http://alps.io/activitystrea.ms/verbs"/> <link rel="about" href="/about-
this -trang">
<Blog>
<link rel="post" href="/messages"/>
Điều này truyền tải tất cả trạng thái tài nguyên cần thiết (mô tả về hai thông báo trong
danh sách thông báo) và bao gồm tất cả các liên kết hypermedia cần thiết (với hồ sơ quan hệ
liên kết , giới thiệu, mục và bài đăng).
Đã xảy ra sự cố với liên kết bài đăng : không rõ liệu đó có phải là quá trình chuyển đổi trạng
thái không an toàn cần được kích hoạt bằng POST hay không và không rõ khách hàng nên gửi nội
dung thực thể nào cùng với yêu cầu POST. Nhưng đó là do thiếu sót chung của HAL. Nếu tôi không
thích tính năng đó của HAL, tôi có thể chọn loại phương tiện khác vào thời điểm này.
Viết hồ sơ
Vì tôi đã lấy tất cả ngữ nghĩa ứng dụng của mình từ các hồ sơ hiện có nên về mặt kỹ thuật tôi
không cần phải viết hồ sơ của riêng mình. Biểu diễn ví dụ chỉ liên kết đến ba cấu hình ALPS
hiện có:
Điều đó bao gồm mọi thứ ngoại trừ mối quan hệ liên kết IANA và mục mà tôi được phép sử dụng
mà không cần giải thích.
Đây là hồ sơ ALPS độc lập cho thiết kế “Bạn gõ nó, chúng tôi đăng nó” của tôi (nó hơi dư
thừa, nhưng đó là một tài liệu duy nhất chứa tất cả các mối quan hệ liên kết và mô tả ngữ
nghĩa mà API của tôi thực sự sử dụng):
<alps>
<descriptor id="about" type="semantic"
href="http://alps.io/iana/relations#about"/>
Thay vì có ba liên kết hồ sơ , một trong những đại diện của tôi chỉ có thể liên kết đến hồ
sơ này.
Một khách hàng không hiểu hồ sơ của tôi có thể coi các biểu diễn của tôi như các biểu diễn
HAL thuần túy. Điều này sẽ không hữu ích lắm vì HAL không tự xác định bất kỳ giao thức hoặc
ngữ nghĩa ứng dụng nào. Trình duyệt HAL có thể phân tích các biểu diễn của tôi và phân biệt
các liên kết với dữ liệu, nhưng nó sẽ không biết các liên kết hoặc dữ liệu có ý nghĩa gì.
Hy vọng đến thời điểm này bạn đã hiểu rõ về quá trình thiết kế của tôi.
Bây giờ tôi muốn đưa ra một số bài học thực tế mà tôi đã học được từ việc phát triển và áp
dụng quy trình này.
Tài nguyên là chi tiết triển khai Hầu hết các quy
trình thiết kế API web RESTful đều tập trung vào thiết kế tài nguyên. Nhưng không có tài nguyên ở
đây. Các hộp trong sơ đồ trạng thái không phải là tài nguyên, chúng là biểu diễn của tài nguyên—các
tài liệu thực tế được gửi qua lại giữa khách hàng và
máy chủ.
Đây không phải là một sự giám sát. Tài nguyên là yếu tố chính đối với HTTP và chúng rất quan trọng
đối với việc triển khai API, nhưng tôi nhận ra rằng thực chất chúng không quan trọng lắm đối với
REST. Quá trình thiết kế của tôi tập trung vào chuyển đổi trạng thái và mô tả ngữ nghĩa. Một khi
bạn đã xác định được những điều đó, bạn sẽ có được nguồn lực của mình.
Hãy nghĩ về HTTP qua lại giữa máy khách và máy chủ. Một tài nguyên nhận được yêu cầu GET và phục vụ
một đại diện với một loại phương tiện nhất định. Biểu diễn chứa các điều khiển hypermedia, mô tả
các chuyển đổi trạng thái có thể xảy ra. Máy khách kích hoạt chuyển đổi trạng thái bằng cách gửi
yêu cầu HTTP đến tài nguyên khác, thực hiện thay đổi trạng thái và gửi một đại diện khác. Máy khách
không bao giờ tương tác trực tiếp với một tài nguyên.
Nếu bạn đến bước 6 và nhận thấy mình cần triển khai một số tài nguyên ngoài dự kiến, tôi e rằng bạn
đã bỏ qua một bước. Tài nguyên bạn đang tưởng tượng cần được liên kết từ một số tài nguyên hiện có.
Liên kết đó là một quá trình chuyển đổi trạng thái và nó phải hiển thị trên một mũi tên trong sơ đồ
trạng thái của bạn (bước 2). Nếu tài nguyên quản lý trạng thái của chính nó thì nó cần có một biểu
diễn. Biểu diễn đó lẽ ra phải hiển thị dưới dạng một hộp trên sơ đồ trạng thái của bạn (bước 2).
Biểu diễn phải có loại phương tiện (bước 4) và có thể có hồ sơ (bước 5). Dữ liệu mà nó truyền đến
máy khách lẽ ra phải hiển thị trong danh sách lớn mà bạn đã lập ở bước 1. Nếu tài nguyên hỗ trợ bất
kỳ chuyển đổi trạng thái không an toàn nào thì những chuyển đổi đó sẽ hiển thị ở bước 2. Chúng phải
được mô tả bằng điều khiển siêu phương tiện được nhúng bên trong một số đại diện.
Nếu bạn chưa quyết định về ngữ nghĩa giao thức và ngữ nghĩa ứng dụng của tài nguyên thì bạn chưa
thực sự thiết kế nó. Nếu bạn đã quyết định những điều đó thì không còn gì khác để thiết kế.
Việc tập trung vào tài nguyên trước tiên sẽ không mang lại cho bạn một thiết kế tồi nhưng nó có xu
hướng thể hiện một thiết kế về mặt triển khai phía máy chủ hơn là về mặt trải nghiệm của khách hàng.
Cũng dễ dàng sử dụng thiết kế tài nguyên tốt (được hỗ trợ bởi rất nhiều tài liệu mà con người có
tập rất chung chung và mạnh mẽ nhưng nó lại chứa một cái bẫy. Tôi đã chứng kiến cái bẫy này xuất
hiện hàng chục lần trong vài năm qua và lời khuyên mà tôi cân nhắc là đừng mắc bẫy. Đừng sử dụng
Thoạt nhìn, việc sử dụng lược đồ cơ sở dữ liệu có vẻ là một ý tưởng tuyệt vời. Cơ sở dữ liệu SQL,
với bốn lệnh cơ bản (CHỌN/CHÈN/CẬP NHẬT/XÓA) ánh xạ tự nhiên vào mẫu CRUD (tạo/truy xuất/cập nhật/
xóa), ánh xạ tự nhiên vào mẫu bộ sưu tập dành cho API, ánh xạ tự nhiên vào bốn phương thức HTTP chính
(GET/POST/PUT/DELETE). Không có lý do kỹ thuật nào khiến bạn không thể bỏ qua hầu hết quy trình của
tôi và xuất bản lược đồ cơ sở dữ liệu của mình thông qua mẫu bộ sưu tập. Điều gì có thể xảy ra?
Nhờ các công cụ hiện đại, chiến lược này sẽ nhanh chóng giúp bạn có được một API hoạt động được nhưng
nó có hai vấn đề lớn. Nguyên nhân đầu tiên xuất phát từ thực tế là người dùng của bạn không quan tâm
đến lược đồ cơ sở dữ liệu của bạn. Họ quan tâm đến ngữ nghĩa ứng dụng của bạn và cả hai chỉ liên quan
một cách mơ hồ. Bạn sẽ không thiết lập một trang web chỉ là một giao diện thô cho cơ sở dữ liệu của
mình. Bạn nên đặt suy nghĩ tương tự vào việc thiết kế API giống như cách bạn thiết kế một trang web.
Mặt khác, bạn quan tâm đến lược đồ cơ sở dữ liệu của mình—đến mức bạn có quyền thay đổi lược đồ khi
yêu cầu của bạn thay đổi. Đó là vấn đề thứ hai. Khi bạn xuất bản một API dựa trên lược đồ cơ sở dữ
liệu, về cơ bản, những thay đổi đối với lược đồ đó trở nên không thể thực hiện được. Bạn đã trao
quyền phụ thuộc phần mềm vào lược đồ cơ sở dữ liệu của mình cho hàng nghìn người mà bạn chưa từng
nghe tên. Những người này là khách hàng của bạn và hỗ trợ họ là trách nhiệm của bạn. Những thay đổi
đối với lược đồ, những thay đổi mà người dùng trang web của bạn thậm chí sẽ không nhận thấy, sẽ gây
Có tất cả các loại kỹ thuật để giải quyết những vấn đề này và tôi sẽ thảo luận về chúng trong “Khi
API của bạn thay đổi” ở trang 185. Nhưng chiến lược tốt nhất là tránh rơi vào tình huống này ngay từ
đầu.
Đó là một lý do khác khiến quy trình của tôi sử dụng sơ đồ trạng thái. Giữ bạn thoát khỏi cái bẫy
này là mối quan tâm lớn của tôi. Suy nghĩ về việc chuyển đổi trạng thái buộc bạn phải xem xét ứng
dụng của mình chứ không phải cơ sở dữ liệu chứa tất cả trạng thái tài nguyên.
Tôi không nói để tránh mô hình bộ sưu tập. Đó là một mô hình tuyệt vời. Nếu sơ đồ trạng thái của bạn
trông giống như Hình 9-7, hãy tiếp tục và sử dụng nó. Nhưng hãy vẽ sơ đồ trạng thái trước. Đừng nhầm
lẫn ngữ nghĩa giao thức do ứng dụng của bạn xác định với giao diện do cơ sở dữ liệu của bạn xác định.
Đừng bắt đầu với Định dạng trình bày Bạn có thể muốn chọn định
dạng trình bày trước khi bắt đầu bước 1, để bạn có thể hình dung tài liệu của mình sẽ trông như thế
nào khi bạn tìm ra ngữ nghĩa. Bạn có thể sử dụng định dạng chung như HTML để vẽ nguệch ngoạc, nhưng
tôi khuyên bạn nên tạm dừng quyết định cho đến khi bạn chuyển sang bước 4, dù chỉ là tạm thời. Đó là
vì các định dạng trình bày không chỉ là nơi chứa dữ liệu thụ động. Họ đưa ra các giả định về ngữ
nghĩa giao thức và ứng dụng vào mọi API sử dụng chúng. Những giả định này có thể xung đột với yêu
Lấy một ví dụ ngớ ngẩn, giả sử bạn bắt đầu thiết kế API bằng cách chọn sử dụng Mê cung +XML, chỉ vì đó là định
dạng trình bày đầu tiên mà tôi đã thảo luận chi tiết. Có lẽ bạn đang phạm sai lầm. Mê cung+XML xác định một sơ
đồ trạng thái rất cụ thể trông giống như sơ đồ trong Hình 9-6. Nó xác định một tập hợp ngữ nghĩa ứng dụng trong
đó các yêu cầu GET có nghĩa là “đi vào mê cung”, “di chuyển theo một hướng nhất định” hoặc “thoát khỏi mê
cung”. Nói tóm lại, Mê cung+XML dành cho trò chơi mê cung.
Bạn không thể chọn Mê cung+XML cho đến khi bạn thực hiện xong hai bước đầu tiên. Bạn cần phân tách các yêu cầu
kinh doanh của mình thành một tập hợp ngữ nghĩa giao thức và ngữ nghĩa ứng dụng. Nếu hóa ra chúng phù hợp với
ngữ nghĩa được xác định bởi Mê cung+XML thì điều đó thật tuyệt.
Để lấy một ví dụ ít ngớ ngẩn hơn, giả sử bạn bắt đầu bằng cách quyết định sử dụng Collection+JSON (hoặc AtomPub
hoặc OData) cho API của mình. Điều đó có nghĩa là bạn đã chọn một tập hợp ngữ nghĩa triển khai mẫu bộ sưu tập.
Bạn đang tuyên bố trước rằng sơ đồ trạng thái API của bạn trông giống như Hình 9-7.
Làm sao bạn có thể nói trước được điều đó? Nếu ngữ nghĩa giao thức của bạn phù hợp với mẫu bộ sưu tập (và chúng
thường như vậy), thì các tiêu chuẩn mẫu bộ sưu tập chính là thứ bạn cần. Nhưng bạn không thể cứ theo trực giác;
Tất nhiên, nếu việc sử dụng một định dạng trình bày cụ thể là một trong những yêu cầu kinh doanh của bạn, bạn
cũng có thể đưa ra quyết định đó trước tiên và thiết kế API của mình xung quanh định dạng trình bày bắt buộc.
Nếu API của bạn là một phần của hệ thống nhúng tiêu thụ điện năng thấp, bạn có thể phải xây dựng nó dựa trên
Định dạng Liên kết CoRE (xem Chương 13). Nếu bạn làm việc cho một công ty nằm trong Ủy ban Kỹ thuật OData và
đã triển khai 75 API OData (Chương 10), hãy đoán xem—bạn có thể đang thiết kế số
76.
Điều này không có nghĩa là API của bạn bị hỏng. Hypermedia mang đến cho bạn rất nhiều sự linh hoạt. Nếu cần,
bạn có thể triển khai bất kỳ API nào bạn muốn dưới dạng tiện ích mở rộng cho Mê cung+XML. Chỉ cần coi nó như
một ràng buộc bổ sung, bên cạnh các ràng buộc Fielding.
dẫn thiết kế API, bao gồm cả Dịch vụ web RESTful ban đầu , dành nhiều thời gian để nói về các URL bạn nên gán
cho tài nguyên của mình. Mỗi URL bạn phân phối phải xác định rõ ràng tài nguyên theo cách mà con người nhìn vào
Nếu bạn xuất bản một tài nguyên là tập hợp các tài khoản người dùng, nó sẽ được gọi là /users/. Các tài nguyên
cấp dưới phải được xuất bản bên dưới nguồn gốc của chúng. Vì vậy, tài nguyên đại diện cho tài khoản của Alice
Về mặt kỹ thuật, không có vấn đề gì trong số này. URL chỉ là địa chỉ của một tài nguyên mà khách
hàng có thể sử dụng để nhận thông tin đại diện. Về mặt kỹ thuật, URL không nói bất cứ điều gì về
tài nguyên hoặc cách trình bày của nó. Kiến trúc của World Wide Web, Tập Một diễn đạt như sau:
Thật thú vị khi đoán bản chất của một tài nguyên bằng cách kiểm tra URI xác định nó.
Tuy nhiên, Web được thiết kế sao cho các tác nhân truyền đạt trạng thái thông tin tài nguyên thông
qua các biểu diễn chứ không phải các mã định danh. Nói chung, người ta không thể xác định loại biểu
diễn tài nguyên bằng cách kiểm tra URI cho tài nguyên đó.
Điều này có nghĩa là việc tập hợp tài khoản người dùng có URL /0000000000000a và tập hợp đó liên kết
với tài khoản người dùng của Alice bằng URL /prime-numbers?how_many=200 là hoàn toàn hợp pháp. Điều
quan trọng là việc trình bày một tập hợp người dùng cho thấy rõ rằng nó đại diện cho một tập hợp
người dùng và việc trình bày tài khoản người dùng của Alice chứa thông tin về trạng thái của tập
hợp đó.
nguồn.
Khi bạn nhìn vào một URL và cố gắng hiểu tài nguyên cơ bản, bạn đang cố gắng tìm ra ngữ nghĩa cấp
ứng dụng của tài nguyên đó. Tốt rồi. Lời khuyên về thiết kế URL được đưa ra trong các cuốn sách và
hướng dẫn khác là lời khuyên hữu ích. Nhưng tôi sẽ không nhắc lại lời khuyên đó trong cuốn sách này,
vì tôi không muốn các API của bạn dựa vào URL để truyền tải ngữ nghĩa cấp ứng dụng của chúng. Chúng
tôi có những cách đáng tin cậy hơn để mô tả nội dung đó: định nghĩa loại phương tiện và cấu hình
Đây là một ví dụ. Nhiều API ngày nay có các quy tắc xây dựng URL trong tài liệu mà con người có
thể đọc được:
URL tới tài khoản của người dùng trông như thế này:
Về cơ bản đó là Mẫu URI. Nếu bạn cung cấp định dạng trình bày hỗ trợ Mẫu URI, bạn có thể thay thế
tài liệu đó bằng điều khiển siêu phương tiện tương đương.
Đây là một ví dụ ở định dạng Tài liệu gia đình JSON (tôi sẽ trình bày trong Chương 10):
Hầu như tất cả những thứ này đều có thể đọc được bằng máy đối với một máy biết cách phân tích Tài
liệu gia đình JSON. Điều duy nhất phải được giải thích bằng thuật ngữ mà con người có thể đọc được
là tên người dùng mô tả ngữ nghĩa. Điều đó có thể đi vào văn bản nội tuyến hoặc vào một hồ sơ có
thể đọc được bằng máy, chẳng hạn như hồ sơ Alps.io được liên kết ở đây.
Hầu hết các định dạng không chính thức hỗ trợ Mẫu URI nhưng chúng bao gồm một điều khiển siêu phương
tiện thực hiện điều gì đó tương tự—hãy nghĩ đến thẻ <form> của HTML với hành động="GET".
Bạn nhận được hai lợi ích lớn từ việc sử dụng các điều khiển này thay vì các điều khiển tương đương mà con người có thể
đọc được.
Vì hypermedia có thể đọc được bằng máy nên người dùng của bạn có thể sử dụng thư viện chuẩn để
quản lý nó. Điều này giúp loại bỏ khả năng họ hiểu sai hướng dẫn văn xuôi của bạn.
Và vì hypermedia được phân phát trong thời gian chạy nên bạn có nhiều thời gian để thay đổi quyền
kiểm soát này mà không làm ảnh hưởng đến ứng dụng khách của mình—điều mà bạn không thể làm khi
thông tin tương tự được lưu giữ trong tài liệu API của bạn.
Một lần nữa, không có gì sai với những URL đẹp mắt. Các URL đẹp mắt thật tuyệt vời!
Nhưng chúng là mỹ phẩm. Họ trông tuyệt thật. Họ không làm gì cả. Ứng dụng khách API của bạn sẽ
tiếp tục hoạt động ngay cả khi tất cả các URL có giao diện đẹp mắt đột nhiên được thay thế bằng
Tên tiêu chuẩn có lẽ tốt hơn tên của bạn Giả sử ngữ nghĩa ứng
dụng của bạn bao gồm “tên của một người”. Bạn sẽ viết nó ra ở bước 1, bạn sẽ cố
gắng khớp nó vào một hệ thống phân cấp và đặt cho nó một tên tạm thời dựa trên
trường tương ứng trong lược đồ cơ sở dữ liệu hoặc mô hình dữ liệu của bạn. Một
cái gì đó như first_name, firstname, first-name, fn, first name, first, fname,
hoặc cung cấp en_name. Bước 1 như vậy là ổn. Nhưng khi đến bước 3, bạn cần nhìn
xung quanh, nhận thấy rằng có rất nhiều hồ sơ hiện có để mô tả tên của mọi người
và sử dụng một trong số đó.
Bạn có thể được gắn với những tên bạn đã chọn ở bước 1. Nhưng bạn không tự mình thực hiện API
này. Bạn đang làm điều này cho người dùng của mình.2 Trong sự nghiệp của mình, người dùng sẽ sử
dụng rất nhiều API khác nhau và họ sẽ được hưởng lợi từ việc không phải học 20 tên hơi khác nhau
cho cùng một thứ. Trước mắt, người dùng của bạn sẽ được hưởng lợi từ việc không phải tìm hiểu về
chi tiết triển khai nội bộ của bạn. Bạn cũng được hưởng lợi: bằng cách áp dụng tên tiêu chuẩn cho
các phần ngữ nghĩa ứng dụng phổ biến, bạn có thể thay đổi tên nội bộ mà không cần thay đổi API.
Nhưng nên chọn hồ sơ nào? Tiêu chuẩn hCard nói rằng bộ mô tả ngữ nghĩa cho tên riêng của một
người là tên riêng. Tiêu chuẩn xCard cho biết nó đã được cung cấp. Tiêu chuẩn FOAF cho biết đó là
GivenName, nhưng FirstName đó có thể được sử dụng khi diễn giải dữ liệu cũ. Mục Schema.org Person
chỉ cho phép GivenName. Đây là những tiêu chuẩn được xác định rõ ràng, được tôn trọng và xung đột
với nhau.
Điều đó thật khó chịu nhưng chẳng có lý do gì để bịa ra thêm nhiều cái tên và khiến tình hình trở
nên tồi tệ hơn. Chỉ cần chọn một cấu hình—bất kỳ cấu hình nào phù hợp nhất với ngữ nghĩa ứng dụng
API của bạn—và sử dụng các tên mà nó xác định.
Những người chịu trách nhiệm về các tiêu chuẩn này đã thực hiện các bước để tránh những cạm bẫy
về mặt khái niệm mà có thể bạn chưa từng cân nhắc. Ví dụ: “tên” không phải là một thuật ngữ chính
xác. Đó là một hiện vật của văn hóa phương Tây, trong đó chúng ta đặt tên của một người lên hàng
đầu. Ở một số nền văn hóa khác, tên gia đình đứng đầu. Chủ tịch hiện tại của Trung Quốc được nêu tên
2. Nếu bạn đang tự làm API này thì hãy làm bất cứ điều gì bạn muốn.
Tập Cận Bình. “Họ” của anh ấy là Tập Cận Bình. Đó là lý do tại sao tên được mô tả có ngữ nghĩa tốt
3
hơn tên.
Nếu bạn là người nói tiếng Anh bản xứ, có thể bạn đã không cân nhắc điều này. Và nếu lược đồ cơ sở
dữ liệu nội bộ của bạn có một trường tên là firstname thì điều đó không quan trọng lắm. Nhưng khi
bạn bắt đầu gửi dữ liệu của mình ra thế giới, việc bạn mô tả dữ liệu đó như thế nào sẽ rất quan trọng.
Các nhà thiết kế hCard, xCard, FOAF và Person của lược đồ.org đã cân nhắc điều này. Xem xét các vấn
đề phức tạp trong việc đặt tên là một phần công việc của họ. Đó là lý do tại sao tất cả các tiêu
chuẩn đó đều sử dụng cụm từ “tên riêng” làm cơ sở cho bộ mô tả ngữ nghĩa của chúng. Đó là lý do tại
sao FOAF nói rằng FirstName chỉ nên được sử dụng để diễn giải dữ liệu cũ. Nếu bạn quan tâm đến độ
nhạy cảm về văn hóa và/hoặc độ chính xác, bạn nên làm theo hướng dẫn của các hồ sơ hiện có. Bằng cách
áp dụng chúng bất cứ khi nào có thể, bạn sẽ hạn chế được tần suất phải thực hiện công việc đặt tên phức tạp.
điểm của loại phương tiện mới là khả năng kiểm soát hoàn toàn mà nó mang lại cho bạn về cách khách
hàng xử lý tài liệu của bạn. Bạn không cần phải dựa trên API của mình dựa trên XML, JSON hoặc HTML.
Bạn có thể khai báo một định dạng tệp nhị phân hoàn toàn mới và đưa ra hướng dẫn từng byte về cách
xử lý nó. Bạn không cần phải tìm kiếm các hồ sơ phản ánh ngữ nghĩa ứng dụng của mình. Dù bạn nói gì,
đi.
Nhiều tổ chức có định dạng tệp dựa trên XML hoặc JSON được thiết kế để sử dụng nội bộ và chưa bao
giờ được chỉ định chính thức. Sẽ không mất nhiều công sức để biến các định dạng đó thành các loại
siêu phương tiện dành riêng cho miền mà người ngoài có thể sử dụng được.4 Công việc là công việc viết
đặc tả chính thức đó. Loại phương tiện phải đi kèm với hướng dẫn xử lý đầy đủ, rõ ràng.
Nếu bạn thấy mình phải xác định 5 hoặc 10 loại phương tiện cho một API thì đó là một dấu hiệu xấu.
Thay vào đó, bạn nên sử dụng loại siêu phương tiện chung hoặc bạn nên xác định một loại phương tiện
mới, cùng với một số quy tắc để áp dụng tài liệu ALPS (hoặc định dạng hồ sơ khác) cho loại phương
tiện đó. 5 hoặc 10 bit ngữ nghĩa khác nhau đó có thể tạo thành 5 hoặc 10 cấu hình.
Mọi loại phương tiện mới đều cần có tên và RFC 6838 giải thích cách đặt tên cho chúng. Có thể bạn sẽ
có một cái tên như application/vnd.yourcompany.type-name. Loại phương tiện dựa trên JSON hoặc XML
3. Tên riêng từng được gọi là “tên Kitô giáo”: tên được đặt như một phần của nghi lễ rửa tội cho trẻ sơ sinh.
Thuật ngữ đó là một tạo tác của văn hóa Công giáo châu Âu. Không phải tất cả mọi người trên thế giới đều trải qua buổi lễ đó (tôi chưa bao
giờ làm vậy), vì vậy chúng tôi chuyển sang một thuật ngữ tổng quát hơn. Sau đó chúng tôi lại đổi chỗ.
4. Nhưng cũng sẽ không mất nhiều công sức để chuyển đổi định dạng JSON đó sang Hydra, một định dạng mà tôi sẽ trình bày trong Chương 12.
Nếu bạn mong muốn những người bên ngoài tổ chức của mình chuyển các tài liệu sử dụng loại phương
tiện của bạn thì bạn cũng cần cho cả thế giới biết cách xử lý các tài liệu đó.
Điều này có nghĩa là đăng ký loại phương tiện của bạn với IANA.
Đăng ký là một thủ tục khá chính thức, được mô tả trong phần 4 và 5 của RFC 6838.
Về cơ bản, bạn đang thông báo cho IANA (và tất cả những người sử dụng loại phương tiện của bạn sau
đó) nơi tìm mô tả về loại phương tiện và liệu nó có tạo ra bất kỳ mối lo ngại bảo mật đặc biệt nào
hay không. Bạn có thể đăng ký loại phương tiện bằng cách điền vào biểu mẫu.
Dưới đây là những điều chính cần xem xét khi điền vào biểu mẫu đó:
• Bạn phải có “thông số kỹ thuật công khai vĩnh viễn và sẵn có về định dạng dành cho loại phương
tiện truyền thông”. Nó cần bố trí định dạng đủ chi tiết để ai đó có thể viết trình phân tích
cú pháp cho định dạng dữ liệu của bạn, chỉ sử dụng thông tin trong phần cụ thể.
cation.
Bạn có thể đang lên kế hoạch tạo định nghĩa loại phương tiện “có sẵn” như một phần tài liệu
API của mình. Nhưng IANA muốn mức độ chi tiết có thể hiệu quả hơn bạn mong đợi. Công việc này
là cần thiết vì khi bạn đăng ký một loại phương tiện, những người chưa bao giờ nghe nói đến
bạn, những người không có kết nối với API của bạn, sẽ truy cập trang web của bạn và đọc thông
số kỹ thuật của bạn để họ có thể tạo tài liệu của riêng họ ở định dạng bạn đã xác định. • Bạn
sẽ cần đề cập đến bất kỳ mối lo ngại nào về bảo mật liên quan đến việc
xử lý tài liệu trong loại phương tiện của bạn. Điều này đặc biệt quan trọng nếu tài liệu của bạn
RFC 6838 có danh sách kiểm tra cơ bản về những điều cần xem xét ở đây. Nếu loại phương tiện
của bạn dựa trên JSON, bạn cũng nên tham khảo phần 6 của RFC 4627, trong đó mô tả các mối lo
Nếu loại phương tiện của bạn dựa trên XML, bạn sẽ cần phải thực hiện một số tác vụ đặc biệt, được
mô tả trong phần 7.1 của RFC 3023. Các tác vụ này chủ yếu liên quan đến việc thêm bản soạn
sẵn dành riêng cho XML vào nội dung gửi của
bạn. • Nếu loại phương tiện của bạn không dựa trên XML, bạn sẽ cần chỉ định cách dữ liệu có thể
xuất hiện qua mạng. Câu trả lời thường sẽ là “nhị phân”. Đối với các loại phương tiện dựa trên
JSON, bạn có thể tham khảo tiêu chuẩn JSON, RFC 4627 hoặc chỉ nói “nhị phân”. Nếu loại phương
tiện của bạn dựa trên XML thì bản soạn sẵn từ RFC 3023 sẽ đảm nhiệm phần này.
• Có lẽ bạn nên xác định tham số cấu hình cho loại phương tiện của mình để khách hàng có thể yêu
cầu một cấu hình cụ thể bằng cách sử dụng tiêu đề Kiểu nội dung . (Tôi đã thảo luận thủ thuật
này trong Chương 8.) Đây là ý kiến của tôi, không phải một phần của RFC 6838. Bạn chỉ có thể
nói rằng loại phương tiện của bạn nhận tham số hồ sơ và giá trị của nó là URI của hồ sơ, theo
RFC 6906.
Nếu bạn muốn nhận lời khuyên từ cộng đồng trước khi gửi bài, hãy gửi những gì bạn nhận được dưới dạng email tới
media-types@iana.org. Nếu bạn muốn xem một ví dụ đơn giản, hãy xem đăng ký đã được phê duyệt cho loại phương tiện
Mê cung+XML.
Bạn không cần phải đăng ký loại của mình với IANA nếu bạn không muốn. Nếu bạn quyết định không đăng ký, bạn sẽ
cần sử dụng vnd. tiền tố (đối với một dự án thương mại—dù sao thì đây cũng có thể là tiền tố mà bạn có thể đang
sử dụng) hoặc prs . tiền tố (đối với một dự án cá nhân hoặc công việc thử nghiệm). Nhưng nếu loại phương tiện của
bạn nói chung trở nên phổ biến, bạn thực sự nên đăng ký nó. Hàng trăm loại phương tiện dành riêng cho nhà cung
những chủ đề được tranh luận sôi nổi nhất hiện nay trong cộng đồng API là lập phiên bản. Đó là một vấn đề lớn.
Hầu hết các công ty đưa ra API không bao giờ thay đổi API đó sau lần phát hành đầu tiên. Họ không thể làm điều đó.
Nói thẳng ra, họ không thể làm điều đó vì họ đã bỏ qua ràng buộc về hypermedia. Hầu hết các API đưa giao thức và
ngữ nghĩa ứng dụng của chúng vào tài liệu mà con người có thể đọc được. Sau đó, người dùng các API đó sẽ viết một
loạt phần mềm máy khách dựa trên tài liệu đó.
Bây giờ các nhà cung cấp API đang bị kẹt. Họ có thể thay đổi tài liệu nhưng làm như vậy sẽ không tự động thay đổi
hành vi của tất cả khách hàng đó. Họ đã trao cho người dùng quyền phủ quyết đối với bất kỳ thay đổi nào trong
Tuy nhiên, việc thay đổi tài liệu hypermedia sẽ thay đổi hành vi của mọi khách hàng nhận được nó. Đó là lý do tại
sao một trang web có thể được thiết kế lại toàn bộ mà không làm hỏng trình duyệt web của mọi người. Một trang web
hoàn toàn được chứa trong các đại diện mà nó phục vụ. Không có gì ẩn thêm trong tài liệu mà con người có thể đọc
được.
Đây là thời điểm mà rất nhiều đề xuất tôi đưa ra trong cuốn sách này – những đề xuất ban đầu có vẻ mô phạm và soi
mói – thực sự bắt đầu có hiệu quả. Một trong những mục tiêu chính của tôi là giảm số lượng tài liệu mà con người
có thể đọc được đi kèm với API của bạn. Điều đó không chỉ vì tài liệu mà con người có thể đọc được dễ bị hiểu
sai. Đó là bởi vì việc thay đổi một phần tài liệu mà con người có thể đọc được đòi hỏi phải có sự thay đổi tương
Việc chuyển ngữ nghĩa API của bạn ra khỏi tài liệu mà con người có thể đọc được và vào các tài liệu siêu phương
tiện giúp API của bạn trở nên linh hoạt hơn khi đối mặt với sự thay đổi. Chọn một định dạng hypermedia tốt và bạn
có thể thêm tài nguyên mới cũng như chuyển đổi trạng thái vào API của mình mà không ảnh hưởng đến các máy khách
hiện tại. Bạn cũng sẽ có khá nhiều chỗ để thay đổi ngữ nghĩa giao thức của mình.
Lý tưởng nhất là việc thiết kế lại một API cũng dễ dàng như việc thiết kế lại một trang web. Có lẽ chúng ta sẽ
không bao giờ đạt được điều đó, vì lý do tương tự, chúng ta sẽ không bao giờ thu hẹp được hoàn toàn khoảng cách
ngữ nghĩa. Nếu bạn thêm một trường bắt buộc mới vào quá trình chuyển đổi trạng thái, bạn có thể thêm một bộ mô
tả ngữ nghĩa mới vào hồ sơ máy có thể đọc được của mình, nhưng vẫn cần phải có phần giải thích về bộ mô tả ngữ nghĩa đó.
để được giải thích bởi một con người. Một máy khách hoàn toàn tự động có thể hiểu được thông báo lỗi mà nó
đột nhiên bắt đầu nhận được—“Bạn không cung cấp giá trị cho re quired_field.”—nhưng nó sẽ không biết nên
Ngoài ra còn có những thay đổi mà ứng dụng khách lý tưởng sẽ thích ứng, nhưng điều đó có thể làm hỏng ứng
dụng khách thực, chẳng hạn như thay đổi điều khiển siêu phương tiện để sử dụng PUT thay vì POST. Nhưng nhìn
chung, bạn sẽ thành công hơn khi thay đổi một chút ngữ nghĩa nếu nó được mô tả ở dạng máy có thể đọc được
điều kiện.
Nếu bạn thay đổi một tài nguyên và khách hàng của bạn không thể tự động thích ứng với thay đổi đó, bạn sẽ
cần dành một khoảng thời gian để xuất bản một cách hiệu quả hai tài nguyên khác nhau—một tài nguyên cũ và
một tài nguyên mới—với ngữ nghĩa giao thức hoặc ứng dụng khác nhau. Có ba chiến lược phổ biến để làm điều
này.
kỹ thuật lập phiên bản phổ biến nhất, toàn bộ API được chia thành hai API riêng biệt.
Đôi khi hai API có các URL biển quảng cáo khác nhau, như http://api-v1.example. com/ và http://api-
v2.example.com/.
Đôi khi chỉ có một URL biển quảng cáo, nhưng việc trình bày biển quảng cáo sử dụng siêu phương tiện để cung
cấp cho khách hàng sự lựa chọn giữa các phiên bản:
<ul>
<li><a class="v1" href="/v1/">Phiên bản 1</a></li>
<li><a class="v2" href="/v2/">Phiên bản 2</ a></li>
</ul>
Ở đây, số phiên bản là một bộ mô tả ngữ nghĩa. Khách hàng không biết v2 nghĩa là gì sẽ không theo liên kết.
Việc phân vùng có hiệu quả vì các biểu diễn được tìm thấy bên dưới /v1 chỉ liên kết đến các tài nguyên được
tìm thấy bên dưới /v1. Cả hai phiên bản API có thể sử dụng cùng một mã cơ bản, nhưng chúng có thể có ngữ
nghĩa ứng dụng hoàn toàn khác nhau, bởi vì bất kỳ khách hàng cụ thể nào cũng sẽ chỉ sử dụng cái này hoặc
cái kia.
tiện Nếu bạn đã xác định loại phương tiện dành riêng cho miền cho ứng dụng của mình, bạn có thể cung cấp
cho nó một tham số phiên bản . Sau đó, khách hàng có thể sử dụng đàm phán nội dung (xem Chương 10) để yêu
cầu phiên bản này hay phiên bản khác:
Tôi không nghĩ bạn nên xác định loại phương tiện dành riêng cho tên miền ngay từ đầu, nhưng ngay cả khi bạn
làm vậy thì đây vẫn là một ý tưởng tồi. Loại phương tiện của bạn không phải là API của bạn. Đây là một thử
nghiệm suy nghĩ: liệu một công ty khác có thể sử dụng loại phương tiện của bạn trong API không liên quan
của riêng họ không? Họ có nhận được lợi ích nào từ việc đó không, ngoài khả năng tương thích với tiêu chuẩn
tiền pháp định của bạn? Nếu không có lý do thuyết phục nào để người khác chấp nhận loại phương tiện của bạn
thì tức là bạn đã đặt quá nhiều API vào định nghĩa loại phương tiện của mình.
Loại phương tiện của bạn có xác định mọi khía cạnh của giao thức API và ngữ nghĩa ứng dụng như
cách Maze+XML thực hiện không? Nếu vậy thì việc thêm tham số phiên bản sẽ có tác dụng. Theo định
nghĩa, sự thay đổi về ngữ nghĩa có nghĩa là sự thay đổi về loại phương tiện. Nhưng nếu bạn giữ
một hồ sơ hoặc bất kỳ tài liệu nào mà con người có thể đọc được ngoài định nghĩa loại phương tiện,
thì có thể bạn sẽ thay đổi API mà không thay đổi định nghĩa loại phương tiện.
Sau đó, bạn sẽ gặp vấn đề: thuộc tính phiên bản thực sự áp dụng cho cái gì? Đây là loại phương
Các loại phương tiện được tiêu chuẩn hóa không làm điều này. HTML 5 rất khác với HTML 4, nhưng cả
hai đều được dùng dưới dạng văn bản/html và HTML 5 gần như tương thích ngược với HTML 4.5
Tôi khuyên bạn nên căn cứ API của mình xung quanh loại phương tiện được tiêu chuẩn hóa và rõ ràng
là bạn không thể truy cập và khai báo phiên bản mới của loại phương tiện của người khác. Nhưng tôi
cũng khuyên bạn nên xác định ngữ nghĩa ứng dụng của mình trong một cấu hình mà máy có thể đọc được
và bạn có thể khai báo một phiên bản mới của cấu hình.
Hồ sơ của bạn tách biệt rõ ràng các phần của ứng dụng sẽ làm hỏng ứng dụng khách khi chúng thay
đổi (vì chúng được mô tả bằng văn bản mà con người có thể đọc được) khỏi các phần mà máy khách có
thể thích ứng (vì chúng được mô tả bằng hypermedia). Việc giữ hai cấu hình cho phép bạn giữ hai
bộ ngữ nghĩa ứng dụng. Khách hàng có thể sử dụng tiêu đề Liên kết để yêu cầu hồ sơ này hoặc hồ sơ
khác. Hoặc, nếu loại phương tiện hỗ trợ tham số hồ sơ , khách hàng có thể sử dụng tiêu đề Kiểu nội
là phiên bản API đặc biệt nhận được nhiều sự chú ý vì vấn đề còn tồi tệ hơn nhiều đối với một API
bỏ qua ràng buộc hypermedia. Nhưng đó chỉ là một ví dụ về vấn đề chung được giải quyết bởi
hypermedia. Làm thế nào để khách hàng biết tài nguyên nào có đại diện mà họ muốn? Sau khi khách
hàng nhận được thông tin đại diện, làm thế nào để biết được thông tin đại diện đó có ý nghĩa gì?
Các kỹ thuật tôi đưa ra trước đó là các kỹ thuật mà máy chủ sử dụng nói chung khi cho khách hàng
Một máy chủ có thể đưa ra các liên kết đến hai URL khác nhau và máy khách có thể chọn liên kết nào
để theo dõi dựa trên sự hiểu biết về ngữ nghĩa của ứng dụng. Điều này giống nhau cho dù hai URL
trỏ đến các tài nguyên hoàn toàn khác nhau hay tới phiên bản v1 và v2 của một tài nguyên cơ bản.
Một tài nguyên có thể có các đại diện trong các loại phương tiện khác nhau. Máy khách có thể chọn
cách thể hiện mà nó muốn bằng cách sử dụng đàm phán nội dung (với tiêu đề Chấp nhận ;
5. Phiên bản 3.0 của HTML, vào năm 1995, thực sự đã làm được những gì API đang làm hiện nay. Nó giới thiệu một tham số phiên
bản và gợi ý rằng các tài liệu HTML nên được phân phát dưới dạng text/html;version=3.0. Điều này đã bị loại bỏ trong HTML
xem Chương 11) hoặc hypermedia. Điều này giống nhau cho dù các loại phương tiện hoàn toàn khác nhau
(Bộ sưu tập+JSON và HTML) hay chúng chỉ khác nhau ở tham số phiên bản . Tôi nghĩ tham số phiên bản
là một ý tưởng tồi, nhưng nếu bạn sử dụng nó, nó sẽ hoạt động giống như khi bạn sử dụng hai loại
Một tài nguyên có thể được mô tả bằng nhiều cấu hình khác nhau và khách hàng có thể sử dụng đàm
phán nội dung hoặc siêu phương tiện để chọn tài nguyên mà nó muốn. Điều này giống nhau cho dù các
cấu hình là những cách tiếp cận khác nhau cho cùng một ý tưởng (hCard so với Person của lược đồ.org)
hay chúng là các cấu hình “v1” và “v2” của một API duy nhất.
thì việc lập phiên bản không phải là một vấn đề kỹ thuật. Đó là một khía cạnh trong mối quan hệ của
bạn với người dùng. Bạn không muốn một thay đổi nhỏ làm hỏng phần mềm máy khách của mọi người, vì
vậy, bạn mô tả càng nhiều thay đổi càng tốt bằng cách sử dụng siêu phương tiện có thể đọc được bằng
máy thay vì tài liệu mà con người có thể đọc được. Khi bạn phải thay đổi ngữ nghĩa của tài nguyên
theo cách phá vỡ tính tương thích ngược, bạn sẽ tạo phiên bản thứ hai của tài nguyên đó để khách
hàng mới sử dụng. Phiên bản thứ hai có thể được xác định bằng một URL khác, loại phương tiện khác
hoặc bất kỳ thứ gì. Khách hàng chưa sửa đổi vẫn có thể sử dụng phiên bản cũ.
Cuối cùng, bạn muốn thoát khỏi phiên bản cũ. Suy cho cùng, nếu bạn thích chức năng cũ thì bạn đã
không thay đổi nó. Một lần nữa, không có giải pháp kỹ thuật ở đây. Vấn đề là mối quan hệ của bạn
với người dùng của bạn. Bạn cần đặt ra kỳ vọng về thời điểm một phiên bản API của bạn sẽ không được
dùng nữa và khách hàng có thể mong đợi tiếp tục sử dụng API không được dùng trong bao lâu.
Khi bạn xuất bản API của mình, hãy đưa ra một số mức độ đảm bảo về thời gian hiệu lực của API. Bạn
có thể đưa ra lời đảm bảo trọn đời (“Chúng tôi sẽ tiếp tục hỗ trợ API này trong 5 năm.”) hoặc bạn
có thể đưa ra lời đảm bảo về thông báo (“Chúng tôi sẽ đưa ra cảnh báo một năm cho bạn trước khi
chúng tôi ngừng hỗ trợ API này.”) Đồng thời thiết lập một kênh liên lạc cụ thể để liên lạc về vấn
Khi bạn muốn thực hiện một thay đổi đối với API làm hỏng khả năng tương thích ngược, đây là một quy
1. Khai báo phiên bản hiện tại “không được dùng nữa”. Nó vẫn sẽ hoạt động, nhưng nó không còn là
phiên bản hiện tại nữa. Thông báo điều này trên kênh liên lạc mà bạn thiết lập cho mục đích
này. Cập nhật tài liệu và hướng dẫn của bạn để các nhà phát triển mới bắt đầu sử dụng phiên
bản hiện tại chứ không phải phiên bản không được dùng nữa.
2. Sau một thời gian, hãy sử dụng kênh liên lạc để thông báo rằng bạn sẽ không sửa lỗi trên API
“không được dùng nữa” và nhắc nhở người dùng về phiên bản mới.
3. Sau một khoảng thời gian không sửa lỗi, hãy thông báo thời hạn sau đó "không được dùng nữa"
API sẽ bị tắt.
4. Có thể bạn sẽ cần thời gian gia hạn sau thời hạn, nhưng tại một thời điểm nào đó sau thời hạn,
hãy tắt API cũ. Yêu cầu sẽ dẫn đến mã trạng thái HTTP 410
(Đã qua), cùng với nội dung thực thể HTML giải thích đây là API đã chết và liên kết đến phiên
bản hiện tại.
Tốc độ bạn có thể thực hiện các bước này tùy thuộc vào quy mô cơ sở người dùng của bạn và tốc độ
trung bình mà cộng đồng của bạn có thể thay đổi. Việc thay đổi API ngân hàng sẽ mất nhiều thời
Nghe có vẻ không vui lắm phải không? Vâng, thật kinh khủng! Nhưng đây là cách bạn triển khai phần
mềm máy chủ mới mà không làm hỏng tất cả các máy khách đã triển khai mà bạn không có quyền kiểm soát.
Đó là lý do tại sao hypermedia lại quan trọng đến vậy. Bạn càng đưa được nhiều giao thức và ngữ
nghĩa ứng dụng vào dạng máy có thể đọc được thì bạn càng có nhiều khả năng thay đổi API của mình
mà không phải trải qua quá trình chậm chạp, rườm rà này.
Đừng giữ tất cả Hypermedia ở một nơi Một trong những tính
năng xác định của các API kiểu cũ, không phải RESTful là tài liệu mô tả dịch vụ. Đây là một tài
liệu lớn (thường ở định dạng WSDL) cung cấp mô tả đầy đủ về ngữ nghĩa ứng dụng và giao thức của
API. Tệp thường được tạo bởi một công cụ nút nhấn hiểu API dựa trên ý nghĩa phía máy chủ của nó.
tâm lý.
Người dùng có thể tải xuống tài liệu mô tả dịch vụ và sử dụng nó để tự động tạo ra bản triển khai
ứng dụng khách tương ứng. Họ có thể sử dụng ứng dụng khách để thực hiện các lệnh gọi API từ xa như
thể chúng là các lệnh gọi bằng ngôn ngữ lập trình cục bộ. Không cần phải hiểu gì về hypermedia, các
định dạng biểu diễn hoặc HTTP. Và sau đó sẽ có điều gì đó thay đổi trong quá trình triển khai phía
Vấn đề với thiết kế này là nó tạo ra sự kết hợp chặt chẽ giữa việc triển khai API phía máy chủ, mô
tả mà máy có thể đọc được và ứng dụng khách được tạo từ mô tả mà máy có thể đọc được đó. Khi việc
triển khai phía máy chủ thay đổi, thay đổi đó sẽ không được phản ánh trong ứng dụng khách được tạo
Bây giờ, có thể bạn chưa nghĩ đến việc tạo mô tả WSDL cho API của mình.
Nhưng tài liệu API truyền thống thực sự là tài liệu mô tả dịch vụ mà con người có thể đọc được. Đó
là một tệp lớn giải thích ngữ nghĩa giao thức và ứng dụng của API.
Tài liệu mà con người có thể đọc được dễ hiểu hơn tệp WSDL, nhưng nó có cùng một vấn đề. Một thay
đổi đối với việc triển khai phía máy chủ sẽ dẫn đến thay đổi đối với “tài liệu dịch vụ”, nhưng thay
đổi đó không được truyền đến các máy khách đã triển khai. Các khách hàng phá vỡ.
API dựa trên hypermedia có khả năng hạn chế trong việc thể hiện các thay đổi phía máy chủ mà không
làm hỏng máy khách. Nhưng bạn không tự động có được khả năng này; bạn phải làm việc cho nó. Hoàn
toàn có thể viết một “tài liệu mô tả dịch vụ” mà máy có thể đọc được bằng HTML.
Trên Web, chúng tôi gọi đó là sơ đồ trang web. Sơ đồ trang web là bản mô tả đầy đủ về trang web
ngữ nghĩa giao thức, tất cả trong một tài liệu. Bạn có thể tự động tạo ứng dụng khách API dựa
trên sơ đồ trang web HTML. Và khi việc triển khai phía máy chủ thay đổi, ứng dụng khách của bạn
Máy khách sử dụng API hypermedia không thể mong đợi biết trước về tất cả các chuyển đổi trạng
thái có thể xảy ra. Nó cần được thiết kế giống như một công cụ giải mê cung, có khả năng đưa ra
quyết định dựa trên các bước tiếp theo có thể được máy chủ trình bày trong thời gian chạy. Đó là
lý do tại sao tôi khuyên bạn nên chia nhỏ các điều khiển hypermedia của mình để mỗi biểu diễn,
khi được phục vụ, đều chứa các điều khiển có liên quan đến ứng dụng hiện tại và trạng thái tài
nguyên. Điều này sẽ buộc các nhà phát triển ứng dụng khách phải tính đến hypermedia, thay vì giả
Tôi đưa ra vấn đề này vì có các công cụ nút bấm sẽ kiểm tra việc triển khai máy chủ của bạn và
tạo API cho bạn, một API được mô tả bằng tài liệu dịch vụ dựa trên hypermedia. Không có gì sai về
mặt kỹ thuật với điều này—hypermedia trong tài liệu dịch vụ vẫn là hypermedia—nhưng nó sẽ khuyến
khích người dùng của bạn đặt niềm tin vào ý tưởng rằng tài liệu dịch vụ sẽ không thay đổi. Ban
đầu mọi thứ có vẻ ổn, nhưng khi API của bạn phát triển, bạn sẽ bắt đầu gặp vấn đề. Bạn sẽ đánh
dấu vào hộp tính năng có nhãn “hypermedia”, nhưng bạn sẽ không thực sự nhận được những lợi ích từ
Bất kỳ định dạng hypermedia nào cũng có thể được sử dụng để viết một tài liệu dịch vụ, nhưng có
ba định dạng đặc biệt phù hợp với mô hình phản mẫu này. Chúng là OData và WADL (tôi sẽ đề cập đến
trong Chương 10) và Hydra (tôi sẽ đề cập đến trong Chương 12). Khi trình bày chúng, tôi sẽ nhắc
một tiêu chuẩn fiat phục vụ các biểu diễn JSON hoặc XML đặc biệt, không có siêu phương tiện:
Bạn sẽ có thể nâng cấp API của mình lên mức chất lượng mà tôi đề xuất trong cuốn sách này mà không
làm ảnh hưởng đến các khách hàng hiện tại của bạn. Đây là phiên bản sửa đổi của quy trình bảy
bước mà tôi đã trình bày trước đó để sửa chữa API dựa trên JSON:
1. Ghi lại tất cả các tuyên bố hiện có của bạn. Mỗi cái sẽ chứa một số mô tả ngữ nghĩa. Bạn
không thể thay đổi những điều này, nhưng bạn có thể thêm mới
những cái đó.
2. Vẽ sơ đồ trạng thái cho API của bạn. Các hộp trên sơ đồ là sự thể hiện hiện có của bạn. Bạn có thể sẽ không
có bất kỳ chuyển đổi trạng thái nào vì hầu hết các API hiện có đều không có bất kỳ liên kết hypermedia nào.
Bây giờ là lúc để thêm một số. Sử dụng các mũi tên để kết nối các cách trình bày theo cách có ý nghĩa. Tên
của các mũi tên là mối quan hệ liên kết của bạn.
Tại thời điểm này, có thể một số bộ mô tả ngữ nghĩa của bạn thực sự là các mối quan hệ liên kết:
Bạn có thể chuyển đổi chúng thành quan hệ liên kết tại thời điểm này, nhưng hãy đảm bảo không đổi tên chúng
3. Bạn không thể thay đổi tên của bất kỳ thứ gì bạn đã viết ở bước 1 vì điều đó sẽ ảnh hưởng đến khách hàng hiện
tại của bạn. Tuy nhiên, bạn có thể xem qua các mối quan hệ liên kết mà bạn đã tạo ở bước 2 và đảm bảo tên của
chúng đến từ IANA và các nguồn nổi tiếng khác bất cứ khi nào có thể.
4. Bạn không thể thay đổi loại phương tiện của mình vì điều đó sẽ làm hỏng ứng dụng khách của bạn. Nó sẽ có
5. Vì bạn không thể thay đổi loại phương tiện nên tất cả ngữ nghĩa ứng dụng và ngữ nghĩa giao thức của bạn phải
được xác định ở một nơi khác. Bạn có hai lựa chọn: cấu hình ALPS hoặc bối cảnh JSON-LD.
Nếu bạn đã viết ra bất kỳ mối quan hệ liên kết không an toàn nào ở bước 2, lựa chọn tốt nhất của bạn là JSON-
LD với Hydra (xem Chương 12). Bạn sẽ có thể lấy các mô tả mà con người có thể đọc được về lệnh gọi API và
chuyển đổi chúng thành các hoạt động Hydra có thể đọc được bằng máy.
6. Bạn đã viết gần hết mã rồi. Bạn chỉ cần mở rộng từng cách trình bày bằng cách cung cấp các liên kết thích hợp.
7. URL biển quảng cáo của bạn sẽ giống như trước đây. Nếu trước đây bạn chưa có tài nguyên này vì API của bạn là
một nhóm các lệnh gọi API riêng biệt, bạn có thể tạo một tài nguyên mới để hoạt động như trang chủ của mình
và biết rằng chỉ những khách hàng nhận biết được siêu phương tiện mới có thể truy cập vào tài nguyên đó.
đối với API phục vụ các biểu diễn XML. Bạn có thể sử dụng XLink và XForm (xem Chương 12) để thêm các điều khiển
Ở bước 2, khi bạn phát hiện ra rằng một trong những bộ mô tả ngữ nghĩa của bạn sẽ có ý nghĩa hơn dưới dạng mối
<homepage>http://example.com/</homepage>
…bạn không thể chuyển đổi nó thành quan hệ liên kết. Điều đó sẽ phá vỡ khách hàng hiện tại của bạn.
Bạn sẽ cần phải thêm dự phòng. Ví dụ này sử dụng XLink để sử dụng trang chủ vừa là mối quan hệ
Bạn cũng có thể gặp một số rắc rối ở bước 5. Bạn không thể sử dụng JSON-LD trên tài liệu XML nhưng
bạn có thể viết cấu hình ALPS. Nếu vẫn thất bại, bạn có thể quay lại hồ sơ mà con người có thể đọc
Nó có đáng không?
Mặc dù về mặt kỹ thuật có thể biến một API thiếu hiểu biết về siêu phương tiện thành một API siêu
đa phương tiện đầy đủ, nhưng lợi ích duy nhất bạn thu được từ việc thực hiện này có thể là cảm
giác hài lòng rực rỡ. Vấn đề là API cũ của bạn đã có ứng dụng khách. Đó là lý do tại sao bạn không
thể loại bỏ nó và thiết kế một API mới từ đầu. Bởi vì các máy khách hiện tại không có được sự linh
hoạt nhờ kiến thức về hypermedia nên sẽ rất khó khăn để di chuyển chúng sang API mới. Và tại sao
người dùng của bạn lại phải bận tâm tìm hiểu API mới?
Nếu bạn vẫn dự định thay đổi API của mình thì việc trang bị thêm các cấu hình và điều khiển
hypermedia cho API đó là điều hợp lý để những thay đổi trong tương lai sẽ dễ dàng hơn. Nhưng việc
thêm siêu phương tiện vào API hiện có sẽ không giải quyết được bất kỳ vấn đề nào.
Trong Chương 1, tôi đã nói về một trang web sử dụng biển quảng cáo để quảng cáo URL tới trang chủ
của nó. Tôi kể câu chuyện về Alice, một nhân vật hư cấu đã gõ URL đó vào trình duyệt web của mình
Câu chuyện khá buồn tẻ vì nó chỉ cho thấy World Wide Web hoạt động theo cách nó phải làm. Nhưng
bây giờ tôi có thể kể câu chuyện tương tự về một API không có gì chung với Web ngoại trừ giao thức
HTTP.
Giống như câu chuyện trước đây của tôi, câu chuyện này bắt đầu bằng một URL—URL biển quảng cáo cho một API:
https://www.example.com/
(Như bạn có thể thấy từ tên máy chủ, không giống như trang web ở Chương 1 và API ở Chương 2, API
Ai đó đang lái xe cho khách hàng này. Đó là Alice, nhân vật hư cấu ở Chương 1. Nhưng lần này cô ấy không sử
dụng trình duyệt web. Cô ấy đang sử dụng máy khách HTTP có thể lập trình để thăm dò khả năng của API mới.
Không có trình duyệt web để hiển thị các biểu diễn bằng đồ họa, Alice có thể gặp khó khăn trong việc hiểu
Máy chủ gửi lại một bản trình bày và Alice kiểm tra nó:
200 OK HTTP/1.1
Loại nội dung: application/vnd.myapi.qbit
===1 wkmje
<{data} {name:"qbe"} 1005>
<{link} {tab:"profile"} "https://www.example.com/The-Metric-System-And-You" >
<{link} {tab:"search"} "https://www.example.com/sosuy{?ebddt}">
===2 qmdk
<{link} {tab:"gyth"} "https:/ /www.example.com/click%20here%20for%20prizes">
<{data} {name:"ebddt"} "Zerde">
<{data} {name:"gioi"} "Snup">
"Cái quái gì đây?" Alice nói. “Nó không hẳn là XML và cũng không hẳn là JSON. Nó chứa đầy những chuỗi vô
nghĩa như qbe và URL dường như dẫn đến những đoạn phim mang tính giáo dục từ những năm 1970.”
Manh mối duy nhất của Alice là tiêu đề Content-Type , xác định định dạng dữ liệu có tên là application/
vnd.myapi.qbit. Không còn nơi nào khác để đi, Alice tra cứu application/vnd.myapi.qbit trong sổ đăng ký IANA
của các loại phương tiện. Điều này dẫn cô đến một trang web công ty mô tả định dạng dữ liệu không hẳn là
XML, không hẳn là JSON mà cô đang xem. Trang web đó cũng có một số thư viện mã để phân tích định dạng tệp.
Bằng cách sử dụng những công cụ này, cô ấy có thể mở rộng ứng dụng khách HTTP có thể lập trình của mình để
nó có thể biến luồng vô nghĩa thành cấu trúc dữ liệu hữu ích.
Bây giờ Alice đã biết một vài điều. Cô ấy biết rằng tài liệu này có hai phần, một
phần tên là wkmje và một phần tên là qmdk. Cô biết rằng tài liệu chứa ba bộ mô tả
ngữ nghĩa (gioi, ebddt và qbe) và ba điều khiển hypermedia (hai liên kết và Mẫu
URI). Vì một lý do kỳ lạ nào đó, loại phương tiện này đề cập đến mối quan hệ liên
kết dưới dạng “tab”, có nghĩa là ba điều khiển siêu phương tiện có hồ sơ quan hệ
liên kết , tìm kiếm và gyth.
Nhưng Alice không biết wkmje hay qmdk nghĩa là gì. Chúng là những từ vô nghĩa không được xác định cùng với
loại phương tiện. Một trong những điều khiển hypermedia trỏ đến https:// www.example.com/
click%20here%20for%20prizes, nhưng Alice không biết đầu bên kia là gì, vì URL trông giống như thư rác và mối
Alice biết rằng điều khiển tìm kiếm là Mẫu URI xác định một biến có tên là ebddt, nhưng cô ấy
không biết ebddt nghĩa là gì. Tìm kiếm quan hệ liên kết đã được đăng ký với IANA và việc đọc
định nghĩa giúp Alice tin tưởng rằng đây là một dạng tìm kiếm nào đó. Điều này có nghĩa là
ebddt có thể là một thuật ngữ tìm kiếm. Nó có thể liên quan đến bộ mô tả ngữ nghĩa được gọi là
Tập 2: Hồ sơ
Câu trả lời cho tất cả những câu hỏi này nằm ở liên kết đầu tiên của tài liệu:
Đến thời điểm này, Alice đã đọc Chương 8 của cuốn sách này. Cô ấy biết rằng hồ sơ quan hệ liên
kết đã được đăng ký với IANA và nó chỉ ra một liên kết đến một tài liệu hồ sơ.
Cô ấy đưa ra yêu cầu thứ hai, hy vọng có được một tài liệu hồ sơ có thể hiểu được tất cả những
thứ ebddt và gyth này :
Khi Alice đọc định nghĩa của application/vnd.myapi.qbit, cô nhận thấy rằng nó bao gồm các quy
tắc áp dụng hồ sơ ALPS cho một biểu diễn, vì vậy Alice đang hy vọng có một hồ sơ ALPS. Nhưng
ngay cả một trang web mà con người có thể đọc được cũng sẽ hữu ích.
Khi điều đó xảy ra, máy chủ sẽ gửi cho Alice một tài liệu ALPS:
HTTP/1.1 200 OK
Loại nội dung: application/vnd.amundsen.alps+xml
được. </doc>
...
</alps>
Alice kết hợp hồ sơ ALPS với tài liệu vnd.myapi.qbit một cách tinh thần hoặc sử dụng
một công cụ tự động. Bây giờ tất cả có ý nghĩa. API này là cơ sở dữ liệu công thức
nấu ăn. Phần đầu tiên của phần trình bày mô tả toàn bộ cơ sở dữ liệu. Nó bao gồm cách
tìm kiếm theo tên công thức (ebddt) và tổng số công thức nấu ăn (qbe). Phần thứ hai
là liên kết đến một công thức đặc trưng (gyth). Nó đề cập đến tên công thức
(ebddt="Zerde") và thực tế đó là công thức chay (gioi="Snup").
Việc kết hợp tài liệu vnd.myapi.qbit với cấu hình ALPS trong một chương trình hiểu
được cả hai loại phương tiện có thể mang lại một GUI giống như Hình 9-12.
Hình 9-12. Có thể hiển thị GUI qbit bằng Cấu hình ALPS
Điều này không hoàn hảo—các giải thích mà con người có thể đọc được không được viết để sử dụng trong GUI,
vì vậy GUI đọc một cách vụng về—nhưng nó tốt hơn rất nhiều so với tài liệu vnd.myapi.qbit khó hiểu của
chính nó .
Là một lập trình viên, Alice có thể sử dụng hồ sơ ALPS để triển khai bất kỳ loại máy khách nào mà tôi đã
• Một ứng dụng khách do con người điều khiển để tìm kiếm cơ sở dữ liệu
công thức nấu ăn. • Trình thu thập thông tin tải xuống tất cả các
công thức nấu ăn mà nó có thể tìm thấy. • Một công cụ giám sát định kỳ thực hiện tìm
kiếm các công thức nấu ăn chay mới. • Một đại lý lấy danh sách các thành phần có trong tay và lên kế
hoạch cho bữa ăn. Tác nhân sử dụng API công thức để tìm các công thức sử dụng nguyên liệu có sẵn. Nó
cũng tích hợp với API định giá của cửa hàng tạp hóa để tra cứu giá thành của những nguyên liệu còn
thiếu. Đầu ra của nó là danh sách các công thức nấu ăn sử dụng hầu hết các nguyên liệu sẵn có và có
chi phí bổ sung tối thiểu.
Nhưng thực tế, Alice không hề quan tâm đến việc nấu nướng. Sau khi hiểu được ý nghĩa của tài liệu mà cô
ấy được cung cấp ban đầu, cô ấy sẽ ngừng sử dụng API kỳ lạ này và không bao giờ quay lại.
tôi thiết kế API này, tôi đã thực hiện mọi bước có thể để che giấu mục đích của nó. Tôi đã tạo một loại
phương tiện khó hiểu, application/vnd.myapi.qbit. Tôi đã sử dụng tab thuật ngữ vô nghĩa để gắn nhãn các
mối quan hệ liên kết, thay vì thuật ngữ tiêu chuẩn rel. Tôi đã cung cấp các URL có tên dẫn đầu sai. Tôi
đã sử dụng các chuỗi ký tự ngẫu nhiên để đặt tên cho các bộ mô tả ngữ nghĩa và các mối quan hệ liên kết.
Tôi đã phát minh ra những quy tắc tùy tiện, lố bịch để xác định liệu một công thức nấu ăn có đáp ứng các
hạn chế về chế độ ăn uống khác nhau hay không. Văn bản hữu ích duy nhất mà con người có thể đọc được
trong tài liệu vnd.mya pi.qbit là “Zerde”, tên của công thức đặc trưng.6 Và không có tài liệu API như
Bất chấp tất cả những điều này, Alice vẫn có thể tìm ra cách hoạt động của API, bởi vì ngay cả trong cơn
bạo dâm của mình, tôi vẫn tuân theo các quy tắc tôi đã đặt ra trong cuốn sách này. Tôi đã cung cấp tiêu
đề Kiểu nội dung chứa loại phương tiện có định dạng trình bày khó hiểu. Alice đã có thể tra cứu nó trong
sổ đăng ký IANA và đọc phần giải thích chính thức về định dạng. Trong tài liệu vnd.myapi.qbit , tôi đã sử
dụng mối quan hệ liên kết (tìm kiếm) đã đăng ký IANA để mô tả một biểu mẫu tìm kiếm và một (hồ sơ) khác
để liên kết đến một tài liệu hồ sơ. Tài liệu hồ sơ có thể đọc được bằng máy nhưng nó cũng chứa các thông
tin cần thiết mà con người có thể đọc được.
6. Zerde là món tráng miệng của Thổ Nhĩ Kỳ, một loại bánh gạo. Tôi chọn nó vì nghĩ rằng không có nhiều độc giả của tôi sẽ
nhận ra từ đó.
câu hỏi về ý nghĩa của sự đại diện . Sau khi tìm thấy và đọc thông tin đó, Alice đã hiểu ngữ
nghĩa của ứng dụng và biết rằng cô ấy không muốn sử dụng API.
Rõ ràng là bạn không nên cố gắng gây khó khăn cho người dùng của mình. Bạn không nên cung cấp
các URL vô nghĩa hoặc tạo ngẫu nhiên tên các mối quan hệ liên kết của mình.7 Điểm mấu chốt
của câu chuyện này là đó không phải là vấn đề ở cấp độ kỹ thuật. Bạn cần đảm bảo rằng giao
thức API và ngữ nghĩa ứng dụng của bạn được ghi lại, thông qua sự kết hợp của các cấu hình
và định nghĩa loại phương tiện. Bạn cần coi tài liệu của mình không phải là một sản phẩm
riêng biệt mà là một phần hạng nhất của API, như một bản trình bày được liên kết với các bản
trình bày khác bằng cách sử dụng điều khiển siêu phương tiện và mối quan hệ liên kết.
Trong phần trình bày API của bạn, các mối quan hệ liên kết và URL mà con người có thể đọc
được là những gợi ý hữu ích—các cách viết tắt giúp các nhà phát triển ứng dụng khách không
phải liên tục tra cứu ebddt trong tài liệu của bạn. Bản thân chúng không phải là tài liệu.
Tài liệu được nhúng trong API của bạn. Đó là điều cho phép API của bạn thay đổi theo thời gian.
7. Trừ khi bạn muốn chắc chắn rằng họ viết các ứng dụng khách có khả năng nhận biết siêu phương tiện.
CHƯƠNG 10
Sở thú Hypermedia
Có rất nhiều định dạng tài liệu hypermedia đang được sử dụng. Một số được thiết kế cho những mục
đích rất chuyên biệt—những người sử dụng chúng thậm chí có thể không coi chúng là định dạng siêu
phương tiện. Các định dạng hypermedia khác được sử dụng phổ biến đến mức mọi người không thực sự
nghĩ đến chúng. Trong chương này, tôi sẽ đưa bạn đi tham quan một “vườn thú” chứa các định dạng
Tôi sẽ không đi sâu vào chi tiết kỹ thuật. Bất kỳ định dạng nào trong số này đều có thể không phải
là định dạng bạn muốn sử dụng và tôi đã đề cập đến nhiều định dạng đó trước đó trong cuốn sách.
Nhiều định dạng vẫn đang được phát triển tích cực và chi tiết của chúng có thể thay đổi. Nếu bạn
quan tâm đến một trong những mẫu vật của vườn thú, bước tiếp theo là đọc thông số kỹ thuật chính thức của nó.
Mục tiêu của tôi là giúp bạn hiểu được nhiều dạng hypermedia có thể thực hiện và cho thấy chúng tôi
đã giải quyết các vấn đề cơ bản về việc biểu diễn nó bao nhiêu lần. Sở thú hypermedia đã đầy đến
mức bạn có thể không cần xác định loại phương tiện hoàn toàn mới cho API của mình. Bạn sẽ có thể
Tôi đã tổ chức vườn thú hypermedia theo hướng giới thiệu của tôi về hypermedia.
Có một phần dành cho các định dạng dành riêng cho miền (a la Chương 5), một phần dành cho các định
dạng có mục đích chính là triển khai mẫu bộ sưu tập (a la Chương 6) và một phần dành cho các định
Đối với các định dạng như Bộ sưu tập+JSON mà tôi đã trình bày chi tiết, tôi sẽ tóm tắt ngắn gọn về
định dạng và hướng bạn đến cuộc thảo luận trước đó. Có một số định dạng siêu phương tiện mà tôi sẽ
không thảo luận trong chương này, vì chúng có những cách tiếp cận khác với REST so với cách tôi đã
ủng hộ cho đến nay trong cuốn sách này. Tôi sẽ đề cập đến RDF và các hậu duệ của nó trong Chương 12
199
Machine Translated by Google
Các loại phương tiện này được thiết kế để thể hiện các vấn đề trong một miền cụ thể. Mỗi định nghĩa
một số ngữ nghĩa ứng dụng rất cụ thể và mặc dù bạn có thể sử dụng chúng để truyền đạt các ngữ nghĩa
Mê cung+XML
• Ngữ nghĩa giao thức: điều hướng bằng liên kết GET • Ngữ
Mê cung+XML xác định các thẻ XML và các mối quan hệ liên kết liên quan đến mê cung, các ô trong mê
cung và các kết nối giữa các ô. Hình 10-1 đưa ra sơ đồ trạng thái của ngữ nghĩa giao thức của nó.
Mê cung+XML xác định thẻ <link> có quan hệ liên kết và xác định chuyển đổi trạng thái an toàn; nghĩa
là nó cho phép khách hàng thực hiện yêu cầu GET. Bạn có thể mở rộng Mê cung+XML bằng cách đưa vào
các quan hệ liên kết tùy chỉnh hoặc bằng cách xác định các thẻ XML bổ sung. Vì đây là định dạng XML
nên bạn cũng có thể sử dụng XForms (qv) để thể hiện các chuyển đổi trạng thái không an toàn.
Tôi thực sự không khuyên bạn nên sử dụng Mê cung+XML, ngay cả khi bạn tình cờ tạo một trò chơi mê
cung. Đây chỉ là một ví dụ và tôi đặt nó lên hàng đầu để làm ví dụ về cách tôi đánh giá các định
dạng hypermedia.
Tìm kiếm mở
• Loại phương tiện: application/opensearchdescription+xml (đang chờ đăng ký) • Được xác định trong:
• Ngữ nghĩa giao thức: tìm kiếm bằng GET • Ngữ nghĩa
Chương 6
OpenSearch là một tiêu chuẩn để thể hiện các hình thức tìm kiếm. Nó có thể được sử dụng độc lập hoặc được
tích hợp vào một API khác bằng cách sử dụng mối quan hệ liên kết tìm kiếm . Sơ đồ trạng thái của nó trông
như thế này:
Đây là một đại diện OpenSearch đơn giản. Đích của biểu mẫu OpenSearch ( thuộc tính mẫu của thẻ <Url> của
nó ) là một chuỗi tương tự như Mẫu URI (RFC 6570), mặc dù nó không có tất cả các tính năng của Mẫu URI:
OpenSearch không xác định cách thể hiện kết quả tìm kiếm. Bạn nên sử dụng bất kỳ định dạng danh sách nào
phù hợp với định dạng trình bày chính của mình.
các quy tắc để tự động chuyển đổi sang XML) • Ngữ nghĩa giao thức: điều hướng bằng
GET
Tài liệu chi tiết về sự cố mô tả tình trạng lỗi. Nó sử dụng văn bản có cấu trúc, con người có thể
đọc được để thêm ngữ nghĩa tùy chỉnh vào mã trạng thái của HTTP. Đó là định dạng JSON đơn giản được
thiết kế để thay thế bất kỳ định dạng dùng một lần nào mà bạn đang nghĩ đến việc thiết kế để truyền
Giống như hầu hết các tài liệu hypermedia dựa trên JSON, chi tiết vấn đề có dạng đối tượng JSON. Đây
là tài liệu có thể được cung cấp cùng với mã trạng thái HTTP 503 (Dịch vụ không khả dụng):
Hai trong số các thuộc tính này được định nghĩa là các liên kết hypermedia. Thuộc tính được mô tảBy là một
liên kết đến phần giải thích mà con người có thể đọc được về cách biểu diễn.1
Thuộc tính supportId là một URL đại diện cho trường hợp cụ thể này của sự cố.
Không có kỳ vọng rằng người dùng cuối sẽ tìm thấy bất cứ điều gì ở đầu kia của URL này.
Đó có thể là một URL nội bộ để nhân viên hỗ trợ API sử dụng hoặc có thể là một URI, một ID duy nhất
Các thuộc tính descriptionBy và title là bắt buộc; phần còn lại là tùy chọn. Bạn cũng có thể thêm
SVG
SVG là một định dạng hình ảnh. Không giống như JPEG, đại diện cho hình ảnh ở cấp độ pixel, hình ảnh
SVG được tạo thành từ các hình dạng. SVG bao gồm một điều khiển siêu phương tiện cho phép các phần
khác nhau của hình ảnh liên kết với các tài nguyên khác nhau.
1. được mô tảBy là mối quan hệ liên kết đã đăng ký IANA, là phiên bản tổng quát hơn của hồ sơ. Một tài nguyên
được mô tả Bởi bất kỳ tài nguyên nào làm sáng tỏ cách giải thích của nó.
Điều khiển hypermedia đó là thẻ <a> có chức năng tương tự như thẻ <a> của HTML .
Đây là biểu diễn SVG đơn giản của một ô trong mê cung của Chương 5:
</svg>
Hình 10-2 cho thấy cách máy khách có thể hiển thị tài liệu này.
SVG là một giải pháp thay thế tốt cho HTML để xây dựng các ứng dụng di động. SVG cũng có thể
được kết hợp với HTML 5: chỉ cần dán thẻ <svg> vào đánh dấu HTML để có được hình ảnh SVG nội
tuyến.
Thẻ <a> của SVG không thực sự xác định bất kỳ khả năng siêu phương tiện nào. Nó chỉ là một thẻ
giữ chỗ cho vai trò của XLink và các thuộc tính href (qv). Vì SVG là định dạng XML nên bạn cũng
có thể thêm biểu mẫu XForms (qv) vào SVG và nhận được ngữ nghĩa giao thức tương đương với HTML.
Điều này không hữu ích bằng việc nhúng SVG vào HTML vì nó yêu cầu máy khách hiểu cả SVG và
XForms.
Giọng nóiXML
Được xác định trong: Tiêu chuẩn mở W3C, với phần mở rộng
• Ngữ nghĩa giao thức: GET để điều hướng; chuyển đổi trạng thái tùy ý thông qua các hình thức:
GET cho quá trình chuyển đổi an toàn, POST cho quá trình chuyển đổi không an toàn
Trong Chương 5, tôi đã đưa ra sự tương tự giữa một máy khách HTTP điều hướng API hypermedia và
một con người đang điều hướng cây điện thoại. Chà, rất nhiều cây điện thoại thực sự được triển
khai trên phần phụ trợ dưới dạng API hypermedia. Định dạng trình bày họ sử dụng là VoiceXML.
Đây là một cách trình bày VoiceXML có thể có của một ô trong trò chơi mê cung của Chương 5:
<thực đơn>
<lời nhắc>
Bạn đang ở trong Sảnh Kinh hoàng. Các lối thoát là: <enumerate/> </prompt>
<choice next="/cells/I">
Miền
Bắc </choice>
<choice next="/cells/M">
Phía đông
</lựa chọn>
<choice next="/cells/O">
Tây
Nếu bạn đang chơi trò chơi mê cung trên điện thoại, bạn sẽ không bao giờ nhìn thấy trực tiếp biểu
tượng này. “Trình duyệt” VoiceXML nằm ở đầu bên kia của đường dây điện thoại. Khi nhận được thông
báo này, nó sẽ xử lý tài liệu bằng cách đọc to <lời nhắc> cho bạn: “Bạn đang ở trong Phòng giải
Mỗi thẻ <choice> là một liên kết hypermedia. Trình duyệt chờ bạn kích hoạt một liên kết bằng
cách nói điều gì đó. Nó sử dụng nhận dạng giọng nói để tìm ra liên kết nào bạn đang kích hoạt.
Có một bước xác thực: nếu bạn không nói gì hoặc nói điều gì đó không ánh xạ tới một trong các
liên kết, trình duyệt sẽ đọc cho bạn một thông báo lỗi ( <noinput> hoặc <no match>) và chờ
nhập lại.
Khi bạn quản lý để kích hoạt một liên kết, trình duyệt sẽ thực hiện yêu cầu NHẬN tới URL được
đề cập trong thuộc tính tiếp theo tương ứng . Máy chủ phản hồi bằng một biểu diễn VoiceXML
mới và trình duyệt xử lý biểu diễn đó và cho bạn biết hiện tại bạn đang ở trong ô mê cung nào.
Thẻ <menu> chỉ là cách điều khiển siêu phương tiện đơn giản nhất của VoiceXML. Ngoài ra còn
có thẻ <form> sử dụng ngữ pháp nhận dạng giọng nói để thực hiện yêu cầu GET hoặc POST dựa
trên nội dung bạn yêu cầu. Đây là biểu mẫu VoiceXML để bật các công tắc bí ẩn mà tôi đã xác
định ở Chương 7:
<form id="switches">
<grammar src="command.grxml" type="application/srgs+xml"/>
<tên trường="lệnh">
<prompt>
Bạn muốn bật công tắc đỏ, bật công tắc xanh hay quên nó đi? </prompt> </field>
<prompt>
Nói tên của công tắc. </
prompt> </
field>
<đầy>
Thẻ <grammar> là một liên kết nội tuyến tương tự như thẻ HTML <img> hoặc <script> . Nó tự
động nhập một tài liệu được viết theo định dạng do W3C's Speech quy định
Đặc tả ngữ pháp công nhận.2 Tôi sẽ không hiển thị tệp SRGS ở đây vì SRGS không phải là định
dạng hypermedia. Đủ để nói rằng khi bạn nói những từ “bật công tắc đỏ” hoặc “quên nó đi”, ngữ
pháp SRGS là thứ cho phép trình duyệt VoiceXML chuyển đổi những từ đó thành một tập hợp các
cặp khóa-giá trị khớp với biểu mẫu. lệnh và chuyển đổi trường :
lệnh=công tắc
lật=công tắc đỏ
Sau khi các trường được điền các giá trị thu được thông qua nhận dạng giọng nói, thẻ <sub
mit> sẽ cho trình duyệt VoiceXML biết cách định dạng yêu cầu HTTP POST. Nó trông giống như
việc gửi biểu mẫu HTML:
command=flip&switch=red%20switch
Một tài liệu VoiceXML không khác gì mã ngôn ngữ lập trình.
VoiceXML sử dụng các thành ngữ trong lập trình để thể hiện luồng hội thoại thông qua cây hộp
thoại: <goto> để chuyển từ phần này sang phần khác của hộp thoại, <if> để thể hiện một điều
kiện và thậm chí <var> để gán giá trị cho một biến .
Ba tiêu chuẩn trong phần này có ngữ nghĩa giao thức và ứng dụng tương tự nhau, bởi vì chúng
đều triển khai mẫu bộ sưu tập mà tôi đã trình bày trong Chương 6. Trong mẫu bộ sưu tập, một
số tài nguyên nhất định được chỉ định là tài nguyên “item”. Một mục thường phản hồi GET, PUT
và DELETE và cách biểu diễn của nó tập trung vào việc biểu diễn các bit dữ liệu có cấu trúc.
Các tài nguyên khác được chỉ định là tài nguyên "bộ sưu tập". Một bộ sưu tập thường phản hồi
GET và POST-to-append, và cách trình bày của nó tập trung vào việc liên kết đến mục
tài nguyên.
Ba tiêu chuẩn này có những cách tiếp cận khác nhau đối với mẫu bộ sưu tập; họ có thể không sử
dụng thuật ngữ “bộ sưu tập” hoặc “vật phẩm”, nhưng tất cả đều thực hiện khá giống nhau.
Bộ sưu tập+JSON
• Ngữ nghĩa giao thức: mẫu thu thập (GET/POST/PUT/DELETE), cộng với tìm kiếm‐
• Ngữ nghĩa ứng dụng: mẫu bộ sưu tập (“bộ sưu tập” và “mục”) • Được đề cập trong:
Chương 6
Collection+JSON được thiết kế như một giải pháp thay thế dựa trên JSON đơn giản cho Giao thức xuất bản
Atom (qv). Đây là phiên bản chính thức, có khả năng nhận biết siêu phương tiện của các nhà phát triển
API có xu hướng thiết kế lần đầu tiên thông qua quy trình. Hình 10-3 cho thấy ngữ nghĩa giao thức của
nó.
• Ngữ nghĩa giao thức: mẫu thu thập (GET/POST/PUT/DELETE); các tiện ích mở rộng được xác định rõ
ràng thêm tính năng tìm kiếm và các hình thức điều hướng khác, tất cả đều sử dụng liên kết hoặc
biểu mẫu GET
• Ngữ nghĩa ứng dụng: mẫu thu thập (nguồn cấp dữ liệu và mục nhập); các mục có ngữ nghĩa của các
bài đăng trên blog (tác giả, tiêu đề, danh mục, v.v.); một mục nhập không phải là tài liệu Atom
(ví dụ: đồ họa nhị phân) được chia thành Mục nhập phương tiện nhị phân và Mục nhập Atom chứa siêu
Tiêu chuẩn API ban đầu, AtomPub đã đi tiên phong trong mẫu bộ sưu tập và cách tiếp cận RESTful đối
với API nói chung. Là một tiêu chuẩn dựa trên XML trong một lĩnh vực hiện bị thống trị bởi các biểu
diễn JSON, AtomPub giờ đây trông hơi lỗi thời, nhưng nó đã truyền cảm hứng cho một số tiêu chuẩn và
mối quan hệ liên kết khác có thể được sử dụng với các định dạng siêu phương tiện khác. Hình 10-4 cho
Mặc dù ngữ nghĩa ứng dụng của Atom ngụ ý rằng nó chỉ nên được sử dụng cho các ứng dụng cấp tin tức
như viết blog và quản lý nội dung API, nhưng tiêu chuẩn này rất có khả năng mở rộng. Có lẽ tiện ích
mở rộng đáng chú ý nhất là Giao thức dữ liệu của Google, nền tảng nền tảng API của Google. Google
thêm các thẻ dành riêng cho tên miền vào AtomPub để mô tả ngữ nghĩa ứng dụng của từng trang web của
mình. Nguồn cấp dữ liệu Atom trở thành tập hợp các video (API YouTube) hoặc tập hợp các ô bảng tính
Nếu bạn cho rằng ngữ nghĩa ứng dụng của mình không phù hợp với mẫu bộ sưu tập, hãy xem thư mục API
của Google có thể thuyết phục bạn bằng cách khác. Giao thức dữ liệu của Google cũng xác định JSON
tương đương với các biểu diễn XML của AtomPub, mặc dù đây là tiêu chuẩn tiền pháp định chứ không phải
Một số tiêu chuẩn mở xác định các tiện ích mở rộng AtomPub, bao gồm Tiện ích mở rộng luồng Atom và
phần tử mục nhập đã xóa . Tôi đã trình bày những điều này ở Chương 6.
OData
Phương tiện: JSON cho một số phần, XML cho một số phần khác
• Ngữ nghĩa giao thức: mẫu thu thập được sửa đổi (GET/POST/PUT/DELETE) với
PATCH để cập nhật một phần và GET cho các truy vấn; chuyển đổi trạng thái tùy ý với các
biểu mẫu (GET cho chuyển đổi an toàn và POST cho chuyển đổi không an toàn)
• Ngữ nghĩa ứng dụng: mẫu thu thập (nguồn cấp dữ liệu và mục nhập)
Ngữ nghĩa của OData được lấy cảm hứng rất nhiều từ Giao thức xuất bản Atom. Trên thực tế, API
OData có thể cung cấp các biểu diễn Atom và khách hàng có thể coi API OData là API AtomPub với
rất nhiều tiện ích mở rộng. Nhưng tôi sẽ coi OData là một API phục vụ hầu hết các biểu diễn
JSON.
Hình 10-5 hiển thị khung nhìn về ngữ nghĩa giao thức của OData, được đơn giản hóa để chỉ hiển
thị các phần của OData mà tôi sẽ trình bày ở đây. Và đây là bản trình bày OData của một bộ sưu
tập từ API tiểu blog, tương tự như You Type It, We Post It của Chương 2:
{
"odata.metadata":
"http://api.example.com/YouTypeItWePostIt.svc/$metadata#Posts", "value": [ {
"#Posts.RandomPostForDate":
{ "title": "Nhận một bài đăng ngẫu nhiên cho ngày nhất
định", "target": "Posts/RandomPostForDate" }
Hình 10-5. Ngữ nghĩa giao thức của OData (được đơn giản hóa)
Giống như các định dạng dựa trên JSON khác mà chúng ta đã thấy, biểu diễn OData là các đối tượng JSON có
thuộc tính được đặt tên bằng các chuỗi ngắn, bí ẩn. Thuộc tính như Content hoặc PostedAt là dữ liệu JSON
thông thường và tên của nó đóng vai trò như một bộ mô tả ngữ nghĩa. Thuộc tính có tên bao gồm odata. tiền
tố là điều khiển hypermedia hoặc một số siêu dữ liệu dành riêng cho OData. Một số ví dụ từ tài liệu này:
• Thuộc tính odata.id chứa một ID duy nhất—nghĩa là một URI—cho một
• Thuộc tính PostedAt@odata.type chứa thông tin loại ngữ nghĩa cho giá trị của thuộc tính PostedAt .
Loại, Edm.DateTimeOffset, đề cập đến định dạng lược đồ của OData: Mô hình Dữ liệu Thực thể. • Thuộc
liên kết AtomPub với rel="edit". Nếu bạn muốn sửa đổi hoặc xóa một trong các bài đăng mẫu, bạn có thể
gửi yêu cầu PUT, PATCH hoặc DELETE tới URL tương đối Bài đăng(2) hoặc Bài đăng(1).
• Thuộc tính PostedBy@odata.navigationLinkUrl chứa liên kết hypermedia tới một tài nguyên khác. Phần
dành riêng cho ứng dụng của tên thuộc tính, PostedBy, đóng vai trò là mối quan hệ liên kết. Về mặt
con người, đây là một liên kết đến người dùng đã xuất bản bài đăng cụ thể này.
Ngữ nghĩa giao thức của tài nguyên OData lặp lại những gì bạn đã thấy trong Collection+JSON và AtomPub.
Tài nguyên bộ sưu tập hỗ trợ GET (để lấy phần trình bày) và POST (để thêm một mục mới vào bộ sưu tập).
Các tài nguyên loại mục nhập hỗ trợ GET, cũng như PUT, DELETE và PATCH (thông qua odata.editLink của
chúng) .
Lọc OData
cũng xác định một tập hợp ngữ nghĩa giao thức ngầm để lọc và sắp xếp một bộ sưu tập, sử dụng ngôn ngữ
truy vấn tương tự như SQL. Nếu bạn biết mình có URL tới bộ sưu tập OData, bạn có thể thao tác URL đó theo
đối với các URL kết quả sẽ mang lại các biểu diễn lọc và phân trang bộ sưu tập theo nhiều cách
khác nhau.
Tôi nói rằng các ngữ nghĩa giao thức này là tiềm ẩn vì bạn không cần phải tìm kiếm một biểu mẫu
siêu phương tiện cho bạn biết cách thực hiện yêu cầu HTTP để thực hiện một tìm kiếm cụ thể. Bạn
có thể xây dựng yêu cầu đó dựa trên các quy tắc có trong thông số OData.
Hãy xem xét một vài ví dụ. Giả sử URL cơ sở (tương đối) của bộ sưu tập microblog là /Bài viết.
Bạn không cần biểu mẫu hypermedia để cho bạn biết cách tìm kiếm các bài đăng trên blog bao gồm
chuỗi “thứ hai” trong thuộc tính Nội dung của chúng . Bạn có thể tự xây dựng URL3 :
Bạn có thể tìm kiếm các bài đăng bao gồm “thứ hai” trong Nội dung của họ và được Đăng bởi một
Bạn chỉ có thể chọn năm bài đăng cuối cùng được xuất bản trong năm 2012:
/Posts$filter=year(PostedAt) eq 2012&$top=5
Bạn muốn có được trang thứ hai của danh sách đó? Bạn không cần phải tìm liên kết với mối quan
hệ tiếp theo trong biểu diễn. URL bạn nên sử dụng được xác định bởi thông số OData:
/Posts$filter=year(PostedAt) eq 2012&$top=5&skip=5
Theo mặc định, bộ sưu tập microblog trình bày các mục theo thứ tự thời gian đảo ngược dựa trên
giá trị của thuộc tính PostedAt . Thay vào đó, nếu bạn muốn sử dụng thứ tự thời gian, thông số
Trong các tiêu chuẩn mẫu bộ sưu tập khác, máy chủ phải cung cấp điều khiển siêu phương tiện để
mô tả rõ ràng từng nhóm tìm kiếm được phép. Collection+JSON phục vụ các mẫu tìm kiếm, AtomPub
phục vụ các biểu mẫu OpenSearch. Bộ sưu tập OData không cần cung cấp thông tin này vì mọi bộ
sưu tập OData đều hỗ trợ ngầm toàn bộ giao thức truy vấn OData. Khách hàng không cần biểu mẫu
hypermedia để biết có thể gửi yêu cầu GET tới một số URL nhất định hay không. Bản thân định
dạng OData đặt ra các ràng buộc bổ sung trên máy chủ để đảm bảo rằng một số URL nhất định sẽ
hoạt động.
OData xác định thêm một vài bit ngữ nghĩa giao thức ngầm, chủ yếu liên quan đến mối quan hệ
giữa các tài nguyên. Tôi sẽ không trình bày chúng ở đây.
Ngoài tập hợp các chuyển đổi trạng thái ấn tượng được xác định ngầm định bởi giao thức truy vấn
của OData, một biểu diễn OData có thể bao gồm các điều khiển siêu phương tiện rõ ràng mô tả
3. Rõ ràng tất cả các URL này cần phải được mã hóa URL. Tôi đã để chúng không được mã hóa để cho rõ ràng.
bất kỳ sự chuyển đổi trạng thái nào cả. Các điều khiển này có ngữ nghĩa giao thức tương tự như các dạng
HTML. Quá trình chuyển đổi an toàn được gọi là “hàm” và chúng sử dụng HTTP GET. Các chuyển đổi không an
toàn được gọi là “hành động” và chúng sử dụng HTTP POST. Tôi sẽ tập trung vào các chức năng, nhưng các hành
Đây là một biểu mẫu OData đơn giản lấy ngày làm đầu vào. Nó kích hoạt một quá trình chuyển đổi trạng thái
trong đó máy chủ xem xét tất cả các mục nhập của microblog từ một ngày nhất định, chọn một mục ngẫu nhiên
"#Posts.RandomPostForDate":
{ "title": "Nhận một bài đăng ngẫu nhiên cho ngày nhất
định", "target": "Posts/RandomPostForDate" },
Nếu đây là một truy vấn đơn giản như “tất cả các mục blog từ một ngày nhất định” thì biểu mẫu này sẽ không
cần thiết. Quá trình chuyển đổi trạng thái sẽ được mô tả ngầm bằng giao thức truy vấn của OData. Nhưng giao
thức đó không thể diễn đạt khái niệm “lựa chọn ngẫu nhiên”, vì vậy quá trình chuyển đổi trạng thái này
phải được mô tả rõ ràng bằng cách sử dụng biểu mẫu siêu phương tiện. Bây giờ, đây là câu hỏi: bạn có thể
nhìn vào biểu mẫu này và tìm ra yêu cầu HTTP nào cần thực hiện không?
Đó là một câu hỏi mẹo. Bạn không thể hình dung ra được vì tôi chưa cho bạn xem toàn bộ biểu mẫu.
Một phần của biểu mẫu cung cấp cho bạn URL cơ sở để sử dụng (Bài đăng/RandomPostforDate), nhưng nó không
giải thích cách định dạng phần đóng góp của bạn—ngày mà bạn muốn có một bài đăng ngẫu nhiên. Nó tương đương
Điều đó rõ ràng là không đầy đủ. Nó thiếu mô tả chính thức cho “ngày nhất định”. "Ngày nhất định" nên dùng
định dạng nào? Mô tả ngữ nghĩa của nó là gì? Bạn có kích hoạt quá trình chuyển đổi trạng thái bằng cách
Trong ví dụ HTML, thông tin còn thiếu sẽ nằm trong thẻ <input> thứ hai trong thẻ <form> . Nhưng với OData,
thông tin đó được lưu giữ trong một tài liệu khác — một “tài liệu siêu dữ liệu” được viết không phải bằng
JSON mà bằng XML, sử dụng từ vựng gọi là Ngôn ngữ định nghĩa lược đồ dấu phẩy (CSDL).4
Một biểu diễn OData liên kết đến tài liệu siêu dữ liệu của nó bằng thuộc tính odata.metadata
{
"odata.metadata":
4. Để biết thêm thông tin về cơ sở dữ liệu, hãy truy cập trang web OData.
"http://api.example.com/YouTypeItWePostIt.svc/$metadata#Posts",
...
}
Đây là một phần của tài liệu siêu dữ liệu hoàn thành định nghĩa về Ngẫu nhiên
Chuyển đổi trạng thái PostForDate :
Bây giờ bạn đã biết toàn bộ câu chuyện. Bạn kích hoạt quá trình chuyển đổi trạng thái RandomForDate bằng
cách định dạng ngày dưới dạng chuỗi, theo định dạng được xác định bởi Mô hình dữ liệu thực thể của
OData.5 Bạn biết rằng quá trình chuyển đổi trạng thái này là an toàn vì mô tả cơ sở dữ liệu của nó có
thuộc tính IsSideEffect ing được đặt thành false. Điều đó có nghĩa là bạn nên kích hoạt quá trình chuyển
Kết hợp tài liệu siêu dữ liệu với bản trình bày OData và bạn có tất cả thông tin cần thiết để kích hoạt
quá trình chuyển đổi trạng thái RandomPostForDate. Bạn gửi một yêu cầu HTTP trông giống như thế này:
Mặc dù RandomPostForDate là một quá trình chuyển đổi đơn giản nhưng quá trình chuyển đổi trạng thái
OData có thể rất phức tạp. Tài liệu siêu dữ liệu lưu trữ các chi tiết lộn xộn giải thích chính xác cách
kích hoạt bất kỳ chuyển đổi trạng thái nào mà bạn có thể thấy được đề cập trong tài liệu OData. Điều này
giúp máy chủ không phải đưa vào mô tả đầy đủ về quá trình chuyển đổi trạng thái phức tạp trong mọi biểu
diễn hỗ trợ nó. Một khách hàng quan tâm đến một quá trình chuyển đổi trạng thái nhất định có thể tra cứu
mô tả đầy đủ về nó.
Tài liệu siêu dữ liệu dưới dạng tài liệu mô tả dịch vụ Tôi
đã trình bày OData theo cách khiến nó trông giống như Collection+JSON hoặc Siren. Một bài đăng trên blog
nhỏ được thể hiện dưới dạng một đối tượng JSON chứa các trường dữ liệu như DatePublish ed, cùng với các
điều khiển siêu phương tiện và “siêu dữ liệu” khác giải thích các bước tiếp theo có thể thực hiện được.
Đó là phiên bản OData mà tôi khuyên dùng và nó có loại phương tiện application/ json;odata=fullmetadata.
Nhưng có một cách khác để ghi lại tài liệu OData: một cách giữ tất cả các điều khiển siêu phương tiện,
không chỉ những điều khiển phức tạp, trong tài liệu siêu dữ liệu.
5. EDM được định nghĩa trong cùng tài liệu với cơ sở dữ liệu.
{
"odata.metadata":
"http://api.example.com/YouTypeItWePostIt.svc/$metadata#Posts",
"value":
[ {
"Nội dung": "Đây là bài đăng đầu tiên.",
"Id": 1,
"PostedAt": "2013-04-30T01:42:57.0901805-05:00" }, {
]
}
Nhỏ hơn rất nhiều, nhưng trong thế giới REST, nhỏ hơn không nhất thiết phải tốt hơn.
Siêu dữ liệu đã đi đâu? Điều gì đã xảy ra với PostedBy@odata.navigationLinkUrl và
#Posts.RandomPostForDate? Làm thế nào bạn có thể quyết định yêu cầu HTTP nào sẽ được
thực hiện tiếp theo?
Tất cả thông tin đó được đưa vào tài liệu cơ sở dữ liệu ở đầu kia của oda
liên kết ta.metadata . Tôi đã cho bạn xem một phần tài liệu cơ sở dữ liệu trước đó khi tôi
thảo luận về RandomPostForDate, nhưng đây là một phần chi tiết hơn (đoạn trích này cho thấy
<Schema Namespace="YouTypeItWePostIt">
<EntityType Name="Post">
<Key><PropertyRef Name="Id"/></Key>
<Property Name="Id" Type="Edm.Int32" Nullable="false "/>
<Property Name="Content" Type="Edm.String"/>
<Property Name="PostedAt" Type="Edm.DateTimeOffset" Nullable="false"/>
<NavigationProperty Name="PostedBy"
Mối quan hệ="YouTypeItWePostIt.Post_PostedBy"
ToRole="PostedBy" FromRole="Post"/>
</EntityType>
...
<EntityContainer Name="YouTypeItWePostItContext"
m:IsDefaultEntityContainer="true">
</EntityContainer>
...
</Schema>
</edmx:DataServices>
</edmx:Edmx>
Không có gì sai khi giữ thông tin bổ sung về một tài nguyên bên ngoài phần trình bày của tài
nguyên đó. Suy cho cùng thì đó chính là chức năng của một cấu hình hoặc ngữ cảnh JSON-LD. Vấn đề
ở đây là tài liệu cơ sở dữ liệu có thể được xem như một tài liệu mô tả dịch vụ: tổng quan về API
nói chung khiến nó trông giống như một cơ sở dữ liệu quan hệ.
Như tôi đã đề cập ở Chương 9, người dùng nhìn thấy một tài liệu như thế này có xu hướng tự động
tạo mã máy khách dựa trên nó. Việc thực hiện này sẽ tạo ra sự kết nối chặt chẽ giữa ứng dụng
khách được tạo và phiên bản mô tả dịch vụ cụ thể này. Nếu việc triển khai máy chủ thay đổi, tài
liệu cơ sở dữ liệu sẽ thay đổi theo, nhưng các máy khách sẽ không thay đổi cho phù hợp. Họ sẽ
phá vỡ.
May mắn thay, không ai bắt bạn sử dụng OData theo cách này. Nếu bạn sử dụng ứng dụng loại phương
tiện/json;odata=fullmetadata, các biểu diễn OData của bạn sẽ chứa các điều khiển siêu phương
tiện của riêng chúng. Máy khách sẽ chỉ cần tham khảo tài liệu siêu dữ liệu cơ sở dữ liệu khi nó
cần kích hoạt quá trình chuyển đổi trạng thái phức tạp—một chức năng hoặc hành động—không thể
Các loại phương tiện này có ngữ nghĩa ứng dụng rất chung chung, nếu không thì chúng không có ngữ
nghĩa ứng dụng nào cả. Họ tập trung vào việc thể hiện ngữ nghĩa giao thức của HTTP. Bạn cung cấp
ngữ nghĩa ứng dụng của riêng mình bằng cách cắm các mối quan hệ liên kết và bộ mô tả ngữ nghĩa
HTML
• Các loại phương tiện: text/html và application/xhtml+xml •
Được xác định trong: các tiêu chuẩn mở cho HTML 4, cho XHTML, và cho HTML 5
• Ngữ nghĩa giao thức: điều hướng thông qua các liên kết GET; chuyển đổi trạng thái tùy ý thông qua các biểu
mẫu (GET cho chuyển đổi an toàn, POST cho chuyển đổi không an toàn) • Ngữ nghĩa ứng dụng:
tài liệu mà con người có thể đọc được (“đoạn”, “danh sách”, “bảng”,
“phần,” v.v.) •
Định dạng hypermedia ban đầu và sự lựa chọn được đánh giá thấp cho API. HTML có thể sử dụng trực tiếp các vi định
dạng và dữ liệu vi mô, thay vì sử dụng giá trị gần đúng như cấu hình ALPS. Thẻ <script> của HTML cho phép bạn
nhúng mã thực thi để chạy trên máy khách, một tính năng của kiến trúc RESTful (“mã theo yêu cầu”; xem Phụ lục C)
không được bất kỳ định dạng siêu phương tiện nào khác hỗ trợ. Và các tài liệu HTML có thể được hiển thị bằng đồ
họa cho con người—có giá trị đối với các API được thiết kế để sử dụng bởi ứng dụng khách Ajax hoặc thiết bị di
HTML có ba loại. HTML 4 đã trở thành tiêu chuẩn ổn định kể từ năm 1997. HTML 5, phiên bản thay thế của nó, vẫn
đang được phát triển. Ngoài ra còn có XHTML, một định dạng giống HTML nhưng lại là XML hợp lệ.
Theo quan điểm của cuốn sách này, sự khác biệt quan trọng duy nhất giữa ba tiêu chuẩn này là các quy tắc mới của
HTML 5 về xác thực đầu vào phía máy khách và thực tế là HTML 5 cuối cùng sẽ hỗ trợ dữ liệu vi mô.
HAL
• Các loại phương tiện: application/hal+json và application/hal+xml • Được xác định trong:
phiên bản XML được định nghĩa trong [tiêu chuẩn cá nhân tại đây] • Phương
chuyển đổi trạng thái tùy ý thông qua các liên kết có thể sử dụng bất kỳ
phương thức HTTP; các liên kết không đề cập đến phương thức HTTP sẽ được sử dụng—phương thức đó được lưu giữ
trong tài liệu mà con người có thể đọc được
HAL là một định dạng tối giản. Sơ đồ trạng thái của nó quá chung chung, trông giống như một điều gì
HAL dựa vào các mối quan hệ liên kết tùy chỉnh (và các giải thích mà con người có thể đọc được trong hồ sơ) để
Phương tiện: JSON (một phiên bản XML được lên kế hoạch)
• Ngữ nghĩa giao thức: điều hướng thông qua các liên kết GET; chuyển đổi trạng thái tùy ý thông
qua các “hành động” (GET cho các hành động an toàn, POST/PUT/DELETE cho các hành động không an toàn)
Tài liệu Siren mô tả một “thực thể”, một đối tượng JSON có ngữ nghĩa gần giống như thẻ <div> của
HTML . Một thực thể có thể có một “lớp” và một danh sách “thuộc tính”.
Nó có thể chứa danh sách các “liên kết”, hoạt động giống như thẻ HTML <a> (có rel và href). Nó cũng
có thể chứa một danh sách các hành động, hoạt động giống như các thẻ HTML <form> (có tên, href , một
Một thực thể cũng có thể có một số thực thể phụ, tương tự như cách một thẻ <div> có thể chứa một thẻ
khác. Bạn có thể triển khai mẫu bộ sưu tập theo cách này.
Sơ đồ trạng thái của Siren trông giống như sự kết hợp giữa HAL và HTML:
• Ngữ nghĩa giao thức: điều hướng thông qua các liên kết GET •
Tiêu đề Liên kết không phải là một định dạng tài liệu, nhưng tôi sẽ đưa nó vào danh sách thú vị vì nó
cho phép bạn thêm các liên kết GET đơn giản vào các biểu diễn thiếu các điều khiển siêu phương tiện,
như hình ảnh nhị phân hoặc tài liệu JSON. Tham số rel của tiêu đề là một vị trí cho mối quan hệ liên kết:
RFC 5988 xác định một số tham số hữu ích khác cho tiêu đề Liên kết , bao gồm loại (cung cấp gợi ý về
loại phương tiện ở đầu bên kia của liên kết) và tiêu đề (chứa tiêu đề mà con người có thể đọc được cho
liên kết).
Theo như tôi được biết, công dụng quan trọng nhất của tiêu đề Liên kết là kết nối tài liệu JSON với
một hồ sơ. JSON cực kỳ phổ biến mặc dù không có điều khiển siêu phương tiện và loại phương tiện ứng
dụng/json không hỗ trợ tham số hồ sơ , vì vậy Liên kết là cách đáng tin cậy duy nhất để trỏ đến hồ sơ
• Ngữ nghĩa giao thức: phụ thuộc vào mã phản hồi HTTP • Ngữ nghĩa ứng
Đây là hai điều khiển hypermedia đơn giản được xác định trong chính tiêu chuẩn HTTP. Tôi đã đề cập sơ
qua đến Vị trí , nhưng tôi sẽ cung cấp cả hai thông tin chi tiết trong Phụ lục B.
Tiêu đề Vị trí nội dung trỏ đến vị trí chuẩn của tài nguyên hiện tại.
Nó tương đương với một liên kết sử dụng chuẩn quan hệ liên kết đã đăng ký IANA.
Tiêu đề Vị trí được sử dụng làm liên kết đa năng bất cứ khi nào ngữ nghĩa giao thức của phản hồi HTTP yêu
cầu liên kết. Hành vi chính xác phụ thuộc vào mã trạng thái HTTP. Khi mã phản hồi là 201 (Đã tạo), tiêu đề
Vị trí sẽ trỏ đến tài nguyên mới được tạo. Nhưng khi mã phản hồi là 301 (Đã di chuyển vĩnh viễn), tiêu đề
Vị trí sẽ trỏ đến URL mới của tài nguyên đã được di chuyển. Một lần nữa, chi tiết có trong Phụ lục B.
Tài liệu văn bản/danh sách uri chỉ là một danh sách các URL:
http://example.org/
https://www.example.com/
...
Đây có lẽ là loại hypermedia cơ bản nhất từng được nghĩ ra. Nó không hỗ trợ các mối quan hệ liên kết, vì
vậy không có cách nào để thể hiện mối quan hệ giữa các URL này và tài nguyên phục vụ danh sách. Không có
biện pháp kiểm soát siêu phương tiện rõ ràng nên máy khách không có cách nào biết được loại yêu cầu nào
được phép gửi tới các URL này. Điều tốt nhất bạn có thể làm là gửi yêu cầu GET tới từng yêu cầu và xem bạn
Tài liệu Trang chủ JSON là phiên bản phức tạp hơn của danh sách URL. Định dạng này được thiết kế để sử dụng
làm “trang chủ” của API, liệt kê tất cả các tài nguyên được cung cấp và hành vi của chúng theo giao thức
HTTP.
Tài liệu gia đình JSON là một đối tượng JSON. Các khóa là các mối quan hệ liên kết và các giá trị là các
đối tượng JSON được gọi là “Đối tượng tài nguyên”. Đây là một ví dụ từ thế giới trò chơi mê cung:
Đối tượng tài nguyên là một điều khiển siêu phương tiện mô tả ngữ nghĩa giao thức của một tài
nguyên hoặc một nhóm tài nguyên liên quan. Đây là biểu mẫu tìm kiếm, được mô tả bởi Mẫu URI:
Đối tượng tài nguyên có thể bao gồm “gợi ý tài nguyên” mô tả ngữ nghĩa giao thức của nó chi
tiết hơn. Gợi ý phổ biến nhất là cho phép, giải thích phương thức HTTP nào mà tài nguyên sẽ
phản hồi. Đây là Tài liệu trang chủ JSON sử dụng mối quan hệ liên kết lật mà tôi đã xác định
Tài liệu gia đình JSON không nói gì về ngữ nghĩa ứng dụng của các tài nguyên mà nó liên kết
tới. Thông tin đó được lưu giữ trong phần trình bày ở phía bên kia của các liên kết.
Bằng cách kết hợp Tài liệu gốc JSON (mô tả ngữ nghĩa giao thức của API) với tài liệu ALPS (mô
tả ngữ nghĩa ứng dụng của nó), bạn có thể sử dụng API hiện có—ngay cả API không sử dụng
hypermedia—và di chuyển hầu hết các phần mà con người có thể đọc được. tài liệu sang định
dạng có cấu trúc, máy có thể đọc được.
không áp dụng • Được mô tả trong: Internet-Draft “dự thảo-nottingham-link-mẫu” (xem thêm RFC
6570)
Tiêu đề Mẫu liên kết hoạt động chính xác theo cách tương tự như tiêu đề Liên kết , ngoại trừ
giá trị của nó được hiểu là Mẫu URI (RFC 6570) thay vì dưới dạng URL. Đây là biểu mẫu tìm kiếm
trong tiêu đề HTTP:
Tiêu đề Mẫu liên kết có một biến đặc biệt gọi là var-base, cho phép bạn chỉ định cấu hình cho
các biến trong Mẫu URI. Trong ví dụ, tên biến family-name gợi ý loại giá trị nào bạn nên đưa vào
biến, nhưng về mặt kỹ thuật nó không có ý nghĩa gì cả. Nó cũng có thể được gọi là đặt-thứ gì đó
ở đây.
Thêm một cơ sở var và đột nhiên có một liên kết đến định nghĩa chính thức về họ.
Bây giờ, biến family-name sẽ mở rộng tới URL http://alps.io/microformats/ hCard#family-name. Tài
liệu ALPS ở đầu kia của URL đó giải thích ngữ nghĩa ứng dụng của biến họ .
Đây là một ví dụ khác sử dụng ngữ nghĩa ứng dụng của Schema.org thay vì ALPS:
Ở đây, biến familyName mở rộng tới URL http://schema.org/familyName, về cơ bản có nghĩa tương tự
như http://alps.io/microformats/hCard#family-
tên.
Vào thời điểm viết bài này, Bản nháp Internet xác định tiêu đề Mẫu liên kết đã hết hạn.
Tác giả của bản thảo, Mark Nottingham, đã bảo tôi cứ tiếp tục và viết nó vào cuốn sách. Anh ấy
cho biết anh ấy sẽ khôi phục Internet-Draft nếu có nhiều người quan tâm đến Link-Template hơn.
WADL
• Loại phương tiện: application/vnd.sun.wadl+xml •
Ngữ nghĩa ứng dụng: không có, hỗ trợ tối thiểu cho các tiện ích mở rộng
WADL là định dạng hypermedia đầu tiên hỗ trợ một bộ ngữ nghĩa giao thức hoàn chỉnh.
Thẻ WADL <request> (tương tự như biểu mẫu HTML) có thể mô tả một yêu cầu HTTP sử dụng bất kỳ
phương thức nào, cung cấp các giá trị cho mọi tiêu đề yêu cầu HTTP được chỉ định và bao gồm nội
dung thực thể của bất kỳ loại phương tiện nào. Giống như AtomPub, điều này bây giờ nghe có vẻ
không đặc biệt lắm nhưng nó đã mang tính đột phá vào thời điểm đó. WADL có thể mô tả ngữ nghĩa
giao thức của bất kỳ API web nào, ngay cả khi API được thiết kế kém và vi phạm tiêu chuẩn HTTP.
Đây là một đoạn WADL giải thích cách lật một công tắc trong phiên bản trò chơi mê cung ở Chương
7:
WADL cũng có thể mô tả nội dung của các biểu diễn XML. Tài liệu WADL có thể chỉ ra phần nào của cách
trình bày thú vị—đáng chú ý là phần nào liên kết đến các tài nguyên khác. Tài liệu WADL có thể đưa
vào tài liệu Lược đồ XML để giải thích các kiểu dữ liệu của dữ liệu XML mà nó mô tả. Điều này hữu ích
khi một biểu diễn XML không có lược đồ liên quan của riêng nó.
Thẻ <doc> của WADL làm cho nó trở thành định dạng hồ sơ cơ bản, có khả năng mô tả ngữ nghĩa ứng dụng
của một yêu cầu HTTP hoặc bên trong biểu diễn XML. Nhưng WADL hoàn toàn không thể mô tả bên trong
biểu diễn JSON.6 WADL không được sử dụng rộng rãi, nhưng có
một số triển khai Java JAX-RS tạo ra các mô tả API WADL. Vấn đề nằm ở đó. Mô tả API được tạo tự động
có thể được kết hợp chặt chẽ với việc triển khai phía máy chủ. Hơn nữa, một API sử dụng WADL thường
phục vụ một tài liệu WADL khổng lồ mô tả ngữ nghĩa giao thức của toàn bộ API.
Đây là tài liệu mô tả dịch vụ và như tôi đã đề cập trong Chương 9 , người dùng tạo , nó khuyến khích
các ứng dụng khách được tạo tự động, dựa trên giả định rằng họ đã có được cái nhìn tổng quan đầy đủ
Nhưng API thay đổi. Khi điều đó xảy ra, mô tả WADL của API cũng sẽ thay đổi, nhưng các ứng dụng khách
được tạo tự động thì không. Các khách hàng sẽ phá vỡ.
XLink
• Ngữ nghĩa giao thức: điều hướng và nhúng với GET • Ngữ nghĩa ứng dụng:
không có
XLink là một tiêu chuẩn plug-in cho phép bạn thêm các liên kết hypermedia vào bất kỳ tài liệu XML nào.
Không giống như HTML và Maze+XML, XLink không xác định các thẻ XML đặc biệt đại diện cho các liên kết
siêu phương tiện. XLink xác định một nhóm thuộc tính có thể được áp dụng cho bất kỳ thẻ XML nào để
Đây là bản trình bày XML đặc biệt của một ô trong trò chơi mê cung. Thẻ <root> và <direction> là tên
6. Tiêu chuẩn Con trỏ JSON, được xác định trong con trỏ ứng dụng Internet-Draft, có thể khắc phục điều này.
khả năng hypermedia của riêng mình, nhưng tôi có thể biến chúng thành liên kết bằng cách thêm thuộc tính XLink.
<?xml version="1.0"?>
<root xmlns:xlink="http://www.w3.org/1999/xlink"> <direction
xlink:href="http://maze-server.com/maze /cell/N"
xlink:title="Đi về phía
đông!" xlink:arcrole="http://alps.io/example/maze/#east"
xlink:show="replace" />
<link
xlink:href="http://maze-server.com/maze/cell/L"
xlink:title="Đi về phía tây!"
xlink:arcrole="http://alps.io/example/maze/#west"
xlink:show="replace" />
</
root>
Các thuộc tính href và title trông quen thuộc. Mối quan hệ liên kết đi vào thuộc tính arcrole tùy chọn . Có một sự
thay đổi nhỏ ở đây: thuộc tính arcrole chỉ hỗ trợ các mối quan hệ liên kết mở rộng—những mối quan hệ trông giống như
các URL. Mối quan hệ liên kết của bạn không được giống tác giả hoặc đông; nó phải trông giống như http://alps.io/maze/
#west.
Thuộc tính show cho phép bạn chuyển đổi giữa liên kết điều hướng hoạt động giống như thẻ <a> của HTML (show="replace",
mặc định) và liên kết nhúng hoạt động giống như thẻ <img> của HTML (show="embed"). Phương thức HTTP được sử dụng
luôn là GET.
Với XLink, tôi có thể cung cấp vốn từ vựng XML đặc biệt gần giống với các khả năng siêu phương tiện đã được thiết kế
thành Mê cung+XML. Có một vài tính năng nâng cao của XLink mà tôi chưa đề cập đến: đáng chú ý là loại liên kết mở
rộng, cho phép bạn kết nối nhiều hơn hai tài nguyên bằng một liên kết duy nhất và thuộc tính vai trò mà tôi sẽ trình
XForms
• Ngữ nghĩa giao thức: chuyển đổi trạng thái tùy ý thông qua các biểu mẫu (GET cho chuyển đổi an toàn, POST/PUT/
XForms thực hiện đối với các biểu mẫu siêu phương tiện giống như XLink thực hiện đối với các liên kết. Đó là một
tiêu chuẩn plug-in bổ sung các biểu mẫu giống HTML vào bất kỳ tài liệu XML nào. Tuy nhiên, không giống như XLink, nó
xác định các thẻ riêng của mình. Đây là cách XForms có thể biểu diễn một biểu mẫu tìm kiếm đơn giản:
<xforms:mô hình>
<xforms:submission action="http://example.com/search" Method="get" id="submit-
button"/>
<xforms:instance>
<query/>
</xforms:instance>
<xforms:model>
Thẻ <model> là một vùng chứa, giống như thẻ <form> của HTML . Thẻ <submission> giải thích yêu
cầu HTTP cần thực hiện: trong trường hợp này là yêu cầu GET tới http://example.com/search.
Phần con của thẻ <instance> giải thích cách xây dựng chuỗi truy vấn (đối với yêu cầu GET) hoặc
phần nội dung thực thể (đối với yêu cầu POST hoặc PUT).
Thẻ <query> là thẻ tôi tạo ra cho ví dụ này; nó đại diện cho một trường biểu mẫu được gọi là
truy vấn. Ý nghĩa của thẻ này—ví dụ: cho dù đó là trường văn bản hay hộp kiểm—được xác định
<xforms:input ref="query">
<xforms:label>Cụm từ tìm kiếm</xforms> </
xforms:input>
<xforms:submit submit="submit-button">
<label>Tìm kiếm!</label> </
xforms:submit>
Thẻ <input> có ref="query" cho biết trường truy vấn là một kiểu nhập văn bản có <nhãn> mà con
người có thể đọc được . Thẻ <submit> cung cấp <label> cho nút gửi. Cùng với nhau, thẻ <model>
và hai thẻ <input> gần đúng chức năng của biểu mẫu HTML này:
Đây là một ví dụ rất cơ bản; có nhiều tính năng nâng cao của XForms mà tôi sẽ không đề cập
đến. Hướng dẫn của W3C “XForms dành cho tác giả XHTML”7 sử dụng các biểu mẫu HTML để giải thích
XForms một cách chi tiết, vượt xa khả năng của HTML thuần túy thành một số tính năng nâng cao
của XForms.
khả năng sử dụng trong APIs.8 Tôi không làm điều này để chọn GeoJSON; Bản thân tôi cũng đã mắc phải
những sai lầm tương tự. Đó là những lỗi phổ biến, vì vậy ngay cả khi GeoJSON không phải là thứ bạn cần
GeoJSON là một tiêu chuẩn dựa trên JSON, được thiết kế để thể hiện các đặc điểm địa lý như các điểm trên
Được xác định trong: tiêu chuẩn công ty được xác định
• Ngữ nghĩa giao thức: GET để loại trừ các hệ tọa độ • Ngữ nghĩa ứng dụng: các
Giống như hầu hết tất cả các tài liệu dựa trên JSON được sử dụng trong API, tài liệu GeoJSON là một đối
tượng JSON phải chứa một số thuộc tính nhất định. Đây là tài liệu GeoJSON xác định chính xác vị trí của
một di tích cổ trên Trái đất:
{ "loại": "FeatureCollection",
"features":
"hình học":
{ "loại": "Điểm",
"tọa độ": [12.484281,41.895797] },
"properties":
{ "type": null,
"title": "Cột Trajan", "awmc_id":
"91644", "awmc_link":
"http://awmc.unc.edu/api/omnia/91644" , "pid": "423025",
"pleiades_link":
"http://pleiades.stoa.org/places/423025", "description": "Đài tưởng
niệm hoàng đế Marcus Ulpius Traianus"}
} ] }
8. Những sai sót này không gây tổn hại nhiều đến GeoJSON đến mức không ai sử dụng nó. Nó khá phổ biến—chỉ là không tốt như nó có thể
là.
Tôi đã điều chỉnh cách trình bày này một chút từ API trong thế giới thực do Trung tâm Bản đồ
Thế giới Cổ đại của UNC cung cấp . Ngữ nghĩa ứng dụng của GeoJSON rất đơn giản và con người
có thể hiểu tài liệu khá dễ dàng. Nó đại diện cho một bộ sưu tập được gọi là FeatureCollection.
Bộ sưu tập chỉ chứa một mục: Đối tượng, có hình học (một Điểm duy nhất trên bản đồ) và một
loạt các thuộc tính linh tinh như mô tả mà con người có thể đọc được .
Nhìn nhanh vào tiêu chuẩn GeoJSON sẽ thấy rằng thay vì Điểm , hình học có thể là LineString
(đại diện cho đường biên giới hoặc đường) hoặc Đa giác (đại diện cho khu vực của một thành
phố hoặc quốc gia).
GeoJSON không có các biện pháp kiểm soát siêu phương tiện
chung Thật không may, ngữ nghĩa giao thức của GeoJSON không hề đơn giản. Bạn có thấy
awmc_link và pleiades_link trong phần trình bày đó không? Chúng trông giống như các liên kết
hypermedia, nhưng thực tế không phải vậy. Theo tiêu chuẩn GeoJSON, đó chỉ là những chuỗi
trông giống như URL. Khi Trung tâm lập bản đồ thế giới cổ đại thiết kế API GeoJSON của họ,
họ phải nhét tất cả các liên kết của mình vào danh sách thuộc tính vì GeoJSON không xác định
các điều khiển hypermedia cho chúng. Điều này có nghĩa là máy khách GeoJSON chung không thể
theo dõi pleiades_link hoặc thậm chí nhận ra nó là một liên kết. Để theo liên kết đó, bạn
cần phải viết một ứng dụng khách cụ thể cho API của Trung tâm Bản đồ Thế giới Cổ đại.
Nếu GeoJSON không xác định bất kỳ điều khiển hypermedia nào thì điều này có thể hiểu được.
Không phải mọi định dạng dữ liệu đều phải là định dạng hypermedia. Đơn giản là tôi sẽ không
đề cập đến GeoJSON trong cuốn sách này. Điều kỳ lạ là GeoJSON xác định điều khiển hypermedia,
nhưng nó chỉ có thể được sử dụng cho một việc cụ thể: thay đổi hệ tọa độ đang sử dụng.
Theo mặc định, tọa độ trong biểu diễn GeoJSON ([12.484281,41.895797]) được đo bằng độ kinh
độ và vĩ độ—một hệ thống mà tất cả chúng ta đều quen thuộc. Vì hành tinh Trái đất không phải
là một hình cầu hoàn hảo nên các phép đo này được diễn giải theo một tiêu chuẩn gọi là
WGS84,9, tiêu chuẩn này đưa ra những thứ như hình dạng gần đúng của Trái đất, vị trí của kinh
tuyến gốc và “mực nước biển” nghĩa là gì.
Nếu bạn không phải là người đam mê bản đồ, bạn có thể cho rằng Trái đất là một hình cầu và
xong việc với nó. Nhưng đối với những người đam mê bản đồ, WGS84 chỉ là mặc định. Có nhiều
hệ tọa độ khác mà bạn có thể sử dụng. Độc giả người Anh có thể quen thuộc với Lưới điện Quốc
gia Khảo sát Quân sự, một hệ thống tọa độ sử dụng “hướng đông” và “hướng bắc” thay vì vĩ độ
và kinh độ, và hệ thống này chỉ có thể biểu thị các điểm trong một khu vực cụ thể có kích
thước 700 x 1300 km mà bao trùm quần đảo Anh. Có vô số hệ tọa độ, vì bạn có thể xác định một
hệ tọa độ đặt kinh tuyến gốc của Trái đất ở bất cứ đâu bạn muốn.
9. Một tiêu chuẩn ngành, nhưng từ một ngành khác với các tiêu chuẩn còn lại được đề cập trong cuốn sách này.
Bạn có thể lấy phiên bản PDF của tiêu chuẩn tại trang này.
Và bây giờ câu chuyện của chúng ta quay trở lại với hypermedia, bởi vì đây chính là mục đích
kiểm soát hypermedia duy nhất của GeoJSON. GeoJSON cho phép bạn liên kết đến mô tả về hệ tọa
độ bạn đang sử dụng.
Đây là tài liệu GeoJSON chứa liên kết hypermedia chính hãng mà bất kỳ ứng dụng khách GeoJSON
nào cũng sẽ nhận ra như vậy:
{ "type:"Tính năng",
"hình học":
{ "type": Điểm",
"tọa độ":[60000,70000] },
"crs":
{ "type":
"link",
"properties": { "href": "http://example.org/
mygrid.wkt",
"type": "esriwkt" }
}
}
Tọa độ [60000,70000] không phải là số đo kinh độ và vĩ độ hợp lệ, nhưng điều đó không sao vì
chúng tôi không sử dụng kinh độ và vĩ độ. Chúng tôi đang sử dụng hệ quy chiếu tọa độ tùy
chỉnh (crs) được mô tả bởi tài nguyên tại http://example.org/ mygrid.wkt. Đây chính xác là
thứ mà hypermedia phù hợp. Vấn đề với GeoJSON là nơi duy nhất nó cho phép liên kết nằm trong
định nghĩa của hệ quy chiếu tọa độ.
Điều đó không hữu ích lắm! Hầu hết các API GeoJSON không sử dụng hệ tọa độ tùy chỉnh—tất cả
chúng ta đều quen với kinh độ và vĩ độ thông thường. Nhưng tiêu chuẩn GeoJSON cho phép chúng,
vì chúng là một khía cạnh thiết yếu của miền có vấn đề. Mặt khác, hầu như bất kỳ API nào cũng
cần cung cấp các liên kết linh tinh giữa các tài nguyên của nó, nhưng tiêu chuẩn Geo- JSON
thiếu khả năng đó, có lẽ vì nó không liên quan trực tiếp đến miền vấn đề. Định dạng dữ liệu
cơ bản không giúp ích được gì vì JSON không xác định điều khiển siêu phương tiện nào cả. Đó
là lý do tại sao những người triển khai API phải dùng đến các thủ thuật hack như awmc_link.
Phàn nàn đủ rồi; tôi sẽ làm gì khác đi? Một thiết kế tập trung hơn vào siêu phương tiện sẽ
cho phép một danh sách các liên kết, mỗi liên kết có thể chỉ định một mối quan hệ liên kết.
GeoJSON sẽ trông giống Collection+JSON hoặc Siren hơn rất nhiều. Sau đó là bản đồ thế giới cổ đại
Center sẽ không cần phải đưa awmc_link và pleiades_link vào đối tượng thuộc tính .
Để liên kết đến một hệ tọa độ, bạn sẽ sử dụng cùng loại liên kết mà bạn sử dụng cho bất kỳ mục đích nào
khác. Các crs của GeoJSON sẽ trở thành một mối quan hệ liên kết, hữu ích trong bất kỳ ứng dụng bản đồ
Bạn có thể có các điều khiển hypermedia dành riêng cho ứng dụng. Thẻ <img> của HTML là một điều khiển
siêu phương tiện dành riêng cho ứng dụng. Nhưng bạn cũng cần cung cấp một điều khiển liên kết chung, đơn
giản.
vấn đề khác với GeoJSON: nó không có loại phương tiện đã đăng ký. Tài liệu GeoJSON được phục vụ dưới dạng
ứng dụng/json, giống như bất kỳ tài liệu JSON nào khác. Làm cách nào khách hàng có thể phân biệt giữa
Giải pháp tốt nhất là máy chủ coi GeoJSON như một cấu hình của JSON. Điều này có nghĩa là cung cấp một
liên kết tới tiêu chuẩn GeoJSON với rel="profile". Vì bản thân JSON không có điều khiển siêu phương tiện
Bạn cũng có thể viết cấu hình ALPS hoặc ngữ cảnh JSON-LD cho GeoJSON và cung cấp liên kết đến đó bằng tiêu
đề Liên kết :
Theo như tôi biết, không có triển khai GeoJSON nào thực hiện được một trong những điều này. GeoJSON được
phục vụ dưới dạng ứng dụng/json và khách hàng chỉ cần biết trước tài nguyên nào phục vụ các biểu diễn
GeoJSON và tài nguyên nào phục vụ JSON thông thường. Máy khách muốn hiểu các cấu hình khác nhau của JSON
phải chạy phương pháp phỏng đoán đối với mọi biểu diễn JSON đến, cố gắng tìm ra cấu hình nào mà máy chủ
Nghe có vẻ phi thực tế khi một khách hàng sẽ cần xử lý các cấu hình JSON khác nhau?
Vâng, hãy xem xét điều này. Nền tảng ArcGIS bao gồm một API trình bày cùng loại thông tin như GeoJSON. Nó
phục vụ các biểu diễn JSON bề ngoài giống với các biểu diễn của GeoJSON và nó phục vụ chúng dưới dạng ứng
Tôi không nghĩ việc tưởng tượng một khách hàng có thể xử lý cả GeoJSON và ArcGIS JSON là một điều viển
vông. Nếu GeoJSON được phân phối dưới dạng ứng dụng/geo+json và ArcGIS JSON được phân phối dưới dạng ứng
dụng/vnd.arcgis.api+json, thì nhà phát triển ứng dụng khách có thể tách mã ứng dụng khách dựa trên giá
trị của tiêu đề Kiểu nội dung và hợp nhất mã đường dẫn sau khi dữ liệu đến được phân tích cú pháp. Nếu
được dùng dưới dạng các cấu hình khác nhau, nhà phát triển có thể chia mã dựa trên giá trị của tiêu đề Liên
kết . Nếu chúng được phân phối với các ngữ cảnh JSON-LD khác nhau, nhà phát triển có thể chia mã dựa trên đó.
Nhưng cả hai định dạng đều được phục vụ như thể chúng có cùng ý nghĩa. Một máy khách hợp nhất phải cố gắng
phân biệt giữa hai định dạng bằng cách sử dụng phương pháp chẩn đoán được xác định kém. Hoặc, nhiều khả năng
hơn, ý tưởng về một khách hàng thống nhất chưa bao giờ xuất hiện với bất kỳ ai. Giống như hai con tàu đi qua
trong đêm, một nhà phát triển viết ứng dụng khách GeoJSON cho API GeoJSON, trong khi một nhà phát triển khác
sao chép phần lớn công việc của nhà phát triển đầu tiên, viết ứng dụng khách ArcGIS để chạy trên các bản cài
đặt ArcGIS.
Không ai có thể đổ lỗi cho việc này. Tiêu chuẩn GeoJSON đã được hoàn thiện vào năm 2008. Vào thời điểm đó,
hiểu biết của chúng tôi về API hypermedia khá kém. Các nhà thiết kế GeoJSON không quên đăng ký loại phương
Nhưng bây giờ không còn là năm 2008 nữa. Hiện tại chúng tôi có các tiêu chuẩn bổ sung các điều khiển siêu
phương tiện thực sự vào JSON. Chúng ta có thể sử dụng cấu hình để thêm ngữ nghĩa cấp ứng dụng vào các loại
siêu phương tiện chung. Chúng tôi đã thấy hàng trăm định dạng dữ liệu không tương thích lẫn nhau được phân
phát dưới dạng ứng dụng/json và chúng tôi biết mình có thể làm tốt hơn.
GeoJSON được đưa vào tài liệu JSON có khả năng siêu phương tiện (chẳng hạn như tài liệu OData, có hỗ trợ rõ
ràng cho GeoJSON được nhúng), cả hai vấn đề này đều biến mất. Việc GeoJSON không có các biện pháp kiểm soát
siêu phương tiện chung không thành vấn đề vì nó được nhúng trong một tài liệu có thể xử lý những nội dung
đó. Việc GeoJSON không có loại phương tiện đặc biệt không thành vấn đề vì nó kế thừa loại phương tiện của
tài liệu gốc. Tại thời điểm này, GeoJSON trở thành một tiêu chuẩn plug-in, tương tự như OpenSearch.
Nếu bạn thiết kế một định dạng dành riêng cho miền mà rõ ràng không phải là một phần bổ trợ cho một số định
dạng khác thì bạn nên cung cấp cho nó một loại phương tiện duy nhất. Sẽ hữu ích nếu bạn cũng đăng ký loại
phương tiện với IANA, nhưng nếu bạn sử dụng vnd . tiền tố, bạn không phải đăng ký bất cứ điều gì.
Ngoài ra, hãy đảm bảo định dạng của bạn có một số loại điều khiển siêu phương tiện chung, như thẻ <link> của
Mê cung+XML. Bạn có thể nghĩ rằng công việc của bạn không phải là cung cấp một điều khiển siêu phương tiện
chung vì điều đó không liên quan gì đến miền vấn đề của bạn. Nhưng nếu bạn không cung cấp khả năng kiểm soát
siêu phương tiện, mỗi người dùng của bạn sẽ nghĩ ra thiết kế chỉ dùng một lần của riêng họ, gọi là
awmc_link. Bạn có thể mượn điều khiển siêu phương tiện clip-on đơn giản bằng cách sử dụng XLink cho tài liệu
Nói chung, có lẽ tốt hơn là nên quên loại phương tiện dành riêng cho miền và thiết kế một tập hợp ngữ nghĩa
ứng dụng dành riêng cho miền — một hồ sơ. Sau đó, những ngữ nghĩa đó có thể được áp dụng vào loại siêu phương
tiện chung như Siren hoặc loại phương tiện mẫu bộ sưu tập như Bộ sưu tập+JSON.
linh hoạt của các thiết kế dựa trên hypermedia. Bây giờ tôi sẽ đưa bạn đi tham quan một vườn thú
khác (nhanh hơn nhiều): một loạt vườn bướm chứa đầy ngữ nghĩa ứng dụng cho các lĩnh vực vấn đề
khác nhau. Mục tiêu của tôi ở đây cụ thể hơn: giúp bạn tiết kiệm thời gian bằng cách sử dụng lại
Trong Chương 9, tôi đã đề cao lợi ích của việc sử dụng lại ngữ nghĩa ứng dụng hiện có. Các hồ sơ
được liệt kê ở đây là kết quả của những người thông minh xem xét cẩn thận một miền có vấn đề và
điều hướng các vấn đề đặt tên phức tạp. Không có lý do gì bạn phải sao chép tác phẩm đó. Việc sử
dụng lại ngữ nghĩa hiện có bất cứ khi nào có thể cũng loại bỏ cám dỗ tiết lộ chi tiết triển khai
máy chủ của bạn, giúp bạn có thể tự do thay đổi những chi tiết đó mà không làm tổn hại đến khách
Điều quan trọng nhất là khi các API khác nhau chia sẻ cùng một ngữ nghĩa ứng dụng, có thể viết
các ứng dụng khách có khả năng tương tác hoặc các thư viện xử lý ngữ nghĩa chung thay vì một ứng
dụng khách tùy chỉnh cho từng API riêng lẻ. Hiện tại điều này mang tính hy vọng hơn là hiện
thực, nhưng ít nhất con đường phía trước trước mắt đã rõ ràng.
Thay vì hiển thị cho bạn nhiều hồ sơ riêng lẻ trong vườn thú ngữ nghĩa, tôi sẽ tập trung chủ yếu
Tôi đã nói về cơ quan đăng ký IANA về các mối quan hệ liên kết gần như trong toàn bộ cuốn sách.
Đó là sổ đăng ký toàn cầu chứa khoảng 60 mối quan hệ liên kết. Bạn được phép sử dụng bất kỳ mối
quan hệ nào đã đăng ký IANA trong bất kỳ tuyên bố nào và cho rằng khách hàng của bạn biết bạn
Các mối quan hệ liên kết chỉ được đưa vào sổ đăng ký IANA nếu chúng được xác định theo tiêu
chuẩn mở như Khuyến nghị RFC hoặc W3C và đủ chung để hữu ích cho mọi loại phương tiện. Mỗi mối
quan hệ liên kết được cung cấp một mô tả ngắn gọn mà con người có thể đọc được và một liên kết
Trong bước 3 của quy trình thiết kế của Chương 9, tôi đề cập đến một số mối quan hệ liên kết đã
• Loại phương tiện: HTML (Phiên bản ALPS có sẵn cho một số vi định dạng)
này • Ngữ nghĩa: loại nội dung mà con người có thể muốn tìm kiếm trực tuyến
Dự án Microformats là nỗ lực thành công đầu tiên trong việc xác định các cấu hình cho ngữ nghĩa
ứng dụng. Các vi định dạng được xác định một cách cộng tác, trên wiki và danh sách gửi thư. Trong
số các vi định dạng ổn định, đây là những vi định dạng mà bạn có thể quan tâm nhất:
hLịch
Diễn tả các sự kiện theo thời gian. Dựa trên định dạng iCalendar văn bản thuần túy được xác định trong
RFC 2445.
hCard
mô tả con người và tổ chức. Dựa trên định dạng vCard văn bản thuần túy (được xác định trong
XFN
Một tập hợp các mối quan hệ liên kết mô tả mối quan hệ giữa con người với nhau, từ bạn bè ,
XOXO
Mô tả các đường nét. Vi định dạng này rất thú vị vì nó không thêm bất kỳ thứ gì vào HTML. Nó
chỉ gợi ý những cách thực hành tốt nhất để sử dụng ngữ nghĩa ứng dụng hiện có của HTML.
Các thông số kỹ thuật vi định dạng này là bản nháp về mặt kỹ thuật, nhưng hầu hết chúng không thay
đổi trong vài năm, vì vậy tôi có thể nói rằng chúng khá ổn định:
quảng cáo
Địa chỉ vật lý. Đây là định dạng con của hCard, chỉ bao gồm các phần đại diện cho địa chỉ. Ý
tưởng là nếu bạn không cần tất cả hCard, bạn chỉ cần sử dụng adr.
địa lý
Vĩ độ và kinh độ. (Dĩ nhiên là sử dụng tiêu chuẩn WGS84!) Một định dạng phụ khác của hCard.
hAtom
Bài đăng trên blog. Dựa trên định dạng nguồn cấp dữ liệu Atom (RFC 4287). Đây là một ví dụ
thú vị về một định dạng siêu phương tiện (HTML) áp dụng ngữ nghĩa ứng dụng của một định dạng
khác (Atom).
hDanh
sách Danh sách các dịch vụ cho thuê, quảng cáo cá nhân, v.v. Vi định dạng này chủ yếu sử dụng
lại ngữ nghĩa từ các vi định dạng có liên quan: hReview, hCard và hCalendar.
hMedia
hNews
Một phần mở rộng của hAtom bổ sung thêm một số mô tả cụ thể cho các bài báo, như dòng ngày.
hSản
hCông
thức nấu ăn .
hTiếp tục
Sơ yếu lý lịch/CV.
hĐánh giá
Mô tả một đánh giá (về bất cứ điều gì), với một đánh giá.
Có một số vi định dạng thú vị mà tôi chưa đề cập đến vì chúng đã được HTML 5 áp
dụng một cách hiệu quả và hiện là các mối quan hệ liên kết đã đăng ký IANA: tác
giả, nofollow, thẻ và giấy phép. Vi định dạng thanh toán lại cũng trở thành thanh
toán quan hệ liên kết được đăng ký IANA.
Tôi đã tạo các tài liệu ALPS nắm bắt ngữ nghĩa ứng dụng thiết yếu của hầu hết các vi định dạng được liệt kê
Wiki Microformats cũng có một danh sách khổng lồ các mối quan hệ liên kết được xác định trong các tiêu chuẩn
hoặc được thấy trong cách sử dụng thực tế nhưng chưa được đăng ký với IANA. Trang wiki này là cơ quan đăng ký
chính thức cho các quan hệ liên kết được sử dụng trong HTML 5, nhưng nó cũng là cơ quan đăng ký không chính
thức của tất cả các quan hệ liên kết mong muốn trở nên hữu ích bên ngoài một ứng dụng. Các mối quan hệ liên
kết của Maze+XML sẽ không bao giờ cắt đứt được với IANA—chúng quá dành riêng cho ứng dụng—nhưng chúng được đề
cập trên wiki Microformats.
Trong Chương 8, tôi đã đề cập đến trang wiki này và đưa ra một số ví dụ về các mối quan hệ được xác định ở
đó. Tôi không khuyên bạn chỉ nên chọn các mối quan hệ liên kết từ trang wiki này và sử dụng chúng. Khách hàng
của bạn sẽ không biết bạn đang nói về điều gì. Ưu điểm thực sự của trang này là cách tìm kiếm các tiêu chuẩn
Nếu bạn đang dự định tạo API trò chơi mê cung của riêng mình và bạn đã tìm kiếm trang này về mê cung hoặc
phía bắc, bạn sẽ khám phá Maze+XML. Bạn không nhất thiết phải sử dụng
Mê cung+XML, nhưng bạn sẽ có cái nhìn thoáng qua về cách người khác đã giải quyết vấn đề tương
tự.
lược đồ.org
Ngữ nghĩa: loại nội dung mà con người có thể muốn tìm kiếm trực tuyến
Như tôi đã đề cập ở Chương 8, nguồn chính cho các mục dữ liệu vi mô là một cơ quan thanh toán bù
trừ có tên là lược đồ.org. Trang web này sử dụng ngữ nghĩa ứng dụng của các tiêu chuẩn như rNews
(dành cho tin tức) và GoodRelations (dành cho các cửa hàng trực tuyến) và chuyển chúng sang các
mục dữ liệu vi mô. Đổi lại, tôi đã tự động tạo tài liệu ALPS cho các mục vi dữ liệu của Schema.org
Có hàng trăm mục dữ liệu vi mô được mô tả trên lược đồ.org và nhiều mục khác đang được triển
khai khi những người bảo trì lược đồ.org làm việc với những người tạo ra các tiêu chuẩn khác để
thể hiện các tiêu chuẩn đó trong dữ liệu vi mô. Thay vì nói về tất cả các mục dữ liệu vi mô, tôi
sẽ liệt kê các mục cấp cao nhất hiện tại và đề cập đến một số lớp con đáng chú ý của chúng:
• CreativeWork (bao gồm Bài viết, Blog, Sách, Bình luận, Ghi âm nhạc, Soft‐
• Sự kiện (bao gồm Sự kiện kinh doanh, Lễ hội và Tương tác người dùng) •
Vô hình là một loại danh mục tổng hợp, trong đó đáng chú ý bao gồm Đối tượng, Thương hiệu,
Tọa độ địa lý, Đăng việc làm, Ngôn ngữ, Ưu đãi và Số lượng •
• Tổ chức (bao gồm Công ty, tổ chức phi chính phủ và Đội thể thao)
• Người
• Địa điểm (bao gồm Thành phố, Núi và Điểm thu hút khách du lịch)
Như bạn có thể thấy, có rất nhiều điểm trùng lặp giữa các mục vi dữ liệu của lược đồ.org và vi
định dạng. Mục Person có cùng nền tảng với vi định dạng hCard. Mục Sự kiện tương tự như hEvent,
Article thành hAtom, NewsArticle thành hNews, Recipe to hRecipe, GeoCoordines to geo, v.v.
Xin lưu ý: các mục vi dữ liệu của lược đồ.org rất tập trung vào người tiêu dùng. Sản phẩm là thứ
mà khách hàng có thể mua, không phải là dự án mà khách hàng đang thực hiện. Ngữ nghĩa của mục
Nhà hàng liên quan nhiều đến việc ăn uống tại một nhà hàng và hầu như không liên quan gì đến
việc điều hành hoặc kiểm tra một nhà hàng. Có một mục Ứng dụng phần mềm,
nhưng không có gì liên quan đến lỗi, bài kiểm tra đơn vị, kho lưu trữ kiểm soát phiên bản, cột
mốc phát hành hoặc bất kỳ vấn đề nào khác mà chúng tôi xử lý khi phát triển phần mềm. Trong mắt
tôi, mục duy nhất được mô tả đủ chi tiết để hữu ích cho bác sĩ là MedicalEntity, và bác sĩ có thể
Nói tóm lại, dự án Schema.org có quan điểm rõ ràng. Nó không phải là bách khoa toàn thư và ngay
cả khi nó xác định một mục trùng với miền API của bạn thì ngữ nghĩa ứng dụng mà nó xác định có
thể không liên quan gì đến cách bạn nhìn nhận mọi thứ.
Dublin Core là tiêu chuẩn ban đầu để xác định ngữ nghĩa ứng dụng, có từ năm
1995. Nó xác định 15 bit ngữ nghĩa cho thông tin về các tác phẩm đã xuất bản:
tiêu đề, tác giả, mô tả, v.v. Những bit ngữ nghĩa này có thể được sử dụng làm
bộ mô tả ngữ nghĩa hoặc làm quan hệ liên kết.
Sáng kiến siêu dữ liệu cốt lõi Dublin cũng đã xác định một hồ sơ hoàn chỉnh hơn, các Điều khoản
siêu dữ liệu DCMI. Cấu hình này bao gồm các bộ mô tả ngữ nghĩa như dateCopyrighed, cũng như các
Luồng hoạt động là một tiêu chuẩn của công ty để thể hiện cuộc sống trực tuyến của chúng ta dưới
dạng một chuỗi các “hoạt động” rời rạc. Mỗi hoạt động có một tác nhân (thường là con người đang
sử dụng máy tính), một động từ (điều mà tác nhân đang làm) và một tân ngữ (điều mà tác nhân đang
Khi bạn xem một video trực tuyến, đó là một hoạt động. Bạn là diễn viên, video là đối tượng và
động từ (theo Luồng hoạt động) là chuỗi ký tự “chơi”. Một số hoạt động có mục tiêu cũng như đối
tượng. Khi tôi xuất bản một bài viết mới lên blog của mình, tôi là tác nhân, bài viết blog là đối
Tôi đã đặt Luồng hoạt động trong phần này, mặc dù đó là định dạng dữ liệu vì định dạng dữ liệu
không xác định bất kỳ điều khiển siêu phương tiện nào. Nhưng có rất nhiều ngữ nghĩa thực sự hữu
ích ở đây. Luồng hoạt động xác định tên và mô tả ngữ nghĩa cho nhiều
những thứ chúng ta tương tác trực tuyến (Bài viết, Sự kiện, Nhóm, Người). Quan trọng hơn, nó
xác định rất nhiều tên hữu ích cho các động từ (join, rsvp-yes, follow, cancel), có ý nghĩa
như tên của các chuyển đổi trạng thái không an toàn.
Tiêu chuẩn Luồng hoạt động giải thích cách trình bày một chuỗi các hoạt động dưới dạng nguồn cấp dữ liệu
Atom. Hãy sử dụng tính năng này và Luồng hoạt động sẽ là một định dạng siêu phương tiện thực sự, một phần
mở rộng cho Atom.
Ngoài ra còn có một phiên bản Luồng hoạt động dựa trên JSON độc lập. Nó có cùng các vấn đề như GeoJSON:
không có điều khiển siêu phương tiện và không có cách nào để phân biệt tài liệu Luồng hoạt động với tài liệu
JSON đơn giản.10 Để thêm điều khiển siêu phương tiện vào tài liệu Luồng hoạt động JSON, bạn sẽ cần sử dụng
Có nhiều điểm trùng lặp giữa ngữ nghĩa của Luồng hoạt động và các mục vi dữ liệu của Schema.org. Có các mục
vi dữ liệu được gọi là Bài viết, Sự kiện, Nhóm và Người. Mục vi dữ liệu Người dùng-Checkins giống như động
từ “checkin” của Luồng hoạt động, UserLikes giống như “like” và UserPlays giống như “play”. (Đối với bản
thiết lập cơ quan đăng ký hồ sơ ALPS tại trang này để tái sử dụng chung. Là một phần trong công việc của tôi
nhằm giải phóng ngữ nghĩa ứng dụng khỏi các loại phương tiện của chúng, tôi đã tạo các phiên bản ALPS của
các mục siêu dữ liệu Schema.org, một số vi định dạng và Dublin Core. Đó chỉ là sự khởi đầu; hy vọng vào thời
điểm bạn đọc bài viết này, tôi cũng sẽ tạo được các hồ sơ ALPS truyền tải được ngữ nghĩa ứng dụng của các
Nếu muốn sử dụng cấu hình ALPS để xác định ngữ nghĩa ứng dụng API của mình, bạn có thể tìm kiếm trên Alps.io
để tìm cấu hình phù hợp với mình hoặc tập hợp một cấu hình mới từ các cấu hình hiện có.
Nếu bạn quyết định sử dụng cấu hình ALPS trong API của mình, vui lòng tham khảo các bit của cấu hình trong
Sổ đăng ký ALPS. Sau khi bạn hoàn tất, tôi sẽ đánh giá cao nếu bạn tải hồ sơ lên Cơ quan đăng ký ALPS (cũng
như lưu trữ hồ sơ cục bộ như một phần API của bạn). Bằng cách đó, người khác có thể tìm và sử dụng lại ngữ
10. “Draft-snell-activity-streams-type” Internet-Draft sẽ giải quyết vấn đề thứ hai. Nó đăng ký phương tiện truyền thông
CHƯƠNG 11
HTTP cho API
Hãy coi World Wide Web (và bất kỳ API RESTful nào khác) như một kho công nghệ.
URL ở dưới cùng; họ xác định tài nguyên. Giao thức HTTP nằm trên các tài nguyên đó, cung
cấp quyền truy cập đọc vào các biểu diễn của chúng và quyền truy cập ghi vào trạng thái
tài nguyên cơ bản. Hypermedia nằm trên HTTP, mô tả ngữ nghĩa giao thức của một trang
web hoặc API cụ thể.
Hình 11-1. Kho công nghệ hình thành nên World Wide Web
Lớp dưới cùng trả lời câu hỏi “Tài nguyên ở đâu?” Lớp giữa trả lời câu hỏi “Làm cách
nào để liên lạc với tài nguyên?” Lớp trên cùng trả lời câu hỏi “Tiếp theo là gì?”
Cho đến nay, cuốn sách này đã tập trung vào lớp trên cùng của ngăn xếp— “Tiếp theo là gì?” Đó là bởi vì
lớp trên cùng là lớp phức tạp nhất. Hầu hết các API ngày nay đều sử dụng URL và HTTP một cách chính xác
Trong chương này, tôi sẽ tạm dừng sử dụng hypermedia và đi xuống một cấp độ để giải
thích ngữ nghĩa giao thức nâng cao của HTTP. Tôi không muốn giải thích chi tiết về giao
thức HTTP; vì điều đó, tôi khuyên dùng HTTP: Hướng dẫn dứt khoát, của David Gourley và Brian
237
Machine Translated by Google
Totty (O'Reilly). Tôi sẽ tập trung vào các tính năng của HTTP đặc biệt hữu ích trong API và các tính
năng mà các nhà phát triển API mới có thể không biết đến.
Fielding (của luận án Fielding nổi tiếng) và một nhóm làm việc của IETF đang nghiên cứu một loạt RFC
Không có gì về giao thức HTTP sẽ thay đổi; vấn đề là cải thiện tài liệu. RFC mới làm rõ ngữ nghĩa giao
thức của HTTP và hợp nhất một số tiện ích bổ sung được xác định sau khi RFC 2616 được xuất bản, chẳng
Hy vọng rằng các RFC mới đã được xuất bản vào thời điểm bạn đọc bài viết này. Nhưng nếu chúng vẫn đang
được thực hiện, bạn có thể đọc bản nháp bằng cách vào danh sách tài liệu của nhóm làm việc . Đó là một
cách dễ dàng hơn để hiểu một số phần phức tạp của giao thức HTTP hơn là nghiên cứu kỹ RFC 2616.
Mã phản hồi
RFC 2616 xác định 41 mã phản hồi HTTP. Một số trong số chúng không hữu ích cho mục đích của chúng tôi,
nhưng nhìn chung, chúng đại diện cho một tập hợp ngữ nghĩa cơ bản, được xác định theo tiêu chuẩn cơ bản
nhất trong tất cả các tiêu chuẩn API. Không có lý do gì để bỏ qua món quà này. Nếu bạn phát minh lại
404 (Không tìm thấy) hoặc 409 (Xung đột) cho API của mình thì bạn chỉ đang tạo thêm công việc cho mọi người.
Nếu khách hàng gửi một số dữ liệu không hợp lệ tới API của bạn, bạn nên gửi mã phản hồi 400 (Yêu cầu
không hợp lệ) và nội dung thực thể giải thích vấn đề là gì. Đừng gửi 200 (OK) kèm theo thông báo lỗi.
Bạn đang nói dối khách hàng. Bạn sẽ phải viết thêm tài liệu giải thích rằng trong API của mình, OK đôi
Trong Phụ lục A, tôi nói về tất cả các mã phản hồi được xác định trong tiêu chuẩn HTTP và một số mã hữu
Tiêu đề
RFC 2616 xác định 47 tiêu đề phản hồi và yêu cầu HTTP. Giống như mã phản hồi, một số mã gần như vô dụng
nhưng nhìn chung chúng xác định một tập hợp ngữ nghĩa cơ bản mà mọi API đều có thể hưởng lợi. Sử dụng
chúng.
Một số tiêu đề tương ứng với các tính năng của HTTP quan trọng đối với API: đáng chú ý là đàm phán nội
dung và yêu cầu có điều kiện. Tôi đã đưa ra những phần riêng của chúng trong chương này. Trong Phụ lục
B, tôi nói về tất cả các tiêu đề được xác định theo tiêu chuẩn HTTP.
Tôi cũng đề cập đến một số tiện ích mở rộng hữu ích: đáng chú ý là tiêu đề Liên kết mà bạn đã thấy.
nhau: nhiều API web phục vụ “các hương vị” XML và JSON cho tất cả các tài nguyên của chúng. Đôi khi các
cách trình bày chứa đựng văn xuôi đã được dịch sang các ngôn ngữ khác nhau của con người. Đôi khi các
cách biểu diễn khác nhau biểu thị các bit khác nhau của trạng thái tài nguyên: một tài nguyên có thể có
Khi máy chủ cung cấp nhiều cách biểu diễn cho một tài nguyên, máy khách phải làm cách nào để phân biệt
giữa chúng? Làm thế nào để khách hàng báo hiệu họ muốn tiếng Anh hay tiếng Tây Ban Nha, XML hay JSON,
có thể sử dụng các tiêu đề yêu cầu HTTP đặc biệt để cho máy chủ biết nó muốn thể hiện những gì. Quá
trình này được gọi là đàm phán nội dung và tiêu chuẩn HTTP xác định năm tiêu đề yêu cầu cho nó. Chúng
được gọi chung là các tiêu đề Accept-* . Tôi sẽ đề cập đến cả năm điều trong Phụ lục B, nhưng ở đây tôi
muốn nhấn mạnh hai điều quan trọng nhất: Ngôn ngữ chấp nhận và Ngôn ngữ chấp nhận.
Hầu hết các ứng dụng khách API web chỉ hiểu một loại phương tiện duy nhất. Khi họ đưa ra yêu cầu, họ sẽ
gửi tiêu đề Chấp nhận đơn giản , yêu cầu loại phương tiện đó:
Máy khách thông báo cho máy chủ rằng nó chỉ hiểu Collection+JSON. Nếu máy chủ có tùy chọn phân phát
Khi tôi thực hiện một yêu cầu HTTP từ trình duyệt web của mình, nó sẽ gửi một yêu cầu phức tạp hơn nhiều
RFC 2616 cung cấp thông tin chi tiết phức tạp về những gì có thể đưa vào tiêu đề Accept-* , nhưng ví dụ
thực tế này đóng vai trò là một chỉ báo tốt về những gì có thể làm được. Công việc chính của trình
duyệt web là hiển thị các trang web, vì vậy trình duyệt của tôi ưu tiên hàng đầu cho các biểu diễn HTML
(loại phương tiện văn bản/html ) và các biểu diễn XHTML (ứng dụng/xhtml). Trình duyệt của tôi cũng có
thể hiển thị XML thô (ứng dụng/xml), nhưng vì nó trông không đẹp bằng nên XML được ưu tiên thấp hơn HTML
(q=0,9). Nếu không có biểu diễn HTML hay XML nào (có thể vì tài nguyên là hình ảnh nhị phân), trình
duyệt của tôi sẽ chấp nhận bất kỳ loại phương tiện nào (*/*). Nhưng đó là lựa chọn cuối cùng và được ưu
Trình duyệt web của tôi cũng có cài đặt cho tùy chọn ngôn ngữ: ngôn ngữ nào tôi muốn sử dụng để truy cập các trang
web. Với mỗi yêu cầu HTTP tôi thực hiện, trình duyệt của tôi sẽ chuyển đổi tùy chọn ngôn ngữ của tôi thành giá trị
Điều này nói lên rằng tôi thích tiếng Anh Mỹ hơn, nhưng tôi sẽ chấp nhận bất kỳ phương ngữ nào của tiếng Anh như
một sự thay thế tốt thứ hai. (Tôi thực sự không kén chọn về vấn đề này, nhưng đó là những gì tôi đã nói với trình
Nếu máy chủ không thể thực hiện yêu cầu do hạn chế Accept-* , nó có thể gửi mã phản hồi 406 (Không được chấp nhận).
Chương 8, tôi đã loại bỏ tham số loại phương tiện hồ sơ vì không có nhiều loại phương tiện hỗ trợ nó, nhưng nó có
lợi thế lớn trong việc đàm phán nội dung. Khi loại phương tiện hỗ trợ tham số cấu hình , bạn có thể sử dụng thương
lượng nội dung để yêu cầu một cấu hình cụ thể. Đây là một khách hàng muốn có bản trình bày XHTML sử dụng vi định
dạng hCard:
Khách hàng này muốn có cùng định dạng dữ liệu (XHTML) nhưng muốn dữ liệu được trình bày dưới dạng vi dữ liệu
Schema.org:
Bạn không thể làm điều đó nếu hồ sơ được truyền tải thông qua tiêu đề Liên kết . Và tất nhiên, bạn không thể làm
nội dung. Nhưng hãy xem xét cách khách hàng tìm thấy sự đại diện mà họ muốn nói chung. Không có quá trình “thương
lượng tài nguyên”. Thay vào đó, máy khách thực hiện yêu cầu GET tới URL biển quảng cáo của API và máy chủ phân
phát bản trình bày trang chủ bao gồm các liên kết hypermedia đến các tài nguyên khác. Máy khách chọn liên kết nào
nó muốn theo dõi và thực hiện một yêu cầu GET khác cho một đại diện khác. Máy khách tìm thấy tài nguyên mà nó đang
tìm kiếm bằng cách lần lượt đưa ra các lựa chọn.
Chiến lược này cũng hoạt động tốt khi các lựa chọn là sự lựa chọn giữa các định dạng dữ liệu.
Các tính năng đàm phán nội dung của HTTP chỉ tối ưu hóa cho một số trường hợp phổ biến. Thay vì sử dụng chúng,
bạn có thể cung cấp cho mỗi phần trình bày URL riêng, biến nó thành một tài nguyên độc lập một cách hiệu quả.
Máy chủ đưa ra lựa chọn giữa các tài nguyên này bằng cách gửi mã phản hồi 300 (Nhiều lựa chọn). Phần thân thực
thể phải chứa một tài liệu hypermedia liên kết với các lựa chọn khác nhau. Nếu bạn làm theo cách này, bạn sẽ cần
có khả năng giải thích những gì ở đầu bên kia của một liên kết. Nếu không, khách hàng của bạn
sẽ không có cách nào quyết định nên nhấp vào liên kết nào.
Các thẻ <a> và <link> của HTML hỗ trợ tốt cho việc này, với thuộc tính type :
Thuộc tính hreflang là gợi ý về ngôn ngữ ở đầu bên kia của liên kết:
Vì hầu hết các định dạng hypermedia không có những tính năng này nên tôi thường khuyên bạn nên
đàm phán nội dung dựa trên tiêu đề cho việc này.
URL chuẩn
Bất cứ khi nào một tài nguyên có nhiều URL, bạn nên xác định một trong số chúng là URL chính
thức hoặc URL chuẩn: URL mà khách hàng nên sử dụng khi nói về tài nguyên thay vì gửi yêu cầu
Có hai cách để làm điều này. Trước tiên, bạn có thể sử dụng tiêu đề HTTP Content-Location tiêu
chuẩn làm điều khiển siêu phương tiện trỏ đến URL chuẩn của tài nguyên hiện tại.
Ngoài ra còn có chuẩn quan hệ liên kết đã đăng ký IANA , phục vụ cùng mục đích. Bạn có thể sử
dụng chuẩn trong phần trình bày hoặc trong tiêu đề Liên kết .
tối ưu hóa để ngăn chặn các yêu cầu có khả năng vô nghĩa (lưu vào bộ nhớ đệm), để giảm chi phí
của một yêu cầu hóa ra là vô nghĩa (yêu cầu có điều kiện) và để giảm chi phí của một yêu cầu
Bộ nhớ đệm
Bộ nhớ đệm là một trong những phần phức tạp nhất của HTTP. RFC 2616 chứa các quy tắc chi tiết
về việc vô hiệu hóa bộ đệm và có nhiều vấn đề liên quan đến các trung gian HTTP như proxy bộ
đệm. Tôi sẽ tập trung vào cách đơn giản nhất để thêm bộ đệm vào API web, sử dụng Kiểm soát bộ
đệm tiêu đề HTTP. Trong Phụ lục B, tôi cũng sẽ thảo luận về tiêu đề Hết hạn , tiêu đề này rất
hữu ích trong một trường hợp phổ biến khác. Đối với bất cứ điều gì phức tạp hơn, tôi sẽ
giới thiệu bạn đến HTTP: Hướng dẫn dứt khoát, và tới “draft-ietf-httpbis-p6-cache” Internet-Draft, một
phần trong nỗ lực hiện tại nhằm thay thế RFC 2616.
Đây là tiêu đề Kiểm soát bộ đệm đang hoạt động, như một phần của phản hồi cho yêu cầu HTTP GET:
HTTP/1.1 200 OK
Loại nội dung: text/html Kiểm
soát bộ đệm: max-age=3600
...
Lệnh max-age cho biết khách hàng phải đợi bao lâu trước khi thực hiện lại yêu cầu HTTP này. Nếu khách hàng
nhận được phản hồi này và nửa giờ sau, khách hàng muốn gửi lại yêu cầu thì khách hàng sẽ tạm dừng. Máy
chủ cho biết sẽ kiểm tra lại sau một giờ (3.600 giây) chứ không phải trước đó.
Chỉ thị bộ nhớ đệm áp dụng cho toàn bộ phản hồi HTTP, bao gồm tiêu đề và mã phản hồi, không chỉ cho phần
nội dung thực thể. Ý tưởng là nếu máy khách thực sự cần xem phản hồi HTTP, thì máy khách sẽ xem xét phản
hồi được lưu trong bộ nhớ đệm thay vì thực hiện lại yêu cầu.
Một cách sử dụng phổ biến khác của Kiểm soát bộ đệm là để máy chủ yêu cầu máy khách không lưu phản hồi
HTTP/1.1 200 OK
Loại nội dung: text/html Kiểm
soát bộ đệm: không có bộ đệm
...
Điều này chỉ ra rằng trạng thái tài nguyên không ổn định đến mức việc thể hiện có thể trở nên lỗi thời
Việc đặt Kiểm soát bộ đệm khi bạn phục vụ một đại diện yêu cầu bạn đưa ra phán quyết về tần suất một đại
diện sẽ thay đổi. Nếu bạn hiểu sai điều này, điều này có thể dẫn đến việc dữ liệu của người dùng đã lỗi
thời.
Đối với các biểu diễn bao gồm hoàn toàn các điều khiển hypermedia, các biểu diễn chỉ thay đổi khi bạn
nâng cấp triển khai API của mình, việc đặt tuổi tối đa khá cao là điều hợp lý. Hoặc bạn có thể sử dụng…
Đôi khi bạn không biết khi nào trạng thái của tài nguyên sẽ thay đổi. (Tài nguyên loại bộ sưu tập là tệ
nhất đối với việc này.) Nó có thể thay đổi mọi lúc hoặc có thể thay đổi hiếm khi đến mức bạn không thể
ước tính tần suất thay đổi xảy ra. Dù bằng cách nào, bạn không thể quyết định giá trị cho độ tuổi tối đa,
vì vậy bạn không thể yêu cầu khách hàng ngừng yêu cầu tài nguyên đó trong một thời gian. Thay vào đó, bạn
có thể để máy khách đưa ra yêu cầu bất cứ khi nào nó muốn và loại bỏ phản hồi của máy chủ nếu không có gì
thay đổi.
Tính năng phía máy khách này được gọi là yêu cầu có điều kiện và để hỗ trợ nó, bạn sẽ cần phân
phát tiêu đề Last-Modified hoặc ETag cùng với phần trình bày của mình (tốt hơn hết là phân phát cả
hai). Tiêu đề được sửa đổi lần cuối cho khách hàng biết thời điểm trạng thái của tài nguyên này
HTTP/1.1 200 OK Độ
dài nội dung: 41123 Loại
nội dung: text/html Sửa đổi
lần cuối: Thứ Hai, ngày 21 tháng 1 năm 2013 09:35:19 GMT
<html>
...
Máy khách ghi lại giá trị được sửa đổi lần cuối và lần sau khi thực hiện yêu cầu, nó sẽ đặt giá
Nếu trạng thái tài nguyên đã thay đổi kể từ ngày được cung cấp trong If-Modified-Since thì không có
gì đặc biệt xảy ra. Máy chủ gửi mã trạng thái 200, Bản sửa đổi lần cuối được cập nhật và bản
HTTP/1.1 200 OK Độ
dài nội dung: 44181 Loại
nội dung: text/html Sửa đổi
lần cuối: Thứ Hai, ngày 27 tháng 1 năm 2013 07:57:10 GMT
<html>
...
Nhưng nếu phần trình bày không thay đổi kể từ yêu cầu cuối cùng thì máy chủ sẽ gửi mã trạng thái
304 (Không được sửa đổi) và không có nội dung thực thể:
Điều này giúp tiết kiệm thời gian và băng thông của cả hai bên. Máy chủ không phải gửi đại diện và
máy khách không cần phải nhận nó. Nếu bản trình bày được tạo động từ trạng thái tài nguyên thì yêu
cầu có điều kiện cũng giúp máy chủ tiết kiệm công sức tạo bản trình bày.
Tất nhiên, điều này có nghĩa là bạn sẽ phải làm thêm việc. Bạn sẽ cần theo dõi ngày sửa đổi gần
đây nhất của tất cả tài nguyên của mình. Và hãy nhớ rằng giá trị của Last-Modified là ngày biểu
diễn được thay đổi. Nếu bạn có một tài nguyên bộ sưu tập mà biểu diễn của nó bao gồm các bit của
các biểu diễn khác, thì Bản sửa đổi lần cuối của tài nguyên đó biểu thị lần cuối cùng bất kỳ nội
Có một chiến lược khác dễ thực hiện hơn Last-Modified và tránh được một số điều kiện chạy đua.
Tiêu đề ETag (viết tắt của “thẻ thực thể”) chứa một chuỗi vô nghĩa phải thay đổi bất cứ khi nào
Dưới đây là một phản hồi HTTP mẫu bao gồm ETag:
HTTP/1.1 200 OK
Độ dài nội dung: 44181
Loại nội dung: text/html
ETag: "7359b7-a37c-45b333d7"
<html>
...
Khi máy khách thực hiện yêu cầu thứ hai cho cùng một tài nguyên, nó sẽ đặt giá trị If-None-
So khớp tiêu đề với ETag mà nó nhận được trong phản hồi ban đầu:
Nếu ETag trong If-None-Match giống với ETag hiện tại của biểu diễn, máy chủ sẽ gửi 304 (Không được
sửa đổi) và phần nội dung thực thể trống. Nếu biểu diễn đã thay đổi, máy chủ sẽ gửi 200 (OK), nội
Việc cung cấp Sửa đổi lần cuối yêu cầu bạn phải theo dõi nhiều dấu thời gian, nhưng bạn có thể
tạo Thẻ ET cho các biểu diễn mà không cần theo dõi bất kỳ dữ liệu bổ sung nào. Một phép biến đổi
như hàm băm MD5 có thể biến bất kỳ chuỗi byte nào thành một chuỗi ngắn duy nhất đáng tin cậy.
Vấn đề là vào thời điểm bạn có thể chạy một trong những phép biến đổi đó, bạn đã tạo biểu diễn
dưới dạng một chuỗi byte. Cuối cùng, bạn có thể tiết kiệm băng thông bằng cách không gửi biểu diễn
qua đường dây, nhưng bạn đã hoàn thành công việc cần thiết để xây dựng nó. Việc sử dụng ETag để
tiết kiệm thời gian, thay vì băng thông, yêu cầu bạn lưu vào bộ đệm ETag của một biểu diễn và vô
Last -Modified hoặc ETag sẽ cung cấp cho bạn sự hỗ trợ cho các yêu cầu có điều kiện, nhưng việc
kiện được thiết kế để ngăn máy chủ gửi các đại diện khổng lồ đến máy khách đã có chúng. Một tính
năng khác của HTTP, ít được sử dụng hơn, có thể giúp máy khách không phải gửi các đại diện khổng
Không có tên chính thức cho loại yêu cầu này, vì vậy Dịch vụ web RESTful ban đầu đã giới thiệu
một cái tên ngớ ngẩn—yêu cầu xem trước khi nhảy—dường như đã bị mắc kẹt.
Để thực hiện yêu cầu LBYL, khách hàng sẽ gửi yêu cầu không an toàn, chẳng hạn như PUT, bỏ qua nội
dung thực thể. Máy khách đặt tiêu đề yêu cầu Expect thành chuỗi ký tự 100- continue. Đây là một yêu
Đây không phải là một yêu cầu PUT thực sự: đó là câu hỏi về một yêu cầu PUT có thể xảy ra trong tương
lai. Máy khách đang hỏi máy chủ: “bạn có cho phép tôi ĐƯA một bản trình bày mới vào /filestore/
myfile.txt không? Máy chủ đưa ra quyết định dựa trên trạng thái hiện tại của tài nguyên đó và các
tiêu đề HTTP do máy khách cung cấp. Trong trường hợp này, máy chủ sẽ kiểm tra Độ dài nội dung và
quyết định xem nó có sẵn sàng chấp nhận tệp 500 MB hay không.
Nếu câu trả lời là có, máy chủ sẽ gửi mã trạng thái 100 (Tiếp tục). Sau đó, khách hàng dự kiến sẽ
gửi lại yêu cầu PUT, bỏ qua Kỳ vọng và bao gồm phần trình bày 500 MB trong phần nội dung thực thể.
Nếu câu trả lời là không, máy chủ sẽ gửi mã trạng thái 417 (Không đạt kỳ vọng). Câu trả lời có thể
là không vì tài nguyên tại /filestore/myfile.txt được bảo vệ chống ghi, vì khách hàng không cung cấp
thông tin xác thực phù hợp hoặc vì 500 MB là quá lớn. Dù lý do là gì đi nữa, yêu cầu xem trước khi
nhảy ban đầu đã giúp khách hàng không phải gửi 500 MB dữ liệu để rồi bị từ chối dữ liệu đó. Cả máy
Tất nhiên, một khách hàng có phần trình bày không tốt có thể nói dối về điều đó trong các tiêu đề chỉ
để nhận được mã trạng thái là 100, nhưng điều đó sẽ chẳng mang lại lợi ích gì. Máy chủ sẽ không chấp
nhận nội dung trình bày không hợp lệ trong yêu cầu thứ hai, nhiều hơn những gì nó có trong yêu cầu
đầu tiên. Quá trình tải lên lớn của khách hàng có thể sẽ bị gián đoạn bởi mã phản hồi 413 (Thực thể
văn bản như tài liệu JSON và XML có thể được nén thành một phần kích thước ban đầu của chúng. Thư
viện máy khách HTTP có thể yêu cầu phiên bản nén của biểu diễn và sau đó giải nén nó một cách minh
Đây là cách nó hoạt động. Khi máy khách gửi yêu cầu, nó sẽ bao gồm tiêu đề Accept-Encoding cho biết
thuật toán nén nào máy khách hiểu được. IANA lưu giữ sổ đăng ký các giá trị được chấp nhận tại trang
IANA này (đó là danh sách “mã hóa nội dung”), nhưng giá trị bạn muốn sử dụng là gzip:
Nếu máy chủ hiểu một trong các thuật toán nén được đề cập trong Mã hóa chấp nhận, nó có thể
sử dụng thuật toán đó để nén biểu diễn trước khi phân phát.
Máy chủ gửi cùng một Loại nội dung mà nó sẽ gửi nếu phần trình bày không được nén. Nhưng nó
cũng gửi tiêu đề Mã hóa nội dung để khách hàng biết tài liệu đã được nén:
HTTP/1.1 200 OK
Loại nội dung: text/html Mã
hóa nội dung: gzip
Máy khách giải nén dữ liệu bằng thuật toán được cung cấp trong Mã hóa nội dung, sau đó coi dữ
liệu đó là loại phương tiện được cung cấp dưới dạng Loại nội dung. Trong trường hợp này, máy
khách sẽ sử dụng thuật toán gzip để giải nén dữ liệu nhị phân trở lại tài liệu HTML. Đối với
khách hàng, nó đã yêu cầu HTML và nó nhận được HTML. Kỹ thuật này có thể tiết kiệm rất nhiều
băng thông với chi phí rất thấp và độ phức tạp tăng thêm.
HTTP một phần GET cho phép máy khách chỉ tìm nạp một tập hợp con của biểu diễn. Nó thường được
sử dụng để tiếp tục tải xuống bị gián đoạn. Hầu hết các máy chủ web đều hỗ trợ GET một phần cho
nội dung tĩnh. Nếu API của bạn phục vụ các tệp tĩnh lớn thì bạn nên nỗ lực hỗ trợ GET một phần
trên chúng.
Tài nguyên hỗ trợ GET một phần sẽ quảng cáo thực tế này để phản hồi GET thông thường, bằng cách
đặt tiêu đề phản hồi Phạm vi chấp nhận thành byte chuỗi ký tự . Đây là phản hồi cho yêu cầu GET
HTTP/1.1 200 OK Độ
dài nội dung: 1271174395 Phạm vi
chấp nhận: byte Loại nội
dung: video/mpeg
Nếu quá trình tải xuống bị gián đoạn, máy khách hỗ trợ GET một phần có thể tiếp tục tải xuống
từ điểm bị gián đoạn, thay vì bắt đầu lại. Đây là yêu cầu cho kilobyte cuối cùng của tệp video
đó:
Về lý thuyết, GET một phần có thể được sử dụng để chia một biểu diễn không thành các đoạn byte mà
thành các phần logic . Trong thế giới giả tưởng này, tiêu đề Phạm vi chấp nhận sẽ có giá trị khác
ngoài byte và tiêu đề Phạm vi sẽ được sử dụng để truy xuất, giả sử, các mục từ 2 đến 5 của bộ sưu
tập.
Đây là một ý tưởng hay, nhưng không có tiêu chuẩn nào trong lĩnh vực này và tôi thường phản đối
việc tạo ra ngữ nghĩa giao thức của riêng bạn. Nếu bạn muốn chia nhỏ một bộ sưu tập để có được một
số yêu cầu HTTP để có được toàn bộ nội dung, bạn nên tạo một số tài nguyên “trang” và liên kết các
phần trình bày của chúng với nhau bằng cách sử dụng các mối quan hệ liên kết đã đăng ký IANA như
next và previous .
Pipeline
Pipeline giảm độ trễ bằng cách cho phép máy khách gửi nhiều yêu cầu HTTP cùng một lúc.
Máy chủ gửi lại phản hồi từ máy chủ theo thứ tự nhận được yêu cầu.
Đường ống phụ thuộc vào, nhưng khác với các kết nối liên tục, một tính năng của HTTP cho phép khách
hàng gửi một số yêu cầu qua một kết nối TCP.
Máy khách có thể dẫn bất kỳ chuỗi yêu cầu HTTP bình thường nào, miễn là toàn bộ chuỗi đó cũng bình
thường. Nếu kết nối bị gián đoạn, bạn phải có khả năng phát lại toàn bộ loạt phim và nhận được kết
Đây là một ví dụ đơn giản. Tôi sẽ gửi hai yêu cầu qua một đường dẫn. Đầu tiên tôi sẽ truy xuất bản
trình bày của một tài nguyên và sau đó tôi sẽ xóa tài nguyên đó:
GET và DELETE là bình thường, nhưng sự kết hợp của chúng thì không. Nếu xảy ra sự cố mạng sau khi
tôi gửi những yêu cầu này và tôi không nhận được phản hồi đầu tiên trong quy trình, thì tôi sẽ
không thể gửi lại yêu cầu và nhận được kết quả tương tự. Tài nguyên sẽ không còn ở đó nữa. Do sự
phức tạp này, tôi chỉ khuyên bạn nên tạo đường dẫn cho các chuỗi yêu cầu GET.
Ngoài sự phức tạp đó, việc tạo đường ống thường xuyên không giúp ích gì cho hiệu suất. Pipeline chỉ
mang lại hiệu quả nếu khách hàng thực hiện một loạt yêu cầu HTTP dài tới cùng một tên miền và hầu
hết các trang web đều bao gồm các thành phần từ các tên miền khác nhau.
Các máy khách API không phải trình duyệt có xu hướng thực hiện một loạt yêu cầu dài tới một miền
duy nhất, nhưng việc tạo đường ống cũng không thực sự hữu ích đối với các API dựa trên hypermedia
vì API hypermedia thường yêu cầu máy khách kiểm tra phản hồi cho một yêu cầu trước khi thực hiện
một yêu cầu khác. . Có lẽ đó là lý do tại sao hầu hết các thư viện máy khách HTTP có thể lập trình
Về cơ bản, tính năng này giống như một sự phá sản. Giao thức HTTP 2.0 (được đề cập trong phần cuối của chương
này) sẽ triển khai đường dẫn HTTP theo cách hữu ích hơn. Như vậy, việc tạo đường ống có thể hữu ích cho một ứng
dụng khách như người tạo bản đồ của Chương 5 hoặc một ứng dụng khách chạy trên thiết bị di động có độ trễ cao.
Đây không phải là điều bắt buộc phải có như GET có điều kiện, nhưng khi bạn đang nghĩ đến việc cải thiện hiệu
suất, thì việc tạo đường dẫn rất đáng để xem xét. Tuy nhiên, đó là khuyến nghị cao nhất mà tôi có thể đưa ra.
GET. Nhưng các yêu cầu có điều kiện cũng hữu ích như một cách tránh mất dữ liệu khi sử dụng các phương thức HTTP
Giả sử Alice và Bob đang sử dụng các ứng dụng khách API khác nhau để chỉnh sửa danh sách tạp hóa. Họ bắt đầu bằng
cách thực hiện các yêu cầu HTTP giống hệt nhau:
HTTP/1.1 200 OK
Loại nội dung: text/plain ETag:
"7359b7-a37c-45b333d7"
Sửa đổi lần cuối: Thứ Hai, ngày 27 tháng 1 năm 2013 07:57:10 GMT
mì ống
bánh mì tròn
Alice thêm một mục vào danh sách và PUT quay lại biểu diễn mới:
mì ống
bánh mì tròn
Trứng
Bob, không biết Alice đang làm gì, thêm một mục vào danh sách và PUT trả lại cách trình bày mới của anh ấy :
mì ống
bánh mì tròn
Sữa
Bob cũng nhận được phản hồi là 200 (OK). Nhưng phiên bản danh sách của Alice—phiên bản bao gồm
“Trứng”—đã bị thất lạc. Bob thậm chí còn chưa bao giờ biết về phiên bản đó.
Loại bi kịch này có thể tránh được bằng cách đưa ra các yêu cầu không an toàn có điều kiện.
Với GET có điều kiện, chúng tôi muốn yêu cầu chỉ được thực hiện nếu cách biểu diễn đã thay
đổi. Ở đây, Bob muốn yêu cầu PUT của mình chỉ được thực hiện nếu cách trình bày không thay
đổi. Kỹ thuật giống nhau nhưng điều kiện bị đảo ngược. Thay vì If-Match, máy khách sử dụng
tiêu đề ngược lại, If-None-Match. Thay vì If-Modified-Since, máy khách sử dụng If-Unmodified-
Since.
mì ống
bánh mì tròn
Sữa
Thay vì 200 (OK), máy chủ sẽ gửi mã trạng thái 412 (Điều kiện tiên quyết không thành công).
Khi đó khách hàng của Bob sẽ biết rằng ai đó đã sửa đổi danh sách hàng tạp hóa.
Thay vì ghi đè lên bản trình bày hiện tại, máy khách của Bob có thể gửi yêu cầu GET cho bản
trình bày mới và cố gắng hợp nhất nó với phiên bản của Bob. Hoặc nó có thể leo thang vấn đề và
yêu cầu Bob tự mình giải quyết. Nó phụ thuộc vào loại phương tiện truyền thông và ứng dụng.
Theo tôi, việc triển khai API của bạn phải yêu cầu khách hàng thực hiện các yêu cầu PUT và
PATCH có điều kiện. Nếu khách hàng cố gắng thực hiện PUT hoặc PATCH vô điều kiện, bạn nên gửi
Xác thực
Để đơn giản, các ví dụ tôi trình bày xuyên suốt cuốn sách này không yêu cầu bất kỳ hình thức
xác thực nào. Bạn thực hiện một yêu cầu HTTP và nhận được phản hồi. Có rất nhiều API thực sự
như thế này, nhưng hầu hết các API đều yêu cầu xác thực.
Có hai bước để xác thực. Bước 1 là bước một lần trong đó người dùng thiết lập thông tin xác
thực của mình với nhà cung cấp dịch vụ. Thông thường, điều này có nghĩa là một người sử dụng
trình duyệt web của mình để tạo tài khoản trên máy chủ API hoặc liên kết một số tài khoản
người dùng hiện có trên một trang web với máy chủ API.
Bước 2 là trình bày tự động thông tin xác thực của người dùng cùng với từng yêu cầu tới API.
Tại sao phải trình bày thông tin xác thực của người dùng cùng với mọi yêu cầu HTTP? Do ràng buộc không
trạng thái, cho phép máy chủ hoàn toàn quên đi ứng dụng khách giữa các yêu cầu. Không có phiên nào trong
quá trình triển khai máy chủ RESTful.1 Một số kỹ thuật xác thực cũng bao gồm “bước
0” được gọi là đăng ký. Tại đây, nhà phát triển sử dụng trình duyệt web của mình để thiết lập thông tin
xác thực cho ứng dụng khách phần mềm mà cô ấy đang viết.
Nếu một nghìn người sử dụng ứng dụng khách đó thì mỗi người sẽ phải thiết lập thông tin xác thực người
dùng cá nhân của riêng mình (bước 1), nhưng tất cả họ sẽ chia sẻ một bộ thông tin xác thực ứng dụng
khách. Khi API áp dụng kỹ thuật này, ứng dụng khách muốn thực hiện yêu cầu HTTP phải xuất trình cả thông
tin xác thực ứng dụng khách và bộ thông tin xác thực người dùng.
Tôi sắp đề cập đến ba kỹ thuật xác thực phổ biến. Đầu tiên tôi sẽ nói về điểm chung của cả ba: tiêu đề
xác thực của HTTP.
Câu chuyện của chúng ta bắt đầu, giống như ở Chương 1, với nữ anh hùng Alice đưa ra một yêu cầu đơn giản
Nhưng lần này, máy chủ từ chối phục vụ đại diện được yêu cầu. Thay vào đó, nó phục vụ
một lỗi:
Mã phản hồi 401 là yêu cầu ủy quyền. Tiêu đề WWW-Authenticate giải thích loại ủy quyền nào mà máy chủ sẽ
chấp nhận. Trong trường hợp này, máy chủ muốn máy khách sử dụng xác thực HTTP Basic.
Alice cần có được một số thông tin xác thực… bằng cách nào đó. Các chi tiết phụ thuộc vào cơ chế xác
thực được sử dụng. Sau khi có được thông tin xác thực, cô ấy có thể thực hiện lại yêu cầu HTTP, gửi
thông tin xác thực của mình trong tiêu đề Yêu cầu ủy quyền :
GET / HTTP/1.1
Máy chủ: api.example.com
Ủy quyền: YWxpY2U6cGFzc3dvcmQ= Cơ bản
Lần này, người phục vụ hy vọng sẽ cung cấp cho Alice sự đại diện mà cô ấy yêu cầu.
1. Nếu bạn bỏ qua lời khuyên này và triển khai các phiên trong API của mình, ID phiên sẽ trở thành một loại thông tin xác
thực tạm thời, được cung cấp cùng với mọi yêu cầu. Tất cả những gì bạn đã làm là thêm một lớp phức tạp khác lên trên hệ
Xác thực HTTP Basic được mô tả trong RFC 2617. Đó là sơ đồ tên người dùng/mật khẩu đơn giản. Người
dùng API phải thiết lập trước tên người dùng và mật khẩu—có thể bằng cách đăng ký tài khoản trên một
trang web liên kết hoặc bằng cách gửi email yêu cầu tài khoản API. Không có tiêu chuẩn nào về cách
yêu cầu tên người dùng và mật khẩu cho một trang web nhất định.
Tuy nhiên, điều đó sẽ xảy ra, khi Alice có tên người dùng và mật khẩu, cô ấy có thể thực hiện lại
yêu cầu HTTP ban đầu đó. Lần này cô ấy sử dụng tên người dùng và mật khẩu của mình để tạo một giá
trị cho Ủy quyền tiêu đề yêu cầu , như đã thấy trong phần trước.
Máy chủ xác thực cô ấy, chấp nhận yêu cầu và đưa ra một đại diện thay vì
lỗi 401:
HTTP/1.1 200 OK
Loại nội dung: application/xhtml+xml
...
Auth cơ bản rất đơn giản nhưng nó có hai vấn đề lớn. Đầu tiên là nó không an toàn. YWx
pY2U6cGFzc3dvcmQ= trông giống như mã hóa vô nghĩa, nhưng thực ra nó là chuỗi alice:password chạy qua
một biến đổi đơn giản, có thể đảo ngược được gọi là Base64.2. Điều này có nghĩa là bất kỳ ai theo
dõi kết nối Internet của Alice đều biết mật khẩu của cô ấy. Họ có thể mạo danh Alice bằng cách gửi
các yêu cầu HTTP bao gồm Ủy quyền: YWx pY2U6cGFzc3dvcmQ= cơ bản.
Sự cố này sẽ biến mất nếu API sử dụng HTTPS thay vì HTTP đơn giản. Ai đó theo dõi kết nối Internet
của Alice sẽ thấy cô ấy mở kết nối, nhưng yêu cầu và phản hồi sẽ được mã hóa bởi lớp SSL.
RFC 2617 xác định phương thức xác thực thứ hai có tên là Digest, phương pháp này tránh được sự cố
này ngay cả khi không sử dụng HTTPS. Tôi sẽ không đề cập đến Digest trong cuốn sách này vì Digest và
Basic có chung một vấn đề thứ hai , vấn đề này không phải là vấn đề lớn trên World Wide Web nhưng
lại rất nghiêm trọng trong thế giới API: những người sử dụng API thường không thể tin tưởng khách
hàng của họ.
Để làm rõ vấn đề, hãy tưởng tượng một API rất phổ biến như API Twitter. API này phổ biến đến mức
Alice đang sử dụng 10 ứng dụng khách khác nhau cho một API này. Có một số trên điện thoại di động
của cô ấy, một số trên máy tính để bàn của cô ấy và cô ấy đã cấp phép cho một số trang web khác nhau
để thay mặt cô ấy sử dụng API này. (Việc này xảy ra mọi lúc.)
Mười khách hàng khác nhau. Điều gì xảy ra khi một trong những khách hàng lừa đảo và bắt đầu đăng thư
rác vào tài khoản của Alice? (Điều này cũng xảy ra thường xuyên.)
2. Base64 được định nghĩa trong phần 6.8 của RFC 2045. Hầu hết các ngôn ngữ lập trình đều có triển khai Base64
trong thư viện tiêu chuẩn của họ.
Sau cuộc tấn công, Alice phải thay đổi mật khẩu của mình. Cô ấy phải làm điều này để khách hàng lừa đảo
không còn có thông tin xác thực hợp lệ. Nhưng cô ấy đã đưa cho cả 10 khách hàng cùng một mật khẩu. Chín
trong số khách hàng vẫn đáng tin cậy, nhưng việc thay đổi mật khẩu sẽ phá vỡ cả 10.
Sau khi thay đổi mật khẩu, Alice phải thông qua chín khách hàng tốt của mình và cho họ biết mật khẩu mới.
Nếu một trong chín khách hàng lừa đảo, cô ấy phải thay đổi mật khẩu một lần nữa và thông qua tám khách
hàng tốt, thông báo lại cho từng khách hàng về mật khẩu mới của mình.
Điều này sẽ không thành vấn đề nếu ngay từ đầu Alice có thể cung cấp cho mỗi khách hàng một bộ thông tin
OAuth 1.0
Theo OAuth, Alice cung cấp cho mỗi khách hàng một bộ thông tin xác thực riêng. Nếu cô ấy quyết định rằng
cô ấy không thích một trong những khách hàng, cô ấy sẽ thu hồi thông tin đăng nhập của khách hàng đó và
chín khách hàng còn lại không bị ảnh hưởng. Nếu một khách hàng lừa đảo và bắt đầu đăng thư rác dưới tên
của người dùng, nhà cung cấp dịch vụ có thể can thiệp và thu hồi thông tin xác thực đối với mọi phiên bản
Có hai phiên bản OAuth. OAuth 1.0 (được xác định trong RFC 5849) hoạt động tốt khi cho phép các nhà phát
triển trang web hướng tới người tiêu dùng tích hợp với API của bạn. Nó bắt đầu thất bại khi bạn muốn cho
phép tích hợp các ứng dụng trên máy tính để bàn, thiết bị di động hoặc trong trình duyệt với API của mình.
OAuth 2.0 rất giống với 1.0 nhưng nó xác định cách xử lý các tình huống này.
Tôi sẽ mô tả ngắn gọn các khái niệm đằng sau OAuth bằng OAuth 1.0 và chỉ cho bạn cuốn Bắt đầu với OAuth
2.0 của Ryan Boyd (O'Reilly) để có phần giải thích chi tiết, dễ đọc về OAuth 2.0.
Đây là mã phản hồi 401 trông như thế nào khi máy chủ muốn khách hàng cung cấp một bộ thông tin xác thực
OAuth:
Để có được những thông tin xác thực đó là một quá trình phức tạp. Giả sử Alice đang sử dụng một trang web,
YouTypeItWePostIt.com. Cô nhìn thấy một tùy chọn kiểm soát siêu phương tiện cho cô biết rằng cô có thể
tích hợp tài khoản của mình trên example.net với tài khoản của mình trên YouTypeItWePostIt.com. Cô ấy có
thể làm điều này mà không cần nói cho YouTypeItWePostIt.com mật khẩu của mình trên example.net (xem Hình
11-2).
Hình 11-2. YouTypeItWePostIt.com với lời nhắc đăng nhập qua example.net
Đây có vẻ là một ý tưởng hay đối với Alice, vì vậy cô ấy nhấp vào nút để kích hoạt điều khiển siêu phương
1. Máy chủ YouTypeItWePostIt.com bí mật yêu cầu một bộ thông tin xác thực tạm thời từ nhà cung cấp
API, api.example.net. Bước này hoàn toàn không yêu cầu sự tham gia của Alice.
2. Máy chủ YouTypeItWePostIt.com gửi chuyển hướng HTTP tới trình duyệt của Alice.
Alice rời khỏi trang web cô đang sử dụng và kết thúc trên một trang web do nhà cung cấp API,
Nếu Alice chưa đăng nhập vào example.net, cô ấy cần đăng nhập hoặc tạo tài khoản người dùng. Điều
này có nghĩa là nhập mật khẩu của cô ấy—nhưng lưu ý rằng cô ấy đang cung cấp mật khẩu Sample.net
3. Sau khi đăng nhập, Alice thấy một trang web được liên kết với thông tin xác thực tạm thời có được ở
bước 1. Văn bản mà con người có thể đọc được của trang này giải thích cho Alice chuyện gì đang xảy
ra và hỏi cô ấy xem cô ấy có muốn ủy quyền cho một bộ api không Thông tin xác thực mã thông
4. Alice đưa ra quyết định của mình và trình duyệt của cô ấy được chuyển hướng trở lại YouTypeItWePost-
5. a) Nếu Alice nói “không” ở bước 4, khách hàng đã không gặp may. Nó sẽ không nhận được gì
b) Nếu Alice nói “có” ở bước 4, khách hàng được phép trao đổi thông tin xác thực tạm thời có được
ở bước 1 để lấy một bộ thông tin xác thực mã thông báo thực. Những thông tin xác thực này có thể
được sử dụng để ký các yêu cầu HTTP bằng mật mã, tạo ra các tiêu đề Cấp phép giống như tiêu đề
GET / HTTP/1.1
Máy chủ: api.example.net
Ủy quyền: OAuth Realm="Example API",
oauth_consumer_key="rQLd1PciL0sc3wZ",
oauth_signature_method="HMAC-SHA1",
oauth_timestamp="1363723000",
oauth_nonce="JFI8Bq",
oauth_signature= "4HBjJvupgIYbeEy4kEOLS%Ydn6qyV%UY"
Tại thời điểm đó, khách hàng có thể sử dụng API bình thường như thể đó là Alice.
Hình 11-3. Ví dụ.net yêu cầu thông tin xác thực của Alice thay mặt cho YouTypeItWePos‐
tIt.com
Tùy thuộc vào API, thông tin xác thực mã thông báo có thể là vĩnh viễn hoặc chúng có thể tự động hết hạn sau
một thời gian. (Sau khi chúng hết hạn, khách hàng sẽ cần gửi lại Alice thực hiện quy trình này nếu muốn tiếp
tục sử dụng API.) Thông tin xác thực mã thông báo có thể cấp cho khách hàng quyền truy cập vào mọi thứ Alice có
thể thực hiện với API hoặc họ có thể chỉ cho phép một tập hợp con về những gì Alice có thể làm. (Một hạn chế
Đây chỉ là một số trong số những thứ không được chỉ định trong tiêu chuẩn OAuth và phải được nhà cung cấp API
xác định.
Bạn có thể thấy rằng OAuth phức tạp hơn nhiều so với HTTP Basic Auth, nhưng—tôi không thể nhấn mạnh điều này đủ
—nó giúp Alice không phải cung cấp mật khẩu của mình cho 10 phần mềm khác nhau mà cô ấy không tin tưởng. Sự
phức tạp của OAuth mang lại một số tính năng hữu ích khác:
• Nếu Alice không thích những gì khách hàng đang làm thay mặt cô ấy, cô ấy có thể thu hồi mã thông báo của nó
thông tin xác thực.
• Nếu nhà cung cấp API nhận thấy một phần mềm máy khách bị lừa đảo, nhà cung cấp có thể thu hồi thông tin xác thực
ứng dụng khách của mình. (Đó là oauth_consumer_key.) Điều này có nghĩa là API ngừng phân phát tất cả các bản sao
• Không giống như HTTP Basic (nhưng giống như HTTP Digest), OAuth 1.0 có thể được sử dụng trên HTTP không an toàn
mà không tiết lộ thông tin xác thực của Alice. Thông tin xác thực mã thông báo là cần thiết để tạo phần
oauth_signature của tiêu đề Ủy quyền , nhưng thông tin xác thực không thực sự xuất hiện ở bất kỳ đâu trong tiêu
đề đó. Máy chủ (cũng biết thông tin xác thực của Alice) có thể xác minh rằng yêu cầu đã được ký bởi thông tin
xác thực của Alice, nhưng ai đó theo dõi yêu cầu sẽ không thể biết thông tin xác thực của cô ấy là gì. • Các giá
trị oauth_timestamp và oauth_nonce trong tiêu đề Ủy quyền ngăn chặn “các cuộc tấn công lặp lại”,
trong đó kẻ tấn công theo dõi các yêu cầu của Alice, sau đó thực hiện các yêu cầu tương tự để mạo danh cô ấy. (Xác
OAuth 1.0 hoạt động tốt khi tất cả hành động diễn ra bên trong trình duyệt web của Alice. Điều gì sẽ xảy ra nếu Alice
đang sử dụng một ứng dụng dành cho máy tính để bàn?
Trong trường hợp đó, Alice cần tạm thời chuyển sang trình duyệt web của mình. Ở bước 2, thay vì chuyển hướng Alice đến
trang trên api.example.net, ứng dụng dành cho máy tính để bàn sẽ mở một cửa sổ trình duyệt mới được đặt cho trang đó.
Khi Alice đưa ra quyết định ở bước 4, sẽ không có nơi nào để api.example.net chuyển hướng cô ấy quay lại. Ở chế độ
nền, ứng dụng dành cho máy tính để bàn cần liên tục hỏi api.example.net xem Alice có ủy quyền (hoặc từ chối) thông tin
Đó là câu trả lời của OAuth 1.0 để tích hợp API vào ứng dụng máy tính để bàn mà không yêu cầu nhập tên người dùng/mật
khẩu. Sẽ hơi rắc rối một chút khi cửa sổ trình duyệt web đột nhiên bật lên khi bạn đang sử dụng một ứng dụng dành cho
máy tính để bàn, nhưng điều đó hoàn toàn có thể thực hiện được. Thật không may, có một số tình huống khác trong đó quy
trình năm bước mà tôi đã mô tả trước đây không hiệu quả hoặc hoàn toàn không hoạt động:
• Điều gì sẽ xảy ra nếu Alice đang sử dụng một ứng dụng trên điện thoại di động hoặc chơi trò chơi trên máy chơi
game? Sẽ rắc rối hơn nhiều khi đột nhiên bật lên một cửa sổ trình duyệt trên các thiết bị này. Nó thậm chí có
thể không thể. Một số thiết bị không có trình duyệt web. • Điều gì sẽ xảy ra nếu Alice là tác giả của
ứng dụng khách phần mềm api.example.net của riêng cô ấy? Liệu việc bắt cô ấy lấy thông tin đăng nhập tạm thời và
hỏi cô ấy xem cô ấy có muốn ủy quyền cho khách hàng của mình có thực sự hợp lý không?
• Điều gì sẽ xảy ra nếu Alice đang sử dụng một ứng dụng máy tính để bàn chạy bên trong trình duyệt web của cô ấy?
Thông tin xác thực tạm thời có thực sự cần thiết không? Ở bước 5, api.example.net không thể chỉ phân phát một
trang chứa mã thông báo truy cập thực và để ứng dụng trong trình duyệt đọc nó bằng mã JavaScript sao?
OAuth 2.0 được thiết kế để đáp ứng các trường hợp sử dụng này.
OAuth 2.0
OAuth 2.0 được xác định trong RFC 6749. Nó chỉ định bốn quy trình khác nhau để nhận mã thông báo truy cập
OAuth (một lần nữa, tôi sẽ không đi sâu vào chi tiết; hãy xem Bắt đầu với OAuth 2.0 để tìm hiểu thêm):
• Bằng cách cung cấp “mã ủy quyền” (mục 1.3.1 của RFC 6749). Đây là hệ thống tôi đã mô tả cho OAuth
1.0. “Chủ sở hữu tài nguyên” (Alice) xác thực bằng “máy chủ ủy quyền” (đăng nhập vào example.net),
máy chủ này chuyển hướng cô ấy đến “máy khách” (api.example.net), máy chủ này sẽ cung cấp mã thông
• Thông qua “khoản trợ cấp ngầm” (mục 1.3.2 của RFC 6749). Đây là một lựa chọn tốt cho một ứng dụng
chạy bên trong trình duyệt web của Alice. Sau khi Alice đăng nhập vào Sample.net, cô ấy được chuyển
hướng đến api.example.net, điều này sẽ chuyển hướng cô ấy đến một URL chứa mã thông báo truy cập.
Không cần phải có thông tin xác thực tạm thời; ứng dụng trong trình duyệt chỉ có thể đọc mã thông
• Thông qua “thông tin xác thực mật khẩu của chủ sở hữu tài nguyên” (phần 1.3.3 của RFC 6749). Nghĩa
là, Alice cung cấp tên người dùng và mật khẩu example.net của mình cho khách hàng, khách hàng sẽ
Đây chính xác là điều OAuth đang cố tránh: Alice tiết lộ mật khẩu của mình cho một khách hàng không
đáng tin cậy. Nhưng trên thiết bị di động hoặc máy chơi game thì không có giải pháp thay thế nào phù
hợp.
Tại thời điểm này, một khách hàng độc hại có thể đánh cắp mật khẩu của Alice. Nhưng một khách hàng
hợp pháp sẽ quên mật khẩu của Alice ngay khi nhận được mã thông báo truy cập OAuth. Điều này có
nghĩa là một khách hàng hợp pháp sẽ không bị hỏng nếu Alice thay đổi mật khẩu của mình vì những lý
do khác. • Thông qua “thông tin xác thực của khách hàng” (mục 1.3.4 của RFC 6749). Điều này sẽ tránh
được rất nhiều rắc rối khi Alice là tác giả của chính khách hàng của mình. Khi Alice đăng ký khách
hàng của mình với api.example.net, cô ấy tự động được cấp một bộ thông tin xác thực sẽ cấp cho khách
hàng quyền truy cập miễn phí vào tài khoản example.net của chính cô ấy .
Là nhà cung cấp API, bạn không cần phải triển khai cả bốn luồng ứng dụng này. Nếu bạn đang viết một API
để phục vụ như một chương trình phụ trợ cho một ứng dụng di động, bạn chỉ cần triển khai luồng “thông tin
xác thực mật khẩu của chủ sở hữu tài nguyên”. Nhưng nếu bạn muốn các bên thứ ba tích hợp ứng dụng khách
với API của mình, bạn sẽ cần triển khai luồng ứng dụng mà khách hàng của bạn muốn sử dụng.
vệ API của mình bằng cách sử dụng HTTP Basic hoặc HTTP Digest au‐
sự thúc giục. Tôi khuyên bạn nên kiên trì và tìm hiểu cách OAuth hoạt động. Nếu cần, hãy nghiên cứu
và sao chép cách triển khai của một nhà cung cấp OAuth tên tuổi như Facebook.
Ưu điểm cơ bản của OAuth—việc tách tên người dùng và mật khẩu example.net của Alice khỏi thông tin xác
thực api.example.net của cô ấy —là một tính năng thực sự quan trọng. Theo tôi, chỉ có hai trường hợp
• API của bạn là một trò giải trí phù phiếm. Nếu một khách hàng độc hại đánh cắp Alice
thông tin xác thực, nó không thể gây ra bất kỳ thiệt hại thực sự nào.
• Mỗi người dùng API của bạn sẽ viết ứng dụng khách của riêng mình. Khi đó, sẽ không có lợi ích bảo
mật nào khi tách Alice nhà phát triển khách hàng khỏi Alice người dùng cuối. Điều này có nghĩa
là khi Alice thay đổi mật khẩu của mình trên trang web, cô ấy cũng sẽ cần thay đổi mật khẩu của
mình trong tất cả các ứng dụng khách API của mình. Đây không phải là một vấn đề lớn.
Nếu bạn hiểu các vấn đề bảo mật, nhưng bạn không nghĩ API của mình sẽ trở nên đủ phổ biến để khiến các
ứng dụng khách độc hại trở thành vấn đề, thì bạn vẫn nên sử dụng OAuth.
Khi bạn bắt đầu sử dụng HTTP Basic, rất khó để chuyển tất cả ứng dụng khách của bạn sang OAuth.
Theo định nghĩa, khá nhiều API web dựa trên giao thức HTTP. Nhưng các khái niệm cơ bản của REST không
yêu cầu HTTP, cũng như ràng buộc siêu phương tiện yêu cầu bạn cung cấp các biểu diễn HTML.
Có hai phần mở rộng cho HTTP xác định các phương thức mới cụ thể để sử dụng trong API và ba giao thức
chính lấy HTTP làm điểm bắt đầu. Một trong những giao thức đó, CoAP, khác thường đến mức tôi dành cả
một chương (Chương 13) cho nó. WebDAV và HTTP 2.0 dựa chặt chẽ vào HTTP, vì vậy tôi sẽ trình bày chúng
• Được định nghĩa trong: RFC 5789 và các tiêu chuẩn khác
• Ngữ nghĩa giao thức: không an toàn cũng không bình thường
Tôi đã trình bày phương pháp này trong Chương 3 như một phần của bộ công cụ được đề xuất dành cho các nhà phát triển API.
Phương thức PATCH giải quyết vấn đề hiệu suất với HTTP PUT. PUT thay thế toàn bộ biểu diễn của tài
nguyên bằng một biểu diễn mới, có nghĩa là máy khách phải gửi lại
3. Khi API Twitter chuyển từ Xác thực cơ bản sang OAuth vào năm 2010, các nhà phát triển đã gọi sự kiện này là “OAuth‐
toàn bộ sự thể hiện ngay cả khi nó chỉ thực hiện một thay đổi nhỏ. Phương thức PATCH cho phép
Nhược điểm của phương pháp PATCH là máy khách và máy chủ phải thống nhất về loại phương tiện mới
cho các tài liệu vá lỗi. May mắn thay, bạn không cần phải tự mình nghĩ ra định dạng này. RFC 6902
xác định định dạng bản vá tiêu chuẩn cho JSON và đăng ký loại phương tiện application/json-patch
cho các tài liệu ở định dạng đó. RFC 5261 xác định định dạng bản vá cho tài liệu XML và “dự thảo-
wilde-xml-patch” Internet-Draft đăng ký loại phương tiện application /xml-patch+xml cho tài liệu ở
• Được định nghĩa trong: Internet-Draft “phương thức liên kết snell”
Phương thức LINK tạo kết nối giữa hai tài nguyên. Có lẽ, khi tài nguyên A được liên kết với tài
nguyên B, một liên kết hypermedia tới B sẽ bắt đầu hiển thị trong các biểu diễn của A.
Nhưng liên kết được tạo ra như thế nào? Làm cách nào một yêu cầu HTTP có thể tham chiếu đến hai tài nguyên khác nhau?
Tất nhiên, bằng cách bao gồm cả hypermedia. Yêu cầu LINK hoặc UNLINK được gửi đến URL của tài
nguyên A và tài nguyên B được đề cập trong tiêu đề Liên kết . Mối quan hệ liên kết được liên kết
Đây là yêu cầu thêm một mục hiện có vào bộ sưu tập (đó là trường hợp sử dụng phổ biến cho mẫu bộ
sưu tập nhưng nó không được xác định trong AtomPub hoặc Collection+JSON):
Đây là yêu cầu xóa tài nguyên thứ hai khỏi chuỗi tài nguyên:
kết: <http://www.example.com/story/part2>;rel="next"
Sau khi yêu cầu này được thực hiện, các tài nguyên tại /story/part1 và /story/part2 vẫn tồn tại.
Chỉ là không còn mối liên kết nào giữa chúng mà mối quan hệ liên kết là “tiếp theo”. Có lẽ /story/
Những phương pháp này không cần thiết về mặt kỹ thuật. Bạn có thể sao chép chức năng của chúng
bằng PUT. Nhưng họ đơn giản hóa mọi thứ. Họ chia ra một hoạt động chung—thao tác các liên kết siêu
phương tiện giữa các tài nguyên—và đặt cho nó ngữ nghĩa giao thức riêng.
Trong Chương 3, tôi đã đề cập rằng từ năm 1997 đến năm 1999, các phương thức này là một phần tiêu
chuẩn của HTTP. RFC 2616 đã xóa chúng vì không rõ lý do và cách thức thực hiện
được dùng. Với sự phát triển của API web và sự ra đời của tiêu đề Liên kết , điều này rõ ràng hơn rất
nhiều.
Điều duy nhất ngăn cản tôi khuyến nghị sử dụng LINK và UNLINK là thực tế là Bản nháp Internet mô tả chúng
WebDAV
• Được định nghĩa trong: RFC 4918 và các tiêu chuẩn khác
• Ngữ nghĩa giao thức: Hoạt động của hệ thống tập tin
Mục tiêu của WebDAV là giúp dễ dàng xuất bản tài nguyên HTTP cho các tệp và thư mục trên hệ thống tệp từ
xa. WebDAV định nghĩa rất nhiều phương thức HTTP mới và các phần mở rộng khác đến mức nó gần như có thể
Các ứng dụng phổ biến nhất của WebDAV là Sharepoint của Microsoft và hệ thống kiểm soát phiên bản
Subversion. Chúng tôi thực sự không coi chúng là API và hầu hết các API hoạt động giống như hệ thống tệp
Chúng là các tiêu chuẩn fiat sử dụng các phương thức HTTP tiêu chuẩn như PUT và phân phát siêu dữ liệu
bằng cách sử dụng các biểu diễn XML hoặc JSON đặc biệt. Nói cách khác, chúng trông giống như các API khác
ngày nay.
Giống như AtomPub, WebDAV là một tiêu chuẩn mở bị nhiều người bỏ qua vì nó không phù hợp với những ý
tưởng hiện đại về giao diện của một API. Tuy nhiên, việc hiểu WebDAV vẫn hữu ích vì đây là công ty tiên
phong đầu tiên trong lĩnh vực API. Dưới đây là một số tính năng thú vị hơn của WebDAV.
• WebDAV triển khai mẫu bộ sưu tập (Chương 6) bằng cách xác định các tài nguyên “bộ sưu tập” hoạt động
giống như các thư mục trên hệ thống tệp cục bộ. Các tài nguyên này phản hồi GET và DELETE. WebDAV
cũng xác định một phương thức HTTP hoàn toàn mới, MKCOL, tạo ra một bộ sưu tập mới.
Máy khách tải tệp lên bằng cách gửi yêu cầu PUT tới bất kỳ URL nào nó chọn cho tài nguyên mới. RFC
5995 là một tiện ích mở rộng cho phép khách hàng tải lên các tệp mới bằng cách sử dụng POST để nối
thêm. Trong trường hợp đó, máy chủ chọn URL của tài nguyên mới chứ không phải máy khách.
• Một tệp trên hệ thống tệp cục bộ của bạn chứa dữ liệu nhưng nó cũng có siêu dữ liệu liên quan: tên
tệp, ngày tạo tệp, v.v. Tài nguyên WebDAV thể hiện siêu dữ liệu này dưới dạng “thuộc tính” như tên
WebDAV định nghĩa phương thức HTTP PROPPATCH để sửa đổi các thuộc tính của tài nguyên và phương thức
PROPFIND để tìm kiếm bộ sưu tập nhằm tìm ra các tài nguyên có thuộc tính nhất định.
• WebDAV cho phép máy khách khóa tài nguyên một cách rõ ràng (sử dụng các phương thức HTTP mới LOCK
và UNLOCK) để các máy khách khác không thể truy cập được. Điều này có thể được sử dụng với các kỹ
thuật mà tôi đã mô tả trước đó trong chương này để tránh vấn đề mất bản cập nhật. • WebDAV
định nghĩa các phương thức HTTP mới MOVE và COPY. Chúng hoạt động giống như các hoạt động hệ thống
tập tin tương đương. MOVE thay đổi URL của tài nguyên và COPY đưa ra một bản sao đại diện hiện tại
WebDAV cũng xác định một điều khiển siêu phương tiện mới cho các phương thức này: tiêu đề yêu cầu
Đích . Tiêu đề này chứa URL mới của tài nguyên hoặc URL để sử dụng cho bản sao. So sánh tiêu đề
Yêu cầu liên kết , như được sử dụng với các phương thức LINK và UNLINK.
• WebDAV xác định năm mã trạng thái HTTP mới, bao gồm một số mã có thể trông hấp dẫn ngay cả khi bạn
không sử dụng WebDAV, như 423 (Đã khóa) và 507 (Không đủ bộ nhớ). Nhưng tôi không khuyên bạn nên
sử dụng các tính năng WebDAV bên ngoài Web-DAV. Thay vào đó hãy quay lại mã trạng thái tiêu chuẩn.
Bạn có thể sử dụng 409 (Xung đột) thay vì 423 (Đã khóa) và cung cấp ngữ cảnh bổ sung trong tài
HTTP 2.0
HTTP 2.0 là phiên bản kế thừa của HTTP hiện tại được xác định trong RFC 2616 và các RFC thay thế của
nó. HTTP 2.0 dựa trên SPDY, một tiêu chuẩn công ty do Google xác định nhằm bổ sung lớp hiệu suất bên
trên HTTP. Hầu hết các trình duyệt web hiện nay đều hỗ trợ SPDY và nhiều trang web lớn cung cấp dữ liệu
Mục tiêu của HTTP 2.0 là cải thiện hiệu suất của HTTP trong khi vẫn duy trì ngữ nghĩa giao thức của nó.
Bất chấp cái tên hoành tráng của nó, HTTP 2.0 sẽ không mang đến các tính năng mới làm lung lay nền tảng
thiết kế API. Cho dù bạn đang phát triển API, ứng dụng khách API hay trang web, bạn đều có thể giả vờ
như mình đang sử dụng HTTP 1.1 và để lớp tương thích tự động chuyển đổi giữa HTTP 1.1 và 2.0.
Khi tôi viết bài này, vẫn còn quá sớm trong quá trình phát triển để nói chính xác HTTP 2.0 sẽ hoạt động
như thế nào. Nó có thể trông không giống SPDY. Nhưng nó cần giải quyết các vấn đề mà SPDY giải quyết,
• HTTP 2.0 sẽ tiết kiệm băng thông bằng cách nén các tiêu đề HTTP, điều này không làm được
• Máy khách HTTP 2.0 sẽ có thể gửi nhiều yêu cầu đồng thời (“luồng”) đến máy chủ qua một kết nối
của HTTP 1.1, nhưng như tôi đã đề cập trước đó, việc tạo đường dẫn không giúp ích nhiều
cho hiệu suất. HTTP 2.0 cần bao gồm một tính năng giống như đường ống thực sự hoạt động.
Những cải tiến kỹ thuật này sẽ có tác động tích cực lớn đến thiết kế API. Chúng sẽ loại bỏ nhu
cầu về một tập hợp chung các mẫu thiết kế API giúp cải thiện hiệu suất bằng cách kết hợp các
yêu cầu lại với nhau.4 Các mẫu này cho phép khách hàng tìm nạp (hoặc cập nhật) các biểu diễn
của nhiều tài nguyên bằng một yêu cầu HTTP duy nhất. Không có cách tiêu chuẩn nào để đóng gói
các “yêu cầu ảo” này lại với nhau, nhưng làm như vậy sẽ tiết kiệm rất nhiều thời gian vì mọi
yêu cầu HTTP 1.1 đều có chi phí thiết lập lớn.
HTTP 2.0 sẽ loại bỏ chi phí thiết lập đó. Thực hiện 20 yêu cầu HTTP và nhận được 20 phản hồi
sẽ nhanh gần như thực hiện một yêu cầu lớn và nhận được một phản hồi lớn.
Sẽ không còn nhu cầu API có các tính năng hàng loạt đặc biệt nữa.
4. Để có giải thích rõ ràng về các mẫu này, hãy xem Chương 11 của Sách dạy nấu ăn về dịch vụ web RESTful (O'Reilly).
CHƯƠNG 12
Các định dạng dữ liệu tôi đề cập trong cuốn sách này chủ yếu được sử dụng để cho phép các
nguồn tài liệu nói về chính chúng. Nghĩa là, khách hàng gửi yêu cầu GET tới URL của tài
nguyên và nhận được bản trình bày của chính tài nguyên đó. Tôi gọi đây là chiến lược đại diện
egy.
Nhưng sự thể hiện của tài nguyên A cũng có thể nói lên điều gì đó về tài nguyên B.
Tài liệu Collection+JSON đơn giản này là sự thể hiện của một tài nguyên (một bộ sưu tập)
nhưng nó có điều gì đó để nói về hai tài nguyên khác (các mục trong bộ sưu tập):
"mặt hàng" : [
] },
] }
]
}
}
Tôi gọi đây là chiến lược mô tả. Với chiến lược mô tả, phần trình bày dành phần lớn thời
gian để nói về các tài nguyên khác ngoài tài nguyên mà nó đại diện.
263
Machine Translated by Google
Tất cả các định dạng hypermedia đều kết hợp các chiến lược trình bày và mô tả ở một mức độ nào
đó, nhưng có một nhóm định dạng tập trung chủ yếu vào chiến lược mô tả: các định dạng lấy cảm
hứng từ mô hình dữ liệu Khung mô tả tài nguyên (RDF) và liên kết với phong trào Web ngữ nghĩa. .
Tôi đã không đề cập đến các định dạng này trong Chương 10 bởi vì, theo quan điểm REST, chúng kỳ
lạ. Chiến lược mô tả thuần túy vi phạm các ràng buộc Fielding. Các tài liệu RDF thường mô tả các
tài nguyên mà từ góc độ REST là “không tồn tại”. Để hiểu những tài liệu này đang nói về điều gì,
May mắn thay, phong trào Web ngữ nghĩa làn sóng thứ hai có tên là Dữ liệu liên kết nhằm mục đích
tái tập trung RDF vào chiến lược biểu diễn. Đây là một tin tuyệt vời vì có một số định dạng dữ
liệu hữu ích bắt nguồn từ RDF và một ngôn ngữ rất mạnh để tạo các cấu hình máy có thể đọc được:
Lược đồ RDF.
Nhưng trước khi tôi chuyển sang Dữ liệu được Liên kết, bạn cần hiểu RDF. Mọi thứ trong chương
này đều dựa trên, lấy cảm hứng từ hoặc được thiết kế để phản ứng với mô hình dữ liệu RDF. Bạn
cần hiểu tài liệu RDF trông như thế nào, ý nghĩa của chúng và tại sao ngay từ đầu phong trào Dữ
RDF
• Các loại phương tiện: ứng dụng/rdf+xml, văn bản/rùa, v.v. •
Được xác định trong: Các tiêu chuẩn mở W3C, được xác định tại đây và đáng
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:maze="http://alps.io/example/maze#">
<rdf:Description about="http://example.com/cells/M">
<maze:title>Hành lang vào</maze :title>
<maze:east Resource="http://example.com/cells/N">
<maze:west Resource="http://example.com/cells/L">
</rdf:Description>
< /rdf:RDF>
Có nhiều cách viết RDF, bao gồm phiên bản HTML có tên RDFa và phiên bản văn bản thuần túy có tên
Turtle. Bạn vừa thấy phiên bản XML, được gọi là RDF+XML.
<http://example.com/cells/M> <http://alps.io/example/maze#title>
"Hành lang vào" .
<http://example.com/cells/M> <http://alps.io/example/maze#east>
<http://example.com/cells/N> .
<http://example.com/cells/M> <http://alps.io/example/maze#west> <http://
example.com/cells/L> .
Thiết lập một số phím tắt Rùa và bạn có thể biểu thị cùng một thông tin theo cách gọn gàng hơn:
Cả ba tài liệu này đều mô tả cùng một tài nguyên: tài liệu có URI http://example.com/cells/M.
Trong RDF+XML, URI được mô tả sẽ đi vào thuộc tính about của thẻ <Description> . Trong Turtle,
URI đó nằm ở đầu dòng, trong dấu ngoặc nhọn. (Giống như cách tiêu đề Liên kết HTTP đặt URL
Mỗi tài liệu này đều đưa ra những xác nhận giống nhau về tài nguyên mà nó mô tả.
Mỗi người đều nói rằng tài nguyên có một thuộc tính được gọi là http://alps.io/example/
maze#title, với giá trị của thuộc tính này là chuỗi ký tự Hành lang lối vào.
Mỗi tài liệu cũng nói rằng tài nguyên có hai thuộc tính được gọi là http://alps.io/ example/
maze#east và http://alps.io/example/maze#west. Các thuộc tính này hoạt động giống như các mối
quan hệ liên kết mở rộng. Giá trị của chúng là URI (chẳng hạn như http://example.com/cell/L).
Họ giải thích mối quan hệ giữa tài nguyên ở phía bên phải của thuộc tính và tài nguyên ở phía
bên trái:
Dịch theo thuật ngữ của con người thì câu nói đó của Rùa là “ô L nằm ở phía tây ô M”.
RDF cung cấp cho bạn một khuôn khổ để nói về ngữ nghĩa ứng dụng của tài nguyên. Bạn có thể nói
về các mối quan hệ liên kết kết nối một tài nguyên với tài nguyên khác và các bộ mô tả ngữ
nghĩa liên kết nó với trạng thái tài nguyên của chính nó. Nhưng không giống như các định dạng
khác, thuộc tính RDF không thể là các chuỗi ngắn như “title” và “east”. Chúng chỉ có thể là
URI, như http://Alps.io/example/maze#title và http://alps.io/example/maze#east. Bạn có thể sử
dụng tiền tố Turtle và không gian tên XML để rút ngắn các URI thành maze:title và maze:east,
Trong thế giới REST, câu hỏi này đã có câu trả lời rõ ràng. Một http: URL xác định một tài
nguyên trên Web và nếu bạn gửi yêu cầu GET tới URL đó, bạn sẽ nhận được một thông báo thể hiện
trạng thái của tài nguyên.
RDF | 265
Machine Translated by Google
Nếu bạn gửi yêu cầu GET tới http://alps.io/example/maze, bạn sẽ nhận được tài liệu ALPS.
Tra cứu “phía đông” và “tiêu đề” trong tài liệu đó và bạn sẽ nhận được những lời giải thích mà con người có thể đọc được.
Điều này không đủ để tự mình thu hẹp khoảng cách ngữ nghĩa, nhưng nếu ứng dụng khách tự động của bạn gặp
khó khăn do không hiểu điều gì đó thì bạn, với tư cách là nhà phát triển, sẽ biết phải đi đâu để khắc
phục sự cố.
Nhưng RDF không coi URL là URL. Nó coi chúng như các URI, một thuật ngữ mà tôi chưa đề cập nhiều kể từ
Chương 4. URI xác định một tài nguyên, giống như một URL, nhưng không có gì đảm bảo rằng bạn có thể sử
dụng máy tính để có được sự thể hiện của tài nguyên đó. Đây là lý do tại sao tôi đã hạ thấp tầm quan
trọng của URI trong suốt cuốn sách này. Như tôi đã nói trong Chương 4, việc xác định tài nguyên của bạn
bằng URI khiến bạn không thể đáp ứng nhiều ràng buộc Fielding.
Nhưng tôi đã sử dụng http: URI trong tài liệu RDF của mình. Đó là những URL. Vậy là tôi an toàn rồi phải
không? Thực ra là không, tôi không an toàn. Đối với RDF, ngay cả http: URL cũng không là gì ngoài URI.
URI http://example.com/cells/N có thể trông hấp dẫn, nhưng từ góc độ RDF, không có gì đảm bảo rằng việc
thực hiện yêu cầu GET tới URI đó sẽ mang lại cho bạn sự đại diện. Máy khách RDF có thể dùng thử và xem
điều gì xảy ra, nhưng không được phép cho rằng điều gì đó sẽ xảy ra.
Nếu bạn đã gửi yêu cầu HTTP GET tới http://example.com/cells/M và nhận lại một trong các tài liệu RDF
này, chúng tôi sẽ nói rằng bạn đã có "bản trình bày" của tài nguyên tại http:// example.com /ô/M. Nhưng
trong thực tế, nếu bạn gửi yêu cầu GET đó, bạn sẽ gặp lỗi 404. http://example.com/cells/M là một tưởng
tượng, một URI mẫu mà tôi đã tạo ra cho mục đích của cuốn sách này. Vì vậy, chúng tôi không thể nói rằng
các tài liệu RDF này là “sự thể hiện” của tài nguyên đó.
Chúng là những mô tả về một tài nguyên, từ góc độ REST, không tồn tại.
Theo RDF, điều này hoàn toàn hợp pháp. Bạn có thể viết mô tả về một tài nguyên không có đại diện. Các
tài liệu RDF thường đề cập đến http: URI không trỏ đến bất kỳ điều gì cụ thể.
Với các định dạng dữ liệu khác, nếu bạn nhìn thấy một liên kết, bạn biết rằng tài liệu đang cố gắng cho
bạn biết về yêu cầu HTTP mà bạn có thể thực hiện. Để trích dẫn định nghĩa của Fielding về siêu phương
tiện, liên kết là “thông tin kiểm soát ứng dụng” giải thích những gì ứng dụng khách HTTP của bạn có thể
thực hiện tiếp theo.
Nhưng đối với tiêu chuẩn RDF, không có “ứng dụng” nào được “kiểm soát”.
Các liên kết không làm gì khác ngoài việc đặt tên cho các kết nối trừu tượng giữa các tài nguyên trừu tượng như nhau.
Bạn phải suy luận về những mối liên hệ đó chứ không phải theo dõi chúng để xem những gì ở phía bên kia.
tài nguyên.
Đầu tiên, mô tả tài nguyên cho phép bạn nói về tài nguyên khi bạn không kiểm soát việc trình
bày. Điều này có thể là do tài nguyên được kiểm soát bởi một máy chủ khác (như tài nguyên
OpenID xác định một trong những người dùng của bạn) hoặc do định dạng trình bày cố định. Bạn
có thể sử dụng chiến lược mô tả để nói lên tài nguyên của người khác.
Thứ hai, nhiều API hiện có phục vụ các biểu diễn không chứa điều khiển siêu phương tiện.
Việc thêm siêu phương tiện vào các tài liệu đó có thể phá vỡ các ứng dụng khách hiện có hoặc
vi phạm tiêu chuẩn. Nhưng với định dạng mô tả tài nguyên, bạn có thể thêm chú thích “bộ xương
ngoài” của cụm từ: [<phrase role="keep- together">hypermedia</phrase>] lên trên một tài liệu
không biết về hypermedia. JSON-LD, mà tôi đã đề cập trong Chương 8 và sẽ quay lại trong phần
sắp tới, được thiết kế chỉ cho mục đích này.
Cuối cùng, bạn có thể sử dụng chiến lược mô tả để nói về một nguồn tài nguyên không có đại
diện vì nó không có trên Web. Tôi đã đề cập ở Chương 4 rằng ấn bản in của cuốn sách này là
một tài nguyên có URI nổi tiếng, urn:isbn:9781449358063. Bạn không thể NHẬN bản trình bày của
tài nguyên đó, nhưng bạn có thể NHẬN tài liệu RDF mô tả nó.
Giả sử bạn gửi yêu cầu GET tới http://www.example.com/book-lookup/ 9781449358063 và nhận được
phản hồi sau:
_:leonard .
_:mike a Schema:Person ;
lược đồ:tên "Mike Amundsen" .
Phần thân thực thể mô tả một tài nguyên: “phiên bản in của API Web RESTful,” được xác định
bởi URI urn:isbn:9781449358063. URI này có một vấn đề lớn: bạn không thể sử dụng nó để thể
hiện tài nguyên. Đó là lý do tại sao khi thiết kế API web, chúng tôi không sử dụng URI. Chúng
tôi tạo các URL http: hoặc https: dựa trên tên miền mà chúng tôi kiểm soát. Chúng tôi tuyên
bố rằng các URL đó tương ứng với mọi thứ trong thế giới thực và chúng tôi cung cấp các đại
diện nắm bắt trạng thái của những thứ trong thế giới thực đó.
Đó không phải là điều tôi đã làm ở đây. Tôi đã tạo tài nguyên thứ hai, “đầu ra của chức năng
tra cứu sách”, được xác định bằng URL http://www.example.com/book-lookup/
9781449358063. Tài nguyên này mô tả trạng thái tài nguyên của vật thể trong thế giới thực được
xác định bởi urn:isbn:9781449358063, thay vì cố gắng thể hiện trực tiếp tài nguyên đó.
Sự thể hiện của nó đưa ra một số khẳng định về một sự vật trong thế giới thực. Nó nói rằng vật
trong thế giới thực là một cuốn sách (một lược đồ: Sách). Tiêu đề của cuốn sách là “API Web
RESTful”, được viết bằng tiếng Anh và có hai tác giả, đều là con người (_mike a Schema:Person),
mỗi tác giả có một tên. (lược đồ: tên)..
Có một ý tưởng thực sự tốt ở đây. Nếu 10 tổ chức khác nhau xác định 10 API web liên quan đến
sách thì chúng tôi sẽ có 10 URL khác nhau cho bất kỳ ISBN nhất định nào. Sẽ phải mất thêm công
sức để xác định rằng cách trình bày của http://example.com/books/ 9781449358063 và cách trình
bày của http://api.example.org/work? isbn=9781449358063 đang nói về cùng một cuốn sách. Nhưng
nếu tất cả các URL đó phục vụ các tài liệu RDF mô tả urn:isbn:9781449358063, thì rõ ràng là
tất cả các trình bày đều nói về cùng một điều cơ bản.
Như tôi đã nói, đây là một ý tưởng tuyệt vời… dành cho sách in. Nó không hoạt động tốt đối với
các tài nguyên thiếu mã định danh duy nhất. Lấy con người. Bạn có thể sử dụng RDF và từ vựng
của lược đồ.org để đưa ra mọi loại khẳng định về một con người:
HTTP/1.1 200 OK
Loại nội dung: văn bản/rùa
Tài liệu RDF/Rùa này mô tả một tài nguyên. Nó nói rằng tài nguyên là một người có tên và ngày
sinh nhất định. Nhưng không có sơ đồ URI được thống nhất cho mọi người1 nên tài nguyên được đề
cập không có URI. Nó chỉ có một mã định danh nội bộ, “Jennifer”.
Tài liệu này là một tập hợp các xác nhận về một tài nguyên ẩn danh. Không có cách thống nhất
nào để xác định con người mà chúng ta đang nói đến. Nếu 10 API phục vụ các mô tả RDF của cùng
một người thì không có cách nào rõ ràng để phát hiện ra tất cả chúng đều đang nói về cùng một
người.
Tại thời điểm này, bạn cũng có thể tạo một URL http: cho tài nguyên cá nhân của mình . Sau đó,
bạn có thể cung cấp bản trình bày về tài nguyên khi ai đó thực hiện yêu cầu GET tới URL của
tài nguyên đó. Và một khi bạn quyết định sử dụng chiến lược biểu diễn thay vì chiến lược mô
tả, bạn có thể muốn sử dụng định dạng dữ liệu có khả năng kiểm soát siêu phương tiện tốt hơn
RDF/XML hoặc RDF/Turtle.
1. Acct: Lược đồ URI, được xác định trong “draft-ietf-appsawg-acct-uri” của Internet-Draft, không thể xác định được con người
nhưng nó có thể xác định tài khoản người dùng. Đối với nhiều API, điều đó đủ gần.