Ссылки и встраивания

WP REST API добавляет ссылки на возможные маршруты во всех ответах API, это позволяет узнать какие еще связанные маршруты возможны. REST API не полностью соответствует HAL стандарту, но свойства ._links и ._embedded тут используются так как описано ниже.

Это свойство в json данных ответа содержит карту ссылок на другие связанные с текущим запросом ресурсы. Связь показывает как указанные в _links ресурсы относятся к основному ресурсу. Например:

  • author — показывает автора текущего ресурса (например поста) и показывает маршрут этого автора.
  • wp:term — показывает какие у поста есть метки или рубрики и по каким маршрутам к ним можно обратиться.

Связи похожи на HTML теги <link> или ссылки вида <a rel="">.

Связь может быть указана как:

  • Стандартная.
  • URI — например https://api.w.org/term.
  • Компактный URI — например wp:term. Компактный URI, для обеспечения полной совместимости, может быть преобразован в полный вид.

Каждая связь в _links содержит объект данных, в котором указаны:

  • href — это ссылка (маршрут).
  • другие свойства — тип контента, дополнительная информация, данные о том что можно сделать со ссылкой.

Пример ответа /wp-json/wp/v2/posts/42

{
	"id": 42,
	...
	"_links": {
		"collection": [
			{
				"href": "https://demo.wp-api.org/wp-json/wp/v2/posts"
			}
		],
		"author": [
			{
				"href": "https://demo.wp-api.org/wp-json/wp/v2/users/1",
				"embeddable": true
			}
		]
	}
}

Пример /wp-json/wp/v2/comments/1

{
	"id": 1,
	...
	"_links": {
		"self": [
			{
				"href": "http://example.com/wp-json/wp/v2/comments/1"
			}
		],
		"collection": [
			{
				"href": "http://example.com/wp-json/wp/v2/comments"
			}
		],
		"up": [
			{
				"embeddable": true,
				"post_type": "post",
				"href": "http://example.com/wp-json/wp/v2/posts/11"
			}
		]
	}
}

Пример /wp-json/wp/v2/posts/72

{
	"id": 72,
	...
	"_links": {
		"self": [
			{
				"href": "http://example.com/wp-json/wp/v2/posts/72"
			}
		],
		"collection": [
			{
				"href": "http://example.com/wp-json/wp/v2/posts"
			}
		],
		"about": [
			{
				"href": "http://example.com/wp-json/wp/v2/types/post"
			}
		],
		"author": [
			{
				"embeddable": true,
				"href": "http://example.com/wp-json/wp/v2/users/1"
			}
		],
		"replies": [
			{
				"embeddable": true,
				"href": "http://example.com/wp-json/wp/v2/comments?post=72"
			}
		],
		"version-history": [
			{
				"count": 8,
				"href": "http://example.com/wp-json/wp/v2/posts/72/revisions"
			}
		],
		"predecessor-version": [
			{
				"id": 97,
				"href": "http://example.com/wp-json/wp/v2/posts/72/revisions/97"
			}
		],
		"wp:attachment": [
			{
				"href": "http://example.com/wp-json/wp/v2/media?parent=72"
			}
		],
		"wp:term": [
			{
				"taxonomy": "category",
				"embeddable": true,
				"href": "http://example.com/wp-json/wp/v2/categories?post=72"
			},
			{
				"taxonomy": "post_tag",
				"embeddable": true,
				"href": "http://example.com/wp-json/wp/v2/tags?post=72"
			}
		],
		"curies": [
			{
				"name": "wp",
				"href": "https://api.w.org/{rel}",
				"templated": true
			}
		]
	}
}

Для запросов коллекций (когда возвращается список объектов), свойство _links, присутствует в каждом элементе списка. А ссылка на верхний уровень ресурса находится в заголовке ответа в свойстве Link.

Если ваш клиент не умеет читать заголовки ответа, то их можно поместить в сам ответ указав параметр _envelope.

Пример /wp-json/wp/v2/posts/72

Золовки ответа:

Access-Control-Allow-Headers : Authorization, Content-Type
Access-Control-Expose-Headers: X-WP-Total, X-WP-TotalPages
Allow                        : GET, POST, PUT, PATCH, DELETE
Cache-Control                : no-cache, must-revalidate, max-age=0
Connection                   : Keep-Alive
Content-Length               : 5459
Content-Type                 : application/json; charset=UTF-8
Date                         : Wed, 29 Aug 2018 23:48:25 GMT
Expires                      : Wed, 11 Jan 1984 05:00:00 GMT
Keep-Alive                   : timeout=10, max=99
Link                         : <http://example.com/provrka-klika-po-ssylke/>; rel="alternate"; type=text/html
Server                       : Apache
X-Content-Type-Options       : nosniff
X-Robots-Tag                 : noindex

_embed (встраивания)

Некоторые ответы содержат ссылки на связанные ресурсы (маршурты), такие ссылки располагаются под ключем _links. Например, пост может содержать ссылку на родительский пост или ссылку на комментарии к посту.

Связанные ресурсы у которых есть возможность встраивания (свойство embeddable = true) можно сразу добавить в ответ, чтобы получить все данные в одном запросе и не создавать дополнительных HTTP запросов. Так, клиенты могут получить сам ресурс, а также связанные с ним данные в одном запросе.

Для этого при запросе нужно указать параметр запроса ?_embed. В этом случае, связанные ресурсы будут встроены в тело ответа и будут расположены под ключом _embedded

Пример

Отправим обычный запрос:

GET http://example.com/wp-json/wp/v2/posts/113
{
	"id": 113,
	"date": "2018-08-17T02:57:44",
	...
	"categories": [ 1 ],
	"tags": [],
	"_links": {
		"self": [
			{ "href": "http://example.com/wp-json/wp/v2/posts/113" }
		],
		...
	}
}

Теперь отправим _embed запрос:

GET http://example.com/wp-json/wp/v2/posts/113?_embed
{
	"id": 113,
	"date": "2018-08-17T02:57:44",
	...
	"categories": [ 1 ],
	"tags": [],
	"_links": {
		"self": [
			{ "href": "http://example.com/wp-json/wp/v2/posts/113" }
		],
		...
	},
	"_embedded": {
		"author": [
			{
				"id": 1,
				"name": "kama",
				"url": "",
				"description": "",
				"link": "http://example.com/author/kama/",
				"slug": "kama",
				"avatar_urls": {
					"24": "http://1.gravatar.com/avatar/155e695ab2251ee3c482c1e3e690683b?s=24&d=mm&r=g",
					"48": "http://1.gravatar.com/avatar/155e695ab2251ee3c482c1e3e690683b?s=48&d=mm&r=g",
					"96": "http://1.gravatar.com/avatar/155e695ab2251ee3c482c1e3e690683b?s=96&d=mm&r=g"
				},
				"_links": {
					"self": [
						{
							"href": "http://example.com/wp-json/wp/v2/users/1"
						}
					],
					"collection": [
						{
							"href": "http://example.com/wp-json/wp/v2/users"
						}
					]
				}
			}
		],
		"wp:term": [
			[
				{
					"id": 1,
					"link": "http://example.com/cat/my-plugins/",
					"name": "My Plugins",
					"slug": "my-plugins",
					"taxonomy": "category",
					"_links": {
						"self": [
							{
								"href": "http://example.com/wp-json/wp/v2/categories/1"
							}
						],
						"collection": [
							{
								"href": "http://example.com/wp-json/wp/v2/categories"
							}
						],
						"about": [
							{
								"href": "http://example.com/wp-json/wp/v2/taxonomies/category"
							}
						],
						"wp:post_type": [
							{
								"href": "http://example.com/wp-json/wp/v2/posts?categories=1"
							}
						],
						"curies": [
							{
								"name": "wp",
								"href": "https://api.w.org/{rel}",
								"templated": true
							}
						]
					}
				}
			],
			[]
		]
	}
}

Пример ответа /wp-json/wp/v2/posts/42?_embed

{
  "id": 42,
  ...
  "_links": {
	"collection": [
	  {
		"href": "https://demo.wp-api.org/wp-json/wp/v2/posts"
	  }
	],
	"author": [
	  {
		"href": "https://demo.wp-api.org/wp-json/wp/v2/users/1",
		"embeddable": true
	  }
	]
  },
  "_embedded": {
	"author": {
	  "id": 1,
	  "name": "admin",
	  "description": "Site administrator"
	}
  }
}

Пример /wp-json/wp/v2/posts/72?_embed

{
	"id": 72,
	...
	"_links": {
		"self": [
			{
				"href": "http://example.com/wp-json/wp/v2/posts/72"
			}
		],
		"collection": [
			{
				"href": "http://example.com/wp-json/wp/v2/posts"
			}
		],
		"about": [
			{
				"href": "http://example.com/wp-json/wp/v2/types/post"
			}
		],
		"author": [
			{
				"embeddable": true,
				"href": "http://example.com/wp-json/wp/v2/users/1"
			}
		],
		"replies": [
			{
				"embeddable": true,
				"href": "http://example.com/wp-json/wp/v2/comments?post=72"
			}
		],
		"version-history": [
			{
				"count": 8,
				"href": "http://example.com/wp-json/wp/v2/posts/72/revisions"
			}
		],
		"predecessor-version": [
			{
				"id": 97,
				"href": "http://example.com/wp-json/wp/v2/posts/72/revisions/97"
			}
		],
		"wp:attachment": [
			{
				"href": "http://example.com/wp-json/wp/v2/media?parent=72"
			}
		],
		"wp:term": [
			{
				"taxonomy": "category",
				"embeddable": true,
				"href": "http://example.com/wp-json/wp/v2/categories?post=72"
			},
			{
				"taxonomy": "post_tag",
				"embeddable": true,
				"href": "http://example.com/wp-json/wp/v2/tags?post=72"
			}
		],
		"curies": [
			{
				"name": "wp",
				"href": "https://api.w.org/{rel}",
				"templated": true
			}
		]
	},
	"_embedded": {
		"author": [
			{
				"id": 1,
				"name": "kama",
				"url": "",
				"description": "",
				"link": "http://example.com/author/kama/",
				"slug": "kama",
				"avatar_urls": {
					"24": "http://1.gravatar.com/avatar/155e695ab2251ee3c482c1e3e690683b?s=24&d=mm&r=g",
					"48": "http://1.gravatar.com/avatar/155e695ab2251ee3c482c1e3e690683b?s=48&d=mm&r=g",
					"96": "http://1.gravatar.com/avatar/155e695ab2251ee3c482c1e3e690683b?s=96&d=mm&r=g"
				},
				"_links": {
					"self": [
						{
							"href": "http://example.com/wp-json/wp/v2/users/1"
						}
					],
					"collection": [
						{
							"href": "http://example.com/wp-json/wp/v2/users"
						}
					]
				}
			}
		],
		"wp:term": [
			[
				{
					"id": 1,
					"link": "http://example.com/cat/my-plugins/",
					"name": "My Plugins",
					"slug": "my-plugins",
					"taxonomy": "category",
					"_links": {
						"self": [
							{
								"href": "http://example.com/wp-json/wp/v2/categories/1"
							}
						],
						"collection": [
							{
								"href": "http://example.com/wp-json/wp/v2/categories"
							}
						],
						"about": [
							{
								"href": "http://example.com/wp-json/wp/v2/taxonomies/category"
							}
						],
						"wp:post_type": [
							{
								"href": "http://example.com/wp-json/wp/v2/posts?categories=1"
							}
						],
						"curies": [
							{
								"name": "wp",
								"href": "https://api.w.org/{rel}",
								"templated": true
							}
						]
					}
				}
			],
			[]
		]
	}
}