{"id":30792,"date":"2019-10-31T21:37:27","date_gmt":"2019-10-31T18:37:27","guid":{"rendered":"https:\/\/prohoster.info\/blog\/nash-opyt-sozdaniya-api-gateway\/"},"modified":"2019-10-31T21:37:27","modified_gmt":"2019-10-31T18:37:27","slug":"nash-opyt-sozdaniya-api-gateway","status":"publish","type":"post","link":"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/nash-opyt-sozdaniya-api-gateway","title":{"rendered":"Our Experience in Creating an API Gateway","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Some companies, including our client, develop their product through a partner network. For instance, large online stores are integrated with a delivery service\u2014when you order a product, you soon receive a tracking number for your package. Another example is when you buy travel insurance or an airport express ticket along with your flight ticket.<\/p>\n<p>This requires a single API, which must be provided to partners through the API Gateway. This is the task we set out to accomplish. In this article, we will discuss the details.<\/p>\n<p>Given: an ecosystem and an API portal with an interface where users are registered, receive information, etc. We need to create a convenient and reliable API Gateway. Throughout the process, we needed to ensure <\/p>\n<ul>\n<li>registration, <\/li>\n<li>management of API connections, <\/li>\n<li>monitoring how users interact with the endpoint system, <\/li>\n<li>tracking business metrics.<\/li>\n<\/ul>\n<p>\n<img decoding=\"async\" alt=\"Our Experience in Creating an API Gateway\" src=\"\/wp-content\/uploads\/2019\/04\/4fa66fd4573af16b0bc78aa61173f907.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nIn this article, we will share our experience in creating an API Gateway, during which we tackled the following tasks:<\/p>\n<ul>\n<li>user authentication,<\/li>\n<li>user authorization,<\/li>\n<li>modification of the original request,<\/li>\n<li>request proxying,<\/li>\n<li>response post-processing.<\/li>\n<\/ul>\n<p>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><br \/>\nThere are two types of API management:<\/p>\n<p>1. Standard, which operates as follows: before connecting, the user tests the features, then pays and integrates it into their site. This is most commonly used in small and medium businesses.<\/p>\n<p>2. Large B2B API Management, where a company first makes a business decision to connect, becomes a partner of the company with contractual obligations, and only then connects to the API. After settling all formalities, the company gains test access, undergoes testing, and goes live. However, this is not possible without a management decision to connect. <\/p>\n<p><img decoding=\"async\" alt=\"Our Experience in Creating an API Gateway\" src=\"\/wp-content\/uploads\/2019\/04\/b9ab53d6c64d5a971c4950cd340ad42e.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h3> Our Solution<\/h3>\n<p>\nIn this section, we will discuss the creation of the API Gateway.<\/p>\n<p>The end users of the API gateway we are developing are the partners of our client. We already have the necessary contracts for each of them stored. We will only need to extend the functionality, indicating the provided access to the gateway. Accordingly, a controlled process for connection and management is needed.<\/p>\n<p>Of course, we could have chosen some ready-made solution for API Management and the creation of an API Gateway in particular. An example could be<noindex><a rel=\"nofollow\" href=\"https:\/\/docs.microsoft.com\/en-us\/azure\/api-management\/\"> Azure API Management<\/a><\/noindex>It didn't work for us because we already had an API portal and a vast ecosystem built around it. All users were already registered and knew where and how to find the information they needed. The necessary interfaces were already present in the API portal; we only needed the API Gateway, which is what we set out to develop. <\/p>\n<p>What we call the API Gateway is a kind of proxy. Again, we had a choice\u2014either write our own proxy or choose something already available. In this case, we went with the second option and chose the combination of nginx+Lua. Why? We needed reliable, tested software that supports scalability. We didn't want to verify both the business logic and the proxy functionality after implementation. <\/p>\n<p>Every web server has a request handling pipeline. In the case of nginx, it looks like this:<\/p>\n<p><img decoding=\"async\" alt=\"Our Experience in Creating an API Gateway\" src=\"\/wp-content\/uploads\/2019\/04\/b4cba1d37cc769202f92df052b45c77e.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n(diagram from <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/openresty\/lua-nginx-module\">GitHub Lua Nginx<\/a><\/noindex>)<\/p>\n<p>Our goal was to integrate into this pipeline at the moment where we could modify the incoming request. <\/p>\n<p>We want to create a transparent proxy so that the request remains functional as it arrived. We only control access to the final API and help the request reach it. If the request is incorrect, the final API should show the error, not us. The only reason we can reject a request is due to a lack of access for the client. <\/p>\n<p>There is already an <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/openresty\/lua-nginx-module\">extension<\/a><\/noindex> to <noindex><a rel=\"nofollow\" href=\"http:\/\/www.lua.ru\/\">Lua<\/a><\/noindex>. Lua is a scripting language that is very lightweight and easy to learn. Thus, we implemented the necessary logic using Lua. <\/p>\n<p>The configuration of nginx (analogous to route in an application), where all the work is done, is quite understandable. The last directive here, post_action, is noteworthy.<\/p>\n<pre><code class=\"nginx\">location \/middleware {\n      more_clear_input_headers Accept-Encoding;\n      lua_need_request_body on;\n      rewrite_by_lua_file 'middleware\/rewrite.lua';\n      access_by_lua_file 'middleware\/access.lua';\n      proxy_pass https:\/\/someurl.com;\n      body_filter_by_lua_file 'middleware\/body_filter.lua';\n      post_action \/process_session;\n}\n<\/code><\/pre>\n<p>\nLet\u2019s consider what happens in this configuration: <br \/>\n<b>more_clear_input_headers<\/b> \u2014 clears the values of the specified headers after the directive. <br \/>\n<b>lua_need_request_body <\/b>\u2014 determines whether to read the original request body before executing the rewrite\/access\/access_by_lua directives or not. By default, nginx does not read the client request body, and if you need to access it, this directive must be set to on.<br \/>\n<b>rewrite_by_lua_file<\/b> \u2014 path to the script that contains the logic for modifying the request<br \/>\n<b>access_by_lua_file <\/b>\u2014 path to the script that contains the logic for checking access to the resource. <br \/>\n<b>proxy_pass <\/b>\u2014 url to which the request will be proxied.<br \/>\n<b>body_filter_by_lua_file <\/b>\u2014 path to the script that contains the logic for filtering the request before returning it to the client.<br \/>\nAnd finally, <b>post_action<\/b> \u2014 an officially undocumented directive that allows you to perform other actions after the response is sent to the client. <\/p>\n<p>Next, we will discuss in order how we solved our tasks.<\/p>\n<h3>Authorization\/authentication and request modification<\/h3>\n<p>\n<b>Authorization<\/b><\/p>\n<p>We implemented authorization and authentication using certificate access. There is a root certificate. A personal certificate is generated for each new client of the customer, which they can use to access the API. This certificate is configured in the server section of the nginx settings.<\/p>\n<pre><code class=\"nginx\">ssl on;\nssl_certificate \/usr\/local\/openresty\/nginx\/ssl\/cert.pem;\nssl_certificate_key \/usr\/local\/openresty\/nginx\/ssl\/cert.pem;\nssl_client_certificate \/usr\/local\/openresty\/nginx\/ssl\/ca.crt;\nssl_verify_client on;<\/code><\/pre>\n<p>\n<b>Modification<\/b><\/p>\n<p>A fair question arises: what to do with a certified client if we suddenly want to disconnect them from the system? We can't reissue certificates for all the other clients. <\/p>\n<p>Thus, we smoothly approached the next task \u2014 modification of the original request. The original request from the client is, generally speaking, not valid for the final system. One of the tasks is to append missing parts to the request to make it valid. The twist is that the missing data is different for each client. We know that the client comes to us with a certificate from which we can take a fingerprint and pull the necessary client data from the database. <\/p>\n<p>If at some point it becomes necessary to disconnect a client from our service, their data will disappear from the database and they will not be able to do anything. <\/p>\n<h3>Working with client data<\/h3>\n<p>\nWe needed to ensure high availability of the solution, especially how we obtain client data. The challenge is that the primary source of this data is a third-party service that does not guarantee uninterrupted and sufficiently high-speed performance. <\/p>\n<p>Therefore, we needed to ensure high availability of client data. As a tool, we chose <noindex><a rel=\"nofollow\" href=\"https:\/\/hazelcast.org\/\">Hazelcast<\/a><\/noindex>, which provides us with:<\/p>\n<ul>\n<li>quick access to data,<\/li>\n<li>the ability to organize a cluster of multiple nodes with replicated data on different nodes.<\/li>\n<\/ul>\n<p>\nWe followed the simplest strategy for delivering data to the cache:<\/p>\n<p><img decoding=\"async\" alt=\"Our Experience in Creating an API Gateway\" src=\"\/wp-content\/uploads\/2019\/04\/0175d6f0fda543566ab13d4cae9d8cc1.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nInteraction with the end system occurs within sessions, and there is a limit on the maximum number. If the client does not close the session, we will have to do it ourselves. <\/p>\n<p>Data about the open session comes from the end system and is initially processed on the Lua side. We decided to use Hazelcast to store this data with a job written in .NET. Then, at regular intervals, we check the validity of open sessions and close the expired ones. <\/p>\n<h3>Access to Hazelcast from both Lua and .NET<\/h3>\n<p>\nThere are no clients on Lua for working with Hazelcast, but Hazelcast has a REST API that we decided to use. For .NET, however, there is <noindex><a rel=\"nofollow\" href=\"https:\/\/hazelcast.org\/clients\/net\/\">a client<\/a><\/noindex>, through which we planned to access Hazelcast data on the .NET side. But it didn't go as planned.<\/p>\n<p><img decoding=\"async\" alt=\"Our Experience in Creating an API Gateway\" src=\"\/wp-content\/uploads\/2019\/04\/52c9437e5cd16073b56afc55a4f415da.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nWhen saving data via REST and retrieving it via the .NET client, different serializers\/deserializers are used. Therefore, it is impossible to put data through REST and retrieve it through the .NET client and vice versa. <\/p>\n<p>If there are those interested, we will provide more details about this issue in a separate article. Spoiler \u2014 on the diagram. <\/p>\n<p><img decoding=\"async\" alt=\"Our Experience in Creating an API Gateway\" src=\"\/wp-content\/uploads\/2019\/04\/73bb11214fdaeca86ef10cdbd788e288.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h3>Logging and monitoring<\/h3>\n<p>\nOur corporate logging standard for .NET is Serilog, all logs ultimately end up in Elasticsearch, and we analyze them through Kibana. We wanted to do something similar in this case. The only <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/DhavalKapil\/elasticsearch-lua\">a client<\/a><\/noindex> client for working with Elastic in Lua that we found broke on the first require. So we used Fluentd. <\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/www.fluentd.org\/\">Fluentd<\/a><\/noindex> is an open source solution for providing a unified application logging layer. It allows collecting logs from different layers of an application and then streaming them to a single source. <\/p>\n<p>The API Gateway runs in K8S, so we decided to add a container with Fluentd to the same pod to write logs to the existing open tcp port of Fluentd. <\/p>\n<p>We also explored how Fluentd would behave if it lost connection to Elasticsearch. For two days, continuous requests were sent to the gateway, logs were sent to Fluentd, but Fluentd's IP was banned by Elastic. After the connection was restored, Fluentd successfully sent all logs to Elastic.<\/p>\n<h3>Conclusion<\/h3>\n<p>\nThe chosen implementation approach allowed us to deliver a working product to the production environment in just 2.5 months.<\/p>\n<p>If you ever find yourself dealing with such matters, we recommend first clearly understanding what task you are addressing and what resources you already have. Be mindful of the complexities of integrating with existing API management systems. <\/p>\n<p>Understand for yourself what exactly you are going to develop \u2014 just the business logic for handling requests or, as was the case for us, the entire proxy. Remember that everything you do yourself must be thoroughly tested afterward.<br \/>\n<br \/>Source: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/true_engineering\/blog\/446438\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438, \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u043d\u0430\u0448 \u0437\u0430\u043a\u0430\u0437\u0447\u0438\u043a, \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u044e\u0442 \u043f\u0440\u043e\u0434\u0443\u043a\u0442 \u0447\u0435\u0440\u0435\u0437 \u043f\u0430\u0440\u0442\u043d\u0435\u0440\u0441\u043a\u0443\u044e \u0441\u0435\u0442\u044c. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043a\u0440\u0443\u043f\u043d\u044b\u0435 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u043c\u0430\u0433\u0430\u0437\u0438\u043d\u044b \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0441\u043e \u0441\u043b\u0443\u0436\u0431\u043e\u0439 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u2014 \u0432\u044b \u0437\u0430\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0435 \u0442\u043e\u0432\u0430\u0440 \u0438 \u0432\u0441\u043a\u043e\u0440\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0435 \u0442\u0440\u0435\u043a\u0438\u043d\u0433\u043e\u0432\u044b\u0439 \u043d\u043e\u043c\u0435\u0440 \u043f\u043e\u0441\u044b\u043b\u043a\u0438. \u0414\u0440\u0443\u0433\u043e\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u2014 \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u0430\u0432\u0438\u0430\u0431\u0438\u043b\u0435\u0442\u043e\u043c \u0432\u044b \u043f\u043e\u043a\u0443\u043f\u0430\u0435\u0442\u0435 \u0441\u0442\u0440\u0430\u0445\u043e\u0432\u043a\u0443 \u0438\u043b\u0438 \u0431\u0438\u043b\u0435\u0442 \u043d\u0430 \u0430\u044d\u0440\u043e\u044d\u043a\u0441\u043f\u0440\u0435\u0441\u0441. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043e\u0434\u0438\u043d API, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0443\u0436\u043d\u043e \u0432\u044b\u0434\u0430\u0442\u044c \u043f\u0430\u0440\u0442\u043d\u0435\u0440\u0430\u043c \u0447\u0435\u0440\u0435\u0437 API Gateway. \u042d\u0442\u0443 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":22777,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-30792","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.2 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438, \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u043d\u0430\u0448 \u0437\u0430\u043a\u0430\u0437\u0447\u0438\u043a, \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u044e\u0442 \u043f\u0440\u043e\u0434\u0443\u043a\u0442 \u0447\u0435\u0440\u0435\u0437 \u043f\u0430\u0440\u0442\u043d\u0435\u0440\u0441\u043a\u0443\u044e \u0441\u0435\u0442\u044c.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/nash-opyt-sozdaniya-api-gateway\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041d\u0430\u0448 \u043e\u043f\u044b\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f API Gateway | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438, \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u043d\u0430\u0448 \u0437\u0430\u043a\u0430\u0437\u0447\u0438\u043a, \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u044e\u0442 \u043f\u0440\u043e\u0434\u0443\u043a\u0442 \u0447\u0435\u0440\u0435\u0437 \u043f\u0430\u0440\u0442\u043d\u0435\u0440\u0441\u043a\u0443\u044e \u0441\u0435\u0442\u044c.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/nash-opyt-sozdaniya-api-gateway\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T18:37:27+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T18:37:27+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Our Experience in Creating API Gateway | ProHoster","description":"Some companies, including our client, are developing the product through a partner network.","canonical_url":"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/nash-opyt-sozdaniya-api-gateway","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"en_US","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041d\u0430\u0448 \u043e\u043f\u044b\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f API Gateway | ProHoster","og:description":"\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438, \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u043d\u0430\u0448 \u0437\u0430\u043a\u0430\u0437\u0447\u0438\u043a, \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u044e\u0442 \u043f\u0440\u043e\u0434\u0443\u043a\u0442 \u0447\u0435\u0440\u0435\u0437 \u043f\u0430\u0440\u0442\u043d\u0435\u0440\u0441\u043a\u0443\u044e \u0441\u0435\u0442\u044c.","og:url":"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/nash-opyt-sozdaniya-api-gateway","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T18:37:27+00:00","article:modified_time":"2019-10-31T18:37:27+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"30792","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-21 03:01:22","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 17:05:31","updated":"2026-01-21 03:01:22","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts\/30792","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/comments?post=30792"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts\/30792\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/media\/22777"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/media?parent=30792"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/categories?post=30792"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/tags?post=30792"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}