{"id":386158,"date":"2024-06-29T06:32:50","date_gmt":"2024-06-29T06:32:50","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=386158"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=386158","title":{"rendered":"<span>Spring Boot app with Apache Kafka in Docker container<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>Privet, comrads!<\/p>\n<p>In this article i\u2019ll show how easy it is to setup Spring Java app with Kafka message brocker. We will use docker containers for kafka zookeeper\/brocker apps and configure plaintext authorization for access from both local and external net.<\/p>\n<p><strong>Final project link to github can be picked up at the end of the article<\/strong><\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/v2\/dc\/gm\/v2dcgmodibabsswcdwwzt3v9l8a.png\" alt=\"by Esperanza Gates\" title=\"by Esperanza Gates\" width=\"1430\" height=\"860\" data-src=\"https:\/\/habrastorage.org\/webt\/v2\/dc\/gm\/v2dcgmodibabsswcdwwzt3v9l8a.png\"\/><figcaption>by Esperanza Gates<\/figcaption><\/figure>\n<h4>Apache Kafka + Zookeeper docker image selection<\/h4>\n<p>First, you have to decide on the vendor of\u00a0the Apache Kafka image for container. The requirements of each specific project differ in the level of security and reliability of the solution, in some cases, of course, you will have to build your own image, but for most projects it will be reasonable to choose one from docker hub. For 2020, there are three main popular image vendors kafka + zookeper:<\/p>\n<ul>\n<li>\n<p>images from\u00a0<a href=\"https:\/\/docs.confluent.io\/current\/quickstart\/ce-docker-quickstart.html\" rel=\"noopener noreferrer nofollow\"><strong><u>confluent<\/u><\/strong><\/a>\u00a0[subjectively, a big plus \u2014 they are supplied by the developers of Apache Kafka itself and are the most reliable in terms of information security]<\/p>\n<\/li>\n<li>\n<p>images from\u00a0<a href=\"https:\/\/github.com\/bitnami\/bitnami-docker-kafka\" rel=\"noopener noreferrer nofollow\"><strong><u>bitnami<\/u><\/strong><\/a>\u00a0[in comparison with confluent, the images need minimal configuration and start out of the box]<\/p>\n<\/li>\n<li>\n<p>images from\u00a0<a href=\"https:\/\/github.com\/wurstmeister\/kafka-docker\" rel=\"noopener noreferrer nofollow\"><strong><u>wurstmeister<\/u><\/strong><\/a>\u00a0[in this example I will use them because the project has the most active community on github and hub.docker, as well as excellent documentation]<\/p>\n<\/li>\n<\/ul>\n<h4>Installing Docker-compose<\/h4>\n<p>Docker-compose is a tool to run and configure multi-container applications . It is a greate choice for Kafka setup because the minimum kafka configuration consist of zookeeper and at least one broker.<\/p>\n<p>Docker-compose comes bundled with Docker app for\u00a0<strong>mac\u00a0<\/strong>and\u00a0<strong>windows<\/strong>, so you only need to to download and install the Docker app from\u00a0<a href=\"https:\/\/docs.docker.com\/engine\/install\/\" rel=\"noopener noreferrer nofollow\"><u>https:\/\/docs.docker.com\/engine\/install\/<\/u><\/a>.<\/p>\n<p><strong>Linux\u00a0<\/strong>users required to install it compose and docker as separate tools. For a guide to installing docker + compose, it\u2019s best to refer to the official documentation\u00a0<a href=\"https:\/\/docs.docker.com\/compose\/install\/\" rel=\"noopener noreferrer nofollow\"><u>https:\/\/docs.docker.com\/compose\/install\/<\/u><\/a>.<\/p>\n<h4>Writing a yaml file for compose<\/h4>\n<p>The general scheme of our cluster with clients and containers will be as follows:<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/px\/ic\/9p\/pxic9pwqdcxiwek5tcdklqep3ca.png\" width=\"1023\" height=\"497\" data-src=\"https:\/\/habrastorage.org\/webt\/px\/ic\/9p\/pxic9pwqdcxiwek5tcdklqep3ca.png\"\/><figcaption><\/figcaption><\/figure>\n<p>One broker will connect to one coordinator with open ports 9093 for localhost connections and 9092 for external connections.For access from external networks, authorization is enabled via login password without ssl. To work through ssl, you need to issue your own keys and sign certificates, the whole process is well\u00a0<a href=\"https:\/\/docs.confluent.io\/current\/security\/security_tutorial.html\" rel=\"noopener noreferrer nofollow\"><u>described in the official documentation<\/u><\/a>.<\/p>\n<p>As a result, the file will look like this (the\u00a0<em>&lt;your public IP here><\/em>\u00a0address needs to be replaced with your public IP to be able to access from other networks):<\/p>\n<div class=\"tm-iframe_temp\" data-src=\"https:\/\/embedd.srv.habr.com\/iframe\/5fb931d73b295d140fdb38c2\" data-style=\"\" id=\"5fb931d73b295d140fdb38c2\" width=\"\"><\/div>\n<\/p>\n<h4>Client authorization<\/h4>\n<p>In order to enable authorization, you need to transfer the\u00a0<em>kafkaserverjaas.conf<\/em>\u00a0file to kafka. In the folder with the compose yaml file, create\u00a0<em>kafkaserverjaas.conf<\/em>\u00a0and add one admin user with the admin-secret password:<\/p>\n<div class=\"tm-iframe_temp\" data-src=\"https:\/\/embedd.srv.habr.com\/iframe\/5fb931e3017bf613f0899deb\" data-style=\"\" id=\"5fb931e3017bf613f0899deb\" width=\"\"><\/div>\n<p>This file will be transferred to the image with the kafka broker via:<\/p>\n<ol>\n<li>\n<p>specifying the path to the file in the kafka config directly<code>KAFKA_OPTS: \"-Djava.security.auth.login.config=\/etc\/kafka\/kafka_server_jaas.conf\"<\/code> <\/p>\n<\/li>\n<li>\n<p>mapping local directory containig file to\u00a0<em>\/etc\/kafka<\/em>\u00a0image directory <code>volumes:       - .\/:\/etc\/kafka<\/code><\/p>\n<\/li>\n<\/ol>\n<h4>Launching containers<\/h4>\n<p>As a result we should get 2 files, which are located in the same directory:<\/p>\n<ul>\n<li>\n<p>docker-compose.yml<\/p>\n<\/li>\n<li>\n<p>kafka_server_jaas.conf<\/p>\n<\/li>\n<\/ul>\n<p>In that directory call:<\/p>\n<p><code>$ docker-compose up -d<\/code><\/p>\n<p>The\u00a0<em>-d<\/em>\u00a0flag allows you to start in\u00a0<em>detached\u00a0<\/em>mode and close the console if necessary without turning off the containers.<\/p>\n<h4>Spring Boot Java client<\/h4>\n<p>Let\u2019s write a minimalistic client to publish\/consume messages from kafka. To do this, we will create a new project through\u00a0<a href=\"https:\/\/start.spring.io\/\" rel=\"noopener noreferrer nofollow\"><u>Spring Initializr<\/u><\/a>\u00a0or any other tool you are used to. It will be enough to connect one dependency:<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/50\/0b\/xo\/500bxocm7jgc_wjbmtuglocdq9i.png\" width=\"700\" height=\"59\" data-src=\"https:\/\/habrastorage.org\/webt\/50\/0b\/xo\/500bxocm7jgc_wjbmtuglocdq9i.png\"\/><figcaption><\/figcaption><\/figure>\n<p>I prefer to configure Spring Boot applications via\u00a0<a href=\"https:\/\/docs.spring.io\/autorepo\/docs\/spring-boot\/1.2.0.M2\/reference\/html\/boot-features-external-config.html#boot-features-external-config-yaml\" rel=\"noopener noreferrer nofollow\"><u>yaml config files\u00a0<\/u><\/a>with minimal Java configurations. Due to the built-in structuring in Yaml-format, these files are much more human-readable than .properties files and allow you to group settings by modules. The only drawback of the .yml configuration is that it is not supported in tests, but it is easily bypassed by the built-in Spring Boot tools.<\/p>\n<blockquote>\n<p><em>I highly recommend to try and check how your perception of the old .properties file changes (especially for large projects) if you rewrite it in yaml. This can be done in a couple of clicks at\u00a0<\/em><a href=\"https:\/\/www.toyaml.com\/index.html\" rel=\"noopener noreferrer nofollow\"><em><u>https:\/\/www.toyaml.com\/index.html<\/u><\/em><\/a><em>.<\/em><\/p>\n<\/blockquote>\n<p>In project resources create an application.yml file with the following content:<\/p>\n<div class=\"tm-iframe_temp\" data-src=\"https:\/\/embedd.srv.habr.com\/iframe\/5fb931f22cbf1a1445b35326\" data-style=\"\" id=\"5fb931f22cbf1a1445b35326\" width=\"\"><\/div>\n<p>This setup works for sequentially reading one message at a time\u00a0<strong>(max-poll-records: 1)<\/strong>\u00a0by one listener\u00a0<strong>(concurrency: 1)<\/strong>\u00a0and requires manual confirmation of message processing in listener\u00a0<strong>(ack-mode: manual_immediate).<\/strong><\/p>\n<h4>Add producer and consumer classes<\/h4>\n<div class=\"tm-iframe_temp\" data-src=\"https:\/\/embedd.srv.habr.com\/iframe\/5fb931fd905dc4e15aeed7f4\" data-style=\"\" id=\"5fb931fd905dc4e15aeed7f4\" width=\"\"><\/div>\n<p>The listener receives the message and logs all available information about it to the console.<\/p>\n<div class=\"tm-iframe_temp\" data-src=\"https:\/\/embedd.srv.habr.com\/iframe\/5fb93206cb79a1e12d666432\" data-style=\"\" id=\"5fb93206cb79a1e12d666432\" width=\"\"><\/div>\n<h4>Let\u2019s start adding messages to the queue every 3 seconds<\/h4>\n<blockquote>\n<p><em>to enable the scheduler, we need to add the\u00a0<\/em><a href=\"http:\/\/twitter.com\/EnableScheduling\" rel=\"noopener noreferrer nofollow\"><em><u>@EnableScheduling<\/u><\/em><\/a><em>\u00a0annotation to our spring application<\/em><\/p>\n<\/blockquote>\n<div class=\"tm-iframe_temp\" data-src=\"https:\/\/embedd.srv.habr.com\/iframe\/5fb9320fd4323713fd4158c5\" data-style=\"\" id=\"5fb9320fd4323713fd4158c5\" width=\"\"><\/div>\n<p>Voil\u00e0! the application is ready to run. You can run the dev-option with a local client and local kafka, and you can also access kafka from other networks if you open port 9092 and specify the host address in application.yml.<\/p>\n<p><strong>The finished project<\/strong>\u00a0<strong>available in the repository &#8212; <\/strong><a href=\"https:\/\/github.com\/layonez\/kafka-example\" rel=\"noopener noreferrer nofollow\"><strong><u>https:\/\/github.com\/layonez\/kafka-example<\/u><\/strong><\/a><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/529222\/\"> https:\/\/habr.com\/ru\/articles\/529222\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>Privet, comrads!<\/p>\n<p>In this article i\u2019ll show how easy it is to setup Spring Java app with Kafka message brocker. We will use docker containers for kafka zookeeper\/brocker apps and configure plaintext authorization for access from both local and external net.<\/p>\n<p><strong>Final project link to github can be picked up at the end of the article<\/strong><\/p>\n<figure class=\"\"><figcaption>by Esperanza Gates<\/figcaption><\/figure>\n<h4>Apache Kafka + Zookeeper docker image selection<\/h4>\n<p>First, you have to decide on the vendor of\u00a0the Apache Kafka image for container. The requirements of each specific project differ in the level of security and reliability of the solution, in some cases, of course, you will have to build your own image, but for most projects it will be reasonable to choose one from docker hub. For 2020, there are three main popular image vendors kafka + zookeper:<\/p>\n<ul>\n<li>\n<p>images from\u00a0<a href=\"https:\/\/docs.confluent.io\/current\/quickstart\/ce-docker-quickstart.html\" rel=\"noopener noreferrer nofollow\"><strong><u>confluent<\/u><\/strong><\/a>\u00a0[subjectively, a big plus \u2014 they are supplied by the developers of Apache Kafka itself and are the most reliable in terms of information security]<\/p>\n<\/li>\n<li>\n<p>images from\u00a0<a href=\"https:\/\/github.com\/bitnami\/bitnami-docker-kafka\" rel=\"noopener noreferrer nofollow\"><strong><u>bitnami<\/u><\/strong><\/a>\u00a0[in comparison with confluent, the images need minimal configuration and start out of the box]<\/p>\n<\/li>\n<li>\n<p>images from\u00a0<a href=\"https:\/\/github.com\/wurstmeister\/kafka-docker\" rel=\"noopener noreferrer nofollow\"><strong><u>wurstmeister<\/u><\/strong><\/a>\u00a0[in this example I will use them because the project has the most active community on github and hub.docker, as well as excellent documentation]<\/p>\n<\/li>\n<\/ul>\n<h4>Installing Docker-compose<\/h4>\n<p>Docker-compose is a tool to run and configure multi-container applications . It is a greate choice for Kafka setup because the minimum kafka configuration consist of zookeeper and at least one broker.<\/p>\n<p>Docker-compose comes bundled with Docker app for\u00a0<strong>mac\u00a0<\/strong>and\u00a0<strong>windows<\/strong>, so you only need to to download and install the Docker app from\u00a0<a href=\"https:\/\/docs.docker.com\/engine\/install\/\" rel=\"noopener noreferrer nofollow\"><u>https:\/\/docs.docker.com\/engine\/install\/<\/u><\/a>.<\/p>\n<p><strong>Linux\u00a0<\/strong>users required to install it compose and docker as separate tools. For a guide to installing docker + compose, it\u2019s best to refer to the official documentation\u00a0<a href=\"https:\/\/docs.docker.com\/compose\/install\/\" rel=\"noopener noreferrer nofollow\"><u>https:\/\/docs.docker.com\/compose\/install\/<\/u><\/a>.<\/p>\n<h4>Writing a yaml file for compose<\/h4>\n<p>The general scheme of our cluster with clients and containers will be as follows:<\/p>\n<figure class=\"\"><figcaption><\/figcaption><\/figure>\n<p>One broker will connect to one coordinator with open ports 9093 for localhost connections and 9092 for external connections.For access from external networks, authorization is enabled via login password without ssl. To work through ssl, you need to issue your own keys and sign certificates, the whole process is well\u00a0<a href=\"https:\/\/docs.confluent.io\/current\/security\/security_tutorial.html\" rel=\"noopener noreferrer nofollow\"><u>described in the official documentation<\/u><\/a>.<\/p>\n<p>As a result, the file will look like this (the\u00a0<em>&lt;your public IP here><\/em>\u00a0address needs to be replaced with your public IP to be able to access from other networks):<\/p>\n<div class=\"tm-iframe_temp\" data-src=\"https:\/\/embedd.srv.habr.com\/iframe\/5fb931d73b295d140fdb38c2\" data-style=\"\" id=\"5fb931d73b295d140fdb38c2\" width=\"\"><\/div>\n<\/p>\n<h4>Client authorization<\/h4>\n<p>In order to enable authorization, you need to transfer the\u00a0<em>kafkaserverjaas.conf<\/em>\u00a0file to kafka. In the folder with the compose yaml file, create\u00a0<em>kafkaserverjaas.conf<\/em>\u00a0and add one admin user with the admin-secret password:<\/p>\n<div class=\"tm-iframe_temp\" data-src=\"https:\/\/embedd.srv.habr.com\/iframe\/5fb931e3017bf613f0899deb\" data-style=\"\" id=\"5fb931e3017bf613f0899deb\" width=\"\"><\/div>\n<p>This file will be transferred to the image with the kafka broker via:<\/p>\n<ol>\n<li>\n<p>specifying the path to the file in the kafka config directly<code>KAFKA_OPTS: \"-Djava.security.auth.login.config=\/etc\/kafka\/kafka_server_jaas.conf\"<\/code> <\/p>\n<\/li>\n<li>\n<p>mapping local directory containig file to\u00a0<em>\/etc\/kafka<\/em>\u00a0image directory <code>volumes:       - .\/:\/etc\/kafka<\/code><\/p>\n<\/li>\n<\/ol>\n<h4>Launching containers<\/h4>\n<p>As a result we should get 2 files, which are located in the same directory:<\/p>\n<ul>\n<li>\n<p>docker-compose.yml<\/p>\n<\/li>\n<li>\n<p>kafka_server_jaas.conf<\/p>\n<\/li>\n<\/ul>\n<p>In that directory call:<\/p>\n<p><code>$ docker-compose up -d<\/code><\/p>\n<p>The\u00a0<em>-d<\/em>\u00a0flag allows you to start in\u00a0<em>detached\u00a0<\/em>mode and close the console if necessary without turning off the containers.<\/p>\n<h4>Spring Boot Java client<\/h4>\n<p>Let\u2019s write a minimalistic client to publish\/consume messages from kafka. To do this, we will create a new project through\u00a0<a href=\"https:\/\/start.spring.io\/\" rel=\"noopener noreferrer nofollow\"><u>Spring Initializr<\/u><\/a>\u00a0or any other tool you are used to. It will be enough to connect one dependency:<\/p>\n<figure class=\"\"><figcaption><\/figcaption><\/figure>\n<p>I prefer to configure Spring Boot applications via\u00a0<a href=\"https:\/\/docs.spring.io\/autorepo\/docs\/spring-boot\/1.2.0.M2\/reference\/html\/boot-features-external-config.html#boot-features-external-config-yaml\" rel=\"noopener noreferrer nofollow\"><u>yaml config files\u00a0<\/u><\/a>with minimal Java configurations. Due to the built-in structuring in Yaml-format, these files are much more human-readable than .properties files and allow you to group settings by modules. The only drawback of the .yml configuration is that it is not supported in tests, but it is easily bypassed by the built-in Spring Boot tools.<\/p>\n<blockquote>\n<p><em>I highly recommend to try and check how your perception of the old .properties file changes (especially for large projects) if you rewrite it in yaml. This can be done in a couple of clicks at\u00a0<\/em><a href=\"https:\/\/www.toyaml.com\/index.html\" rel=\"noopener noreferrer nofollow\"><em><u>https:\/\/www.toyaml.com\/index.html<\/u><\/em><\/a><em>.<\/em><\/p>\n<\/blockquote>\n<p>In project resources create an application.yml file with the following content:<\/p>\n<div class=\"tm-iframe_temp\" data-src=\"https:\/\/embedd.srv.habr.com\/iframe\/5fb931f22cbf1a1445b35326\" data-style=\"\" id=\"5fb931f22cbf1a1445b35326\" width=\"\"><\/div>\n<p>This setup works for sequentially reading one message at a time\u00a0<strong>(max-poll-records: 1)<\/strong>\u00a0by one listener\u00a0<strong>(concurrency: 1)<\/strong>\u00a0and requires manual confirmation of message processing in listener\u00a0<strong>(ack-mode: manual_immediate).<\/strong><\/p>\n<h4>Add producer and consumer classes<\/h4>\n<div class=\"tm-iframe_temp\" data-src=\"https:\/\/embedd.srv.habr.com\/iframe\/5fb931fd905dc4e15aeed7f4\" data-style=\"\" id=\"5fb931fd905dc4e15aeed7f4\" width=\"\"><\/div>\n<p>The listener receives the message and logs all available information about it to the console.<\/p>\n<div class=\"tm-iframe_temp\" data-src=\"https:\/\/embedd.srv.habr.com\/iframe\/5fb93206cb79a1e12d666432\" data-style=\"\" id=\"5fb93206cb79a1e12d666432\" width=\"\"><\/div>\n<h4>Let\u2019s start adding messages to the queue every 3 seconds<\/h4>\n<blockquote>\n<p><em>to enable the scheduler, we need to add the\u00a0<\/em><a href=\"http:\/\/twitter.com\/EnableScheduling\" rel=\"noopener noreferrer nofollow\"><em><u>@EnableScheduling<\/u><\/em><\/a><em>\u00a0annotation to our spring application<\/em><\/p>\n<\/blockquote>\n<div class=\"tm-iframe_temp\" data-src=\"https:\/\/embedd.srv.habr.com\/iframe\/5fb9320fd4323713fd4158c5\" data-style=\"\" id=\"5fb9320fd4323713fd4158c5\" width=\"\"><\/div>\n<p>Voil\u00e0! the application is ready to run. You can run the dev-option with a local client and local kafka, and you can also access kafka from other networks if you open port 9092 and specify the host address in application.yml.<\/p>\n<p><strong>The finished project<\/strong>\u00a0<strong>available in the repository &#8212; <\/strong><a href=\"https:\/\/github.com\/layonez\/kafka-example\" rel=\"noopener noreferrer nofollow\"><strong><u>https:\/\/github.com\/layonez\/kafka-example<\/u><\/strong><\/a><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/529222\/\"> https:\/\/habr.com\/ru\/articles\/529222\/<\/a><br \/><\/br><\/br><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-386158","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/386158","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=386158"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/386158\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=386158"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=386158"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=386158"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}