{"id":301456,"date":"2020-04-07T15:01:40","date_gmt":"2020-04-07T15:01:40","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=301456"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=301456","title":{"rendered":"\u0421\u043f\u043e\u0441\u043e\u0431\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 API-\u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043d\u0430 Golang \u0441 \u0430\u0432\u0442\u043e\u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0435\u0439 \u043a\u043e\u0434\u0430 \u0438 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438"},"content":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/post\/496098\/\">\n<p>\u042f \u0431\u044b \u0445\u043e\u0442\u0435\u043b \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u0432\u0430\u043c \u043e \u0442\u043e\u043c \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u0441\u0442\u0440\u043e \u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0432\u0435\u0431 \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0430 \u044f\u0437\u044b\u043a\u0435 Golang \u0441 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0435\u0439 \u043a \u043d\u0435\u043c\u0443. \u0418 \u043e \u0442\u043e\u043c \u043a\u0430\u043a\u0438\u0435 \u0435\u0441\u0442\u044c \u043f\u043e\u0434\u0445\u043e\u0434\u044b \u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u0438\u0445 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438<\/p>\n<p>  <\/p>\n<p>\u0421\u0435\u0433\u043e\u0434\u043d\u044f \u043c\u044b \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c \u044d\u0442\u0438 \u0433\u043e\u0442\u043e\u0432\u044b\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b:<\/p>\n<p>  <\/p>\n<ul>\n<li><a href=\"#swagger-codegen\">swagger-api\/swagger-codegen<\/a><\/li>\n<li><a href=\"#go-swagger\">go-swagger\/go-swagger<\/a><\/li>\n<li><a href=\"#grpc-gateway\">grpc-ecosystem\/grpc-gateway<\/a><\/li>\n<li><a href=\"#swag\">swaggo\/swag<\/a><\/li>\n<\/ul>\n<p><a name=\"habracut\"><\/a>  <\/p>\n<h1 id=\"swagger-codegen\">Swagger Codegen<\/h1>\n<p>  <\/p>\n<p>\u041d\u0430\u0447\u043d\u0435\u043c \u0441 <a href=\"https:\/\/github.com\/swagger-api\/swagger-codegen\" rel=\"nofollow\">swagger-api\/swagger-codegen<\/a>, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u043c <a href=\"https:\/\/swagger.io\/tools\/swagger-codegen\/\" rel=\"nofollow\">swagger.io<\/a>. Swagger Codegen \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0441\u0431\u043e\u0440\u043a\u0438 \u0437\u0430 \u0441\u0447\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0445 \u0437\u0430\u0433\u043b\u0443\u0448\u0435\u043a \u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0438\u0445 SDK \u0434\u043b\u044f \u043b\u044e\u0431\u043e\u0433\u043e API, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u0432 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 OpenAPI (\u0440\u0430\u043d\u0435\u0435 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e\u0439 \u043a\u0430\u043a Swagger), \u0432\u0430\u043c \u043e\u0441\u0442\u0430\u0435\u0442\u0441\u044f \u043b\u0438\u0448\u044c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0432\u0430\u0448\u0435\u0433\u043e API.<\/p>\n<p>  <\/p>\n<p>\u041d\u0438\u0436\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d \u043f\u0440\u0438\u043c\u0435\u0440 \u043d\u0430\u0448\u0435\u0433\u043e swagger \u0444\u0430\u0439\u043b\u0430 \u0438 \u0435\u0433\u043e \u043d\u0430\u0433\u043b\u044f\u0434\u043d\u044b\u0439 \u0432\u0438\u0434 \u0432 Swagger Editor&#8217;\u0435, \u0433\u0434\u0435 \u043c\u044b \u0437\u0430 \u043e\u0434\u043d\u043e \u043c\u043e\u0436\u0435\u043c \u0438 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0448\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">swagger.json<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"json\">{   &quot;swagger&quot; : &quot;2.0&quot;,   &quot;info&quot; : {     &quot;version&quot; : &quot;1.0.0&quot;,     &quot;title&quot; : &quot;Swagger Petstore&quot;   },   &quot;host&quot; : &quot;localhost&quot;,   &quot;basePath&quot; : &quot;\/v1&quot;,   &quot;tags&quot; : [ {     &quot;name&quot; : &quot;pet&quot;   } ],   &quot;schemes&quot; : [ &quot;https&quot;, &quot;http&quot; ],   &quot;paths&quot; : {     &quot;\/pet&quot; : {       &quot;post&quot; : {         &quot;tags&quot; : [ &quot;pet&quot; ],         &quot;summary&quot; : &quot;Add a new pet to the store&quot;,         &quot;operationId&quot; : &quot;addPet&quot;,         &quot;consumes&quot; : [ &quot;application\/json&quot; ],         &quot;produces&quot; : [ &quot;application\/json&quot; ],         &quot;parameters&quot; : [ {           &quot;in&quot; : &quot;body&quot;,           &quot;name&quot; : &quot;body&quot;,           &quot;description&quot; : &quot;Pet object that needs to be added to the store&quot;,           &quot;required&quot; : true,           &quot;schema&quot; : {             &quot;$ref&quot; : &quot;#\/definitions\/Pet&quot;           }         } ],         &quot;responses&quot; : {           &quot;405&quot; : {             &quot;description&quot; : &quot;Invalid input&quot;           }         }       }     }   },   &quot;definitions&quot; : {     &quot;Category&quot; : {       &quot;type&quot; : &quot;object&quot;,       &quot;properties&quot; : {         &quot;id&quot; : {           &quot;type&quot; : &quot;integer&quot;,           &quot;format&quot; : &quot;int64&quot;         },         &quot;name&quot; : {           &quot;type&quot; : &quot;string&quot;         }       }     },     &quot;Tag&quot; : {       &quot;type&quot; : &quot;object&quot;,       &quot;properties&quot; : {         &quot;id&quot; : {           &quot;type&quot; : &quot;integer&quot;,           &quot;format&quot; : &quot;int64&quot;         },         &quot;name&quot; : {           &quot;type&quot; : &quot;string&quot;         }       }     },     &quot;Pet&quot; : {       &quot;type&quot; : &quot;object&quot;,       &quot;required&quot; : [ &quot;name&quot;, &quot;photoUrls&quot; ],       &quot;properties&quot; : {         &quot;id&quot; : {           &quot;type&quot; : &quot;integer&quot;,           &quot;format&quot; : &quot;int64&quot;         },         &quot;category&quot; : {           &quot;$ref&quot; : &quot;#\/definitions\/Category&quot;         },         &quot;name&quot; : {           &quot;type&quot; : &quot;string&quot;,           &quot;example&quot; : &quot;doggie&quot;         },         &quot;photoUrls&quot; : {           &quot;type&quot; : &quot;array&quot;,           &quot;items&quot; : {             &quot;type&quot; : &quot;string&quot;           }         },         &quot;tags&quot; : {           &quot;type&quot; : &quot;array&quot;,           &quot;items&quot; : {             &quot;$ref&quot; : &quot;#\/definitions\/Tag&quot;           }         },         &quot;status&quot; : {           &quot;type&quot; : &quot;string&quot;,           &quot;description&quot; : &quot;pet status in the store&quot;,           &quot;enum&quot; : [ &quot;available&quot;, &quot;pending&quot;, &quot;sold&quot; ]         }       }     }   } }<\/code><\/pre>\n<\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041d\u0430\u0433\u043b\u044f\u0434\u043d\u044b\u0439 \u0432\u0438\u0434 \u0432 Swagger\u00a0UI<\/b><\/p>\n<div class=\"spoiler_text\">\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/wm\/tp\/_y\/wmtp_yayfkblzb4aztgx9xfbgvy.png\" alt=\"\u041d\u0430\u0433\u043b\u044f\u0434\u043d\u044b\u0439 \u0432\u0438\u0434 \u0432 Swagger\u00a0UI\"><\/p>\n<\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u042d\u043a\u0441\u043f\u043e\u0440\u0442 \u0438\u0437 Swagger\u00a0Editor<\/b><\/p>\n<div class=\"spoiler_text\">\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/ey\/xe\/8o\/eyxe8o7tfmmraehfwxmbk3nyasi.png\" alt=\"\u042d\u043a\u0441\u043f\u043e\u0440\u0442 \u0438\u0437 Swagger\u00a0Editor\"><\/p>\n<\/div>\n<\/div>\n<p>  <\/p>\n<p>\u0423 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0438\u0434\u0435\u043d\u0442\u0438\u0447\u043d\u044b \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440. \u041f\u0440\u0438\u043c\u0435\u0440 \u0444\u0430\u0439\u043b\u0430 <code>go-client-generated\/model_pet.go<\/code> \u0438 <code>go-server-server-generated\/go\/model_pet.go<\/code>.<\/p>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041c\u043e\u0434\u0435\u043b\u044c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b Pet \u0432 \u043a\u043b\u0438\u0435\u043d\u0442\u0435 \u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0435<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"go\">\/*  * Swagger Petstore  *  * No description provided (generated by Swagger Codegen https:\/\/github.com\/swagger-api\/swagger-codegen)  *  * API version: 1.0.0  * Generated by: Swagger Codegen (https:\/\/github.com\/swagger-api\/swagger-codegen.git)  *\/  package swagger  type Pet struct {     Id int64           `json:&quot;id,omitempty&quot;`     Category *Category `json:&quot;category,omitempty&quot;`     Name string        `json:&quot;name&quot;`     PhotoUrls []string `json:&quot;photoUrls&quot;`     Tags []Tag         `json:&quot;tags,omitempty&quot;`     \/\/ pet status in the store     Status string `json:&quot;status,omitempty&quot;` }<\/code><\/pre>\n<\/div>\n<\/div>\n<p>  <\/p>\n<p>\u041a\u043b\u0438\u0435\u043d\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0442\u0430\u043a \u0436\u0435 \u0432 \u0441\u0435\u0431\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u0430 \u0441\u0435\u0440\u0432\u0435\u0440 endpiont&#8217;\u044b \u0438 \u0437\u0430\u0433\u043b\u0443\u0448\u043a\u0438 \u0434\u043b\u044f \u0438\u0445 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438.<\/p>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0430<\/b><\/p>\n<div class=\"spoiler_text\">\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/4z\/bx\/ww\/4zbxwwsnnlg_ne_ngvcqmyxujh4.png\" alt=\"\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0430\"><\/p>\n<\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430<\/b><\/p>\n<div class=\"spoiler_text\">\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/bm\/ze\/4a\/bmze4a1htcmybly84wqgrgb4ffg.png\" alt=\"\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430\"><\/p>\n<\/div>\n<\/div>\n<p>  <\/p>\n<p>\u0421\u0430\u043c\u044b\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442, \u0432 \u043f\u043b\u0430\u043d\u0435 \u0441\u0432\u043e\u0435\u0433\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430. \u0421\u0438\u043b\u044c\u043d\u0430\u044f \u0441\u0442\u043e\u0440\u043e\u043d\u0430, \u044d\u0442\u043e \u0442\u043e \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u0434 \u043f\u043e\u0447\u0442\u0438 \u043f\u043e\u0434 \u0432\u0441\u0435 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u044f\u0437\u044b\u043a\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<p>  <\/p>\n<h1 id=\"go-swagger\">go-swagger<\/h1>\n<p>  <\/p>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u200a \u2014 \u200a<a href=\"https:\/\/github.com\/go-swagger\/go-swagger\" rel=\"nofollow\">go-swagger\/go-swagger<\/a>. \u041e\u043d \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u0443 go \u043f\u043e\u043b\u043d\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u043f\u043e\u043b\u043d\u043e\u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0445 API-\u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 Swagger API: \u0441\u0435\u0440\u0432\u0435\u0440, \u043a\u043b\u0438\u0435\u043d\u0442 \u0438 \u043c\u043e\u0434\u0435\u043b\u044c \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0421\u043e\u0437\u0434\u0430\u0435\u0442 \u0441\u0435\u0440\u0432\u0435\u0440 \u0438\u0437 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 Swagger<\/li>\n<li>\u0413\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0438\u0437 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 Swagger<\/li>\n<li>\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u0439, \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u043c\u044b\u0445 jsonschema \u0438 swagger, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u043f\u043e\u043b\u0438\u043c\u043e\u0440\u0444\u0438\u0437\u043c<\/li>\n<li>\u0421\u043e\u0437\u0434\u0430\u0435\u0442 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e swagger \u0438\u0437 \u0430\u043d\u043d\u043e\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 go<\/li>\n<li>\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u043e swagger \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0435\u0439<\/li>\n<li>\u041e\u0442\u043b\u0438\u0447\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438, \u0441 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f\u043c\u0438 \u043f\u043e\u0441\u0442\u0430\u0432\u0449\u0438\u043a\u043e\u0432 \u0438 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c\u044b\u043c\u0438 \u0448\u0430\u0431\u043b\u043e\u043d\u0430\u043c\u0438<\/li>\n<\/ul>\n<p>  <\/p>\n<h3 id=\"server\">\u0421\u0435\u0440\u0432\u0435\u0440<\/h3>\n<p>  <\/p>\n<p>\u041a\u043e\u043c\u0430\u043d\u0434\u0430 \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">$ swagger generate server -f .\/swagger.json<\/code><\/pre>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0421\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b\u00a0\u0441\u0435\u0440\u0432\u0435\u0440\u0430<\/b><\/p>\n<div class=\"spoiler_text\">\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/su\/a8\/c8\/sua8c8w8yevd6cg9wlocjpouafo.png\" alt=\"\u0421\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b\u00a0\u0441\u0435\u0440\u0432\u0435\u0440\u0430\"><\/p>\n<\/div>\n<\/div>\n<p>  <\/p>\n<p>\u0412\u0441\u0435 \u0444\u0430\u0439\u043b\u044b, \u043a\u0440\u043e\u043c\u0435 \u043e\u0434\u043d\u043e\u0433\u043e, \u0431\u0443\u0434\u0443\u0442 \u043f\u0435\u0440\u0435\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b \u043f\u043e\u0441\u043b\u0435 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u044b. \u0411\u0443\u0434\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u044b \u043f\u0440\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043a\u043e\u0434\u0430 \u043f\u043e\u0434 \u043d\u043e\u0432\u044b\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438.<\/p>\n<p>  <\/p>\n<p>\u042d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b \u2014 <code>go-swagger-service\/restapi\/configure_swagger_petstore.go<\/code>. \u0412 \u043d\u0435\u043c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0448 \u0441\u0435\u0440\u0432\u0435\u0440: \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c handler&#8217;\u044b, \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0442\u044c middleware, \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u043e\u0442\u0432\u0435\u0442\u044b, \u0438 \u0432\u0441\u0435 \u0447\u0442\u043e \u043d\u0430\u043c \u043c\u043e\u0436\u0435\u0442 \u0435\u0449\u0435 \u0431\u044b\u0442\u044c \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u043c.<\/p>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0424\u0430\u0439\u043b \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0439 \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0439 \u043c\u0435\u0442\u043e\u0434<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"go\">\/\/ This file is safe to edit. Once it exists it will not be overwritten  package restapi  import (     &quot;crypto\/tls&quot;     &quot;net\/http&quot;      errors &quot;github.com\/go-openapi\/errors&quot;     runtime &quot;github.com\/go-openapi\/runtime&quot;     middleware &quot;github.com\/go-openapi\/runtime\/middleware&quot;      &quot;go-generator\/go-swagger-service\/restapi\/operations&quot;     &quot;go-generator\/go-swagger-service\/restapi\/operations\/pet&quot; )  \/\/go:generate swagger generate server --target ..\/..\/go-swagger --name SwaggerPetstore --spec ..\/..\/swagger.json  func configureFlags(api *operations.SwaggerPetstoreAPI) {     \/\/ api.CommandLineOptionsGroups = []swag.CommandLineOptionsGroup{ ... } }  func configureAPI(api *operations.SwaggerPetstoreAPI) http.Handler {     \/\/ configure the api here     api.ServeError = errors.ServeError      \/\/ Set your custom logger if needed. Default one is log.Printf     \/\/ Expected interface func(string, ...interface{})     \/\/     \/\/ Example:     \/\/ api.Logger = log.Printf      api.JSONConsumer = runtime.JSONConsumer()      api.JSONProducer = runtime.JSONProducer()      if api.PetAddPetHandler == nil {         api.PetAddPetHandler = pet.AddPetHandlerFunc(func(params pet.AddPetParams) middleware.Responder {             return middleware.NotImplemented(&quot;operation pet.AddPet has not yet been implemented&quot;)         })     }      api.ServerShutdown = func() {}      return setupGlobalMiddleware(api.Serve(setupMiddlewares)) }  \/\/ The TLS configuration before HTTPS server starts. func configureTLS(tlsConfig *tls.Config) {     \/\/ Make all necessary changes to the TLS configuration here. }  \/\/ As soon as server is initialized but not run yet, this function will be called. \/\/ If you need to modify a config, store server instance to stop it individually later, this is the place. \/\/ This function can be called multiple times, depending on the number of serving schemes. \/\/ scheme value will be set accordingly: &quot;http&quot;, &quot;https&quot; or &quot;unix&quot; func configureServer(s *http.Server, scheme, addr string) { }  \/\/ The middleware configuration is for the handler executors. These do not apply to the swagger.json document. \/\/ The middleware executes after routing but before authentication, binding and validation func setupMiddlewares(handler http.Handler) http.Handler {     return handler }  \/\/ The middleware configuration happens before anything, this middleware also applies to serving the swagger.json document. \/\/ So this is a good place to plug in a panic handling middleware, logging and metrics func setupGlobalMiddleware(handler http.Handler) http.Handler {     return handler }<\/code><\/pre>\n<\/div>\n<\/div>\n<p>  <\/p>\n<p>\u041f\u0440\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044f \u0432\u0441\u0435\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0438 \u0438\u0445 \u043f\u043e\u043b\u0435\u0439. \u0418 \u043e\u0442\u0434\u0430\u0435\u0442\u0441\u044f \u043e\u0442\u0432\u0435\u0442 \u0441\u043e \u0441\u0442\u0430\u0442\u0443\u0441\u043e\u043c <code>422<\/code> \u0438 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0438.<\/p>\n<p>  <\/p>\n<p>\u041f\u043e\u043b\u044f \u0432\u0430\u043b\u0438\u0434\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u043d\u0430 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u043c \u0432 swagger \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438. \u0422\u0430\u043a\u0438\u0435 \u043a\u0430\u043a <code>enum<\/code>, <code>required<\/code>, <code>type<\/code>, <code>maximum<\/code> \u0438 \u0434\u0440\u0443\u0433\u0438\u0435.<\/p>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041e\u0431\u044a\u0435\u043a\u0442 Pet \u0438 \u0435\u0433\u043e \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044f<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"go\">\/\/ Code generated by go-swagger; DO NOT EDIT.  package models  \/\/ This file was generated by the swagger tool. \/\/ Editing this file might prove futile when you re-run the swagger generate command  import (     &quot;encoding\/json&quot;     &quot;strconv&quot;      strfmt &quot;github.com\/go-openapi\/strfmt&quot;      &quot;github.com\/go-openapi\/errors&quot;     &quot;github.com\/go-openapi\/swag&quot;     &quot;github.com\/go-openapi\/validate&quot; )  \/\/ Pet pet \/\/ swagger:model Pet type Pet struct {      \/\/ category     Category *Category `json:&quot;category,omitempty&quot;`      \/\/ id     ID int64 `json:&quot;id,omitempty&quot;`      \/\/ name     \/\/ Required: true     Name *string `json:&quot;name&quot;`      \/\/ photo urls     \/\/ Required: true     PhotoUrls []string `json:&quot;photoUrls&quot;`      \/\/ pet status in the store     \/\/ Enum: [available pending sold]     Status string `json:&quot;status,omitempty&quot;`      \/\/ tags     Tags []*Tag `json:&quot;tags&quot;` }  \/\/ Validate validates this pet func (m *Pet) Validate(formats strfmt.Registry) error {     var res []error      if err := m.validateCategory(formats); err != nil {         res = append(res, err)     }      if err := m.validateName(formats); err != nil {         res = append(res, err)     }      if err := m.validatePhotoUrls(formats); err != nil {         res = append(res, err)     }      if err := m.validateStatus(formats); err != nil {         res = append(res, err)     }      if err := m.validateTags(formats); err != nil {         res = append(res, err)     }      if len(res) &gt; 0 {         return errors.CompositeValidationError(res...)     }     return nil }  func (m *Pet) validateCategory(formats strfmt.Registry) error {      if swag.IsZero(m.Category) { \/\/ not required         return nil     }      if m.Category != nil {         if err := m.Category.Validate(formats); err != nil {             if ve, ok := err.(*errors.Validation); ok {                 return ve.ValidateName(&quot;category&quot;)             }             return err         }     }      return nil }  func (m *Pet) validateName(formats strfmt.Registry) error {      if err := validate.Required(&quot;name&quot;, &quot;body&quot;, m.Name); err != nil {         return err     }      return nil }  func (m *Pet) validatePhotoUrls(formats strfmt.Registry) error {      if err := validate.Required(&quot;photoUrls&quot;, &quot;body&quot;, m.PhotoUrls); err != nil {         return err     }      return nil }  var petTypeStatusPropEnum []interface{}  func init() {     var res []string     if err := json.Unmarshal([]byte(`[&quot;available&quot;,&quot;pending&quot;,&quot;sold&quot;]`), &amp;res); err != nil {         panic(err)     }     for _, v := range res {         petTypeStatusPropEnum = append(petTypeStatusPropEnum, v)     } }  const (      \/\/ PetStatusAvailable captures enum value &quot;available&quot;     PetStatusAvailable string = &quot;available&quot;      \/\/ PetStatusPending captures enum value &quot;pending&quot;     PetStatusPending string = &quot;pending&quot;      \/\/ PetStatusSold captures enum value &quot;sold&quot;     PetStatusSold string = &quot;sold&quot; )  \/\/ prop value enum func (m *Pet) validateStatusEnum(path, location string, value string) error {     if err := validate.Enum(path, location, value, petTypeStatusPropEnum); err != nil {         return err     }     return nil }  func (m *Pet) validateStatus(formats strfmt.Registry) error {      if swag.IsZero(m.Status) { \/\/ not required         return nil     }      \/\/ value enum     if err := m.validateStatusEnum(&quot;status&quot;, &quot;body&quot;, m.Status); err != nil {         return err     }      return nil }  func (m *Pet) validateTags(formats strfmt.Registry) error {      if swag.IsZero(m.Tags) { \/\/ not required         return nil     }      for i := 0; i &lt; len(m.Tags); i++ {         if swag.IsZero(m.Tags[i]) { \/\/ not required             continue         }          if m.Tags[i] != nil {             if err := m.Tags[i].Validate(formats); err != nil {                 if ve, ok := err.(*errors.Validation); ok {                     return ve.ValidateName(&quot;tags&quot; + &quot;.&quot; + strconv.Itoa(i))                 }                 return err             }         }      }      return nil }  \/\/ MarshalBinary interface implementation func (m *Pet) MarshalBinary() ([]byte, error) {     if m == nil {         return nil, nil     }     return swag.WriteJSON(m) }  \/\/ UnmarshalBinary interface implementation func (m *Pet) UnmarshalBinary(b []byte) error {     var res Pet     if err := swag.ReadJSON(b, &amp;res); err != nil {         return err     }     *m = res     return nil }<\/code><\/pre>\n<\/div>\n<\/div>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0441\u0442\u0430\u0440\u0442\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043a\u043e\u043c\u0430\u043d\u0434\u0430<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">$ run .\/go-swagger-service\/cmd\/swagger-petstore-server\/main.go --port 8090<\/code><\/pre>\n<p>  <\/p>\n<h3 id=\"klient\">\u041a\u043b\u0438\u0435\u043d\u0442<\/h3>\n<p>  <\/p>\n<p>\u041a\u043e\u043c\u0430\u043d\u0434\u0430 \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">$ swagger generate client -f .\/swagger.json<\/code><\/pre>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0421\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b\u00a0\u043a\u043b\u0438\u0435\u043d\u0442\u0430<\/b><\/p>\n<div class=\"spoiler_text\">\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/qc\/bh\/n3\/qcbhn3zttrbaxi2bsb12b3j5gxo.png\" alt=\"\u0421\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b\u00a0\u043a\u043b\u0438\u0435\u043d\u0442\u0430\"><\/p>\n<\/div>\n<\/div>\n<p>  <\/p>\n<p>\u042d\u0442\u0430 \u0444\u0438\u0447\u0430 \u043e\u0447\u0435\u043d\u044c \u043f\u043e\u043b\u0435\u0437\u043d\u0430, \u0434\u043b\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f api-sdk. \u041a\u043b\u0438\u0435\u043d\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432 \u0441\u0435\u0431\u0435 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043c\u043e\u0434\u0435\u043b\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432, \u043d\u043e \u0438 \u043c\u0435\u0442\u043e\u0434\u044b \u0434\u043b\u044f \u0438\u0445 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u0437\u0430\u043f\u0440\u043e\u0441, \u0435\u0433\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0443 \u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043e\u0442\u0432\u0435\u0442\u0430.<\/p>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041e\u0431\u0435\u0440\u0442\u043a\u0430 \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043d\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"go\">\/\/ Code generated by go-swagger; DO NOT EDIT.  package pet  \/\/ This file was generated by the swagger tool. \/\/ Editing this file might prove futile when you re-run the swagger generate command  import (     &quot;github.com\/go-openapi\/runtime&quot;      strfmt &quot;github.com\/go-openapi\/strfmt&quot; )  \/\/ New creates a new pet API client. func New(transport runtime.ClientTransport, formats strfmt.Registry) *Client {     return &amp;Client{transport: transport, formats: formats} }  \/* Client for pet API *\/ type Client struct {     transport runtime.ClientTransport     formats   strfmt.Registry }  \/* AddPet adds a new pet to the store *\/ func (a *Client) AddPet(params *AddPetParams) error {     \/\/ TODO: Validate the params before sending     if params == nil {         params = NewAddPetParams()     }      _, err := a.transport.Submit(&amp;runtime.ClientOperation{         ID:                 &quot;addPet&quot;,         Method:             &quot;POST&quot;,         PathPattern:        &quot;\/pet&quot;,         ProducesMediaTypes: []string{&quot;application\/json&quot;},         ConsumesMediaTypes: []string{&quot;application\/json&quot;},         Schemes:            []string{&quot;http&quot;, &quot;https&quot;},         Params:             params,         Reader:             &amp;AddPetReader{formats: a.formats},         Context:            params.Context,         Client:             params.HTTPClient,     })     if err != nil {         return err     }     return nil }  \/\/ SetTransport changes the transport on the client func (a *Client) SetTransport(transport runtime.ClientTransport) {     a.transport = transport }<\/code><\/pre>\n<\/div>\n<\/div>\n<p>  <\/p>\n<p>\u0415\u0441\u0442\u044c \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0438\u0437 \u043a\u043e\u0434\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u041e\u0431 \u044d\u0442\u043e\u043c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c <a href=\"https:\/\/goswagger.io\/generate\/spec.html\" rel=\"nofollow\">Generate a spec from source code<\/a>.<\/p>\n<p>  <\/p>\n<p>\u042f \u043e\u043f\u0438\u0441\u0430\u043b \u043d\u0435 \u0432\u0441\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u044d\u0442\u043e\u0433\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430. \u041e\u043d\u043e \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u0430\u043c\u044b\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u043c, \u0433\u0438\u0431\u043a\u0438\u043c \u0438 \u043f\u043e\u043b\u043d\u044b\u043c \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 swagger \u0438 \u043a\u043e\u0434\u043e\u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0435\u0439.<\/p>\n<p>  <\/p>\n<h1 id=\"grpc-gateway\">grpc-gateway<\/h1>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 swagger \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438. <a href=\"https:\/\/github.com\/grpc-ecosystem\/grpc-gateway\" rel=\"nofollow\">grpc-ecosystem\/grpc-gateway<\/a> \u2014 \u200a\u044d\u0442\u043e \u043f\u043b\u0430\u0433\u0438\u043d <code>protoc<\/code>. \u041e\u043d \u0447\u0438\u0442\u0430\u0435\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 gRPC \u0438 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u043e\u0431\u0440\u0430\u0442\u043d\u044b\u0439 \u043f\u0440\u043e\u043a\u0441\u0438-\u0441\u0435\u0440\u0432\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0438\u0442 RESTful JSON API \u0432 gRPC. \u042d\u0442\u043e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440 \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438 \u0441 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u043c\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438 \u0432 \u0432\u0430\u0448\u0435\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0438 gRPC.<\/p>\n<p>  <\/p>\n<p>\u042d\u0442\u043e\u0442 \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d \u043d\u0430 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 HTTP + JSON \u0432\u0430\u0448\u0435\u0439 \u0441\u043b\u0443\u0436\u0431\u0435 gRPC. \u042d\u0442\u043e \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u0432\u0430\u043c \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u0432\u043e\u0438 API \u0432 \u0441\u0442\u0438\u043b\u0435 gRPC \u0438 RESTful \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e.<\/p>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0412\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u044b grpc-gateway \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 reverse-proxy<\/b><\/p>\n<div class=\"spoiler_text\">\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/qt\/pa\/r2\/qtpar2s-2ax3soxtvwffkzoufo4.png\" alt=\"\u0412\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u044b grpc-gateway \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 reverse-proxy\"><\/p>\n<\/div>\n<\/div>\n<p>  <\/p>\n<p>\u0418 \u043a\u0430\u043a \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0431\u043e\u043d\u0443\u0441 \u0442\u0430\u043a \u0436\u0435 \u0435\u0441\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f swagger.json \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c protoc-gen-swagger.<\/p>\n<p>  <\/p>\n<p>\u0421\u0435\u0439\u0447\u0430\u0441 \u043c\u044b \u0441\u043e\u0431\u0435\u0440\u0435\u043c \u043d\u0430\u0448 \u0441\u0435\u0440\u0432\u0435\u0440 \u0438 \u043f\u0440\u043e\u0439\u0434\u0435\u043c\u0441\u044f \u043f\u043e \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u0438\u0437 \u0448\u0430\u0433\u043e\u0432. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c \u043d\u0430\u0448\u0438 \u0441\u0431\u043e\u0440\u0449\u0438\u043a\u0438.<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">$ go install \\     github.com\/grpc-ecosystem\/grpc-gateway\/protoc-gen-grpc-gateway \\     github.com\/grpc-ecosystem\/grpc-gateway\/protoc-gen-swagger \\     github.com\/golang\/protobuf\/protoc-gen-go<\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043d\u0430\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0432\u043e\u0442 \u0442\u0430\u043a\u043e\u0439\u00a0<code>.proto<\/code> \u0444\u0430\u0439\u043b<\/p>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041f\u0440\u0438\u043c\u0435\u0440 protobuf \u0444\u0430\u0439\u043b\u0430 \u0441 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044f\u043c\u0438<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"plaintext\">syntax = &quot;proto3&quot;;  import &quot;google\/api\/annotations.proto&quot;; import &quot;google\/protobuf\/empty.proto&quot;;  package pet;  message AddPetRequest {     int64 id = 1;     message Category {         int64 id = 1;         string name = 2;     }     Category category = 2;     string name = 3;     repeated string photo_urls = 4;     message Tag {         int64 id = 1;         string name = 2;     }     repeated Tag tags = 5;     \/\/pet status in the store     enum Status {         available = 0;         pending = 1;         sold = 2;     }     Status status = 6; }  service PetService {     rpc AddPet (AddPetRequest) returns (google.protobuf.Empty) {         option (google.api.http) = {             post: &quot;\/pet&quot;             body: &quot;*&quot;         };     } }<\/code><\/pre>\n<\/div>\n<\/div>\n<p>  <\/p>\n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u0438\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 gRPC stub:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">$ protoc -I\/usr\/local\/include -I. \\   -I$GOPATH\/src \\   -I$GOPATH\/src\/github.com\/grpc-ecosystem\/grpc-gateway\/third_party\/googleapis \\   --go_out=plugins=grpc:. \\   pet.proto<\/code><\/pre>\n<p>  <\/p>\n<p>\u0423 \u043d\u0430\u0441 \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f \u0444\u0430\u0439\u043b\u0438\u043a <code>pet.pb.go<\/code>. \u0418 \u0441\u0440\u0430\u0437\u0443 \u0436\u0435 \u0441\u043e\u0431\u0435\u0440\u0435\u043c reverse-proxy \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>protoc-gen-grpc-gateway<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">$ protoc -I\/usr\/local\/include -I. \\   -I$GOPATH\/src \\   -I$GOPATH\/src\/github.com\/grpc-ecosystem\/grpc-gateway\/third_party\/googleapis \\   --grpc-gateway_out=logtostderr=true:. \\   pet.proto<\/code><\/pre>\n<p>  <\/p>\n<p>\u0424\u0430\u0439\u043b <code>pet.pb.gw.go<\/code> \u0433\u043e\u0442\u043e\u0432. \u042d\u0442\u043e \u0438 \u0435\u0441\u0442\u044c \u043d\u0430\u0448 gateway. \u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0431\u0435\u0440\u0435\u043c <code>pet.swagger<\/code>.json \u0443\u0442\u0438\u043b\u0438\u0442\u043e\u0439 <code>protoc-gen-swagger<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">$ protoc -I\/usr\/local\/include -I. \\   -I$GOPATH\/src \\   -I$GOPATH\/src\/github.com\/grpc-ecosystem\/grpc-gateway\/third_party\/googleapis \\   --swagger_out=logtostderr=true:. \\   pet.proto<\/code><\/pre>\n<p>  <\/p>\n<p>\u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 PetServiceServer.<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">\/\/ PetServiceServer is the server API for PetService service. type PetServiceServer interface {    AddPet(context.Context, *AddPetRequest) (*empty.Empty, error) }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0410 \u043a\u043e\u0434 \u0434\u043b\u044f \u0441\u0442\u0430\u0440\u0442\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0432\u043e\u0442 \u0442\u0430\u043a:<\/p>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">main.go<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"go\">package pet  import (     &quot;context&quot;     &quot;flag&quot;     &quot;net\/http&quot;      &quot;github.com\/golang\/glog&quot;     &quot;github.com\/grpc-ecosystem\/grpc-gateway\/runtime&quot;     gw &quot;grpc-gateway\/pet&quot;     &quot;grpc-gateway\/service&quot; )  func run() error {     ctx := context.Background()     ctx, cancel := context.WithCancel(ctx)     defer cancel()      mux := runtime.NewServeMux()     err := gw.RegisterPetServiceHandlerServer(ctx, mux, &amp;service.PetService{})     if err != nil {         return err     }      return http.ListenAndServe(&quot;:8081&quot;, mux) }  func main() {     flag.Parse()     defer glog.Flush()      if err := run(); err != nil {         glog.Fatal(err)     } }<\/code><\/pre>\n<\/div>\n<\/div>\n<p>  <\/p>\n<p>\u041a\u043e\u0433\u0434\u0430 \u043c\u044b \u0441\u043e\u0431\u0440\u0430\u043b\u0438 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0436\u0438\u0432\u0443\u0447\u0438\u0439 \u043f\u0440\u043e\u0434\u0443\u043a\u0442, \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a \u0442\u043e\u043d\u043a\u043e\u0441\u0442\u044f\u043c \u0435\u0433\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438. \u0418\u0445 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u043c\u043e\u0435\u0439 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435, \u0441 \u0431\u043e\u043b\u0435\u0435 \u0433\u043b\u0443\u0431\u043e\u043a\u0438\u043c \u0438 \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u044b\u043c \u0440\u0430\u0437\u0431\u043e\u0440\u043e\u043c \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u043a \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044e \u0432\u0435\u0431-\u0441\u0435\u0440\u0432\u0435\u0440\u0430.\u00a0<\/p>\n<p>  <\/p>\n<h1 id=\"swag\">Swag<\/h1>\n<p>  <\/p>\n<p>Swag \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 Go \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e Swagger 2.0. \u041d\u0430\u043f\u0438\u0441\u0430\u043d\u043e \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432 \u0434\u043b\u044f \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u0432\u0435\u0431-\u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u043e\u0432 Go. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0431\u044b\u0441\u0442\u0440\u043e \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/github.com\/swaggo\/swag\" rel=\"nofollow\">swaggo\/swag<\/a> \u0432 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 Go (\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f Swagger UI).<br \/>  \u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0435 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0438:<\/p>\n<p>  <\/p>\n<ul>\n<li>gin<\/li>\n<li>echo<\/li>\n<li>buffalo<\/li>\n<li>net\/http<\/li>\n<\/ul>\n<p>  <\/p>\n<p>Swagger \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 \u0434\u0435\u043b\u044f\u0442\u0441\u044f \u043d\u0430 \u0434\u0432\u0435 \u0447\u0430\u0441\u0442\u0438, \u043e\u0431\u0449\u0435\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0438 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e endpoint&#8217;\u043e\u0432. \u041d\u0438\u0436\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u044b \u0438\u0445 \u043f\u0440\u0438\u043c\u0435\u0440\u044b.<\/p>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041e\u0431\u0449\u0438\u0435 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 API<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"go\">\/\/ @title Swagger Example API \/\/ @version 1.0 \/\/ @description This is a sample server celler server. \/\/ @termsOfService http:\/\/swagger.io\/terms\/  \/\/ @contact.name API Support \/\/ @contact.url http:\/\/www.swagger.io\/support \/\/ @contact.email support@swagger.io  \/\/ @license.name Apache 2.0 \/\/ @license.url http:\/\/www.apache.org\/licenses\/LICENSE-2.0.html  \/\/ @host localhost:8080 \/\/ @BasePath \/api\/v1 \/\/ @query.collection.format multi  \/\/ @securityDefinitions.basic BasicAuth  \/\/ @securityDefinitions.apikey ApiKeyAuth \/\/ @in header \/\/ @name Authorization  \/\/ @securitydefinitions.oauth2.application OAuth2Application \/\/ @tokenUrl https:\/\/example.com\/oauth\/token \/\/ @scope.write Grants write access \/\/ @scope.admin Grants read and write access to administrative information  \/\/ @securitydefinitions.oauth2.implicit OAuth2Implicit \/\/ @authorizationurl https:\/\/example.com\/oauth\/authorize \/\/ @scope.write Grants write access \/\/ @scope.admin Grants read and write access to administrative information  \/\/ @securitydefinitions.oauth2.password OAuth2Password \/\/ @tokenUrl https:\/\/example.com\/oauth\/token \/\/ @scope.read Grants read access \/\/ @scope.write Grants write access \/\/ @scope.admin Grants read and write access to administrative information  \/\/ @securitydefinitions.oauth2.accessCode OAuth2AccessCode \/\/ @tokenUrl https:\/\/example.com\/oauth\/token \/\/ @authorizationurl https:\/\/example.com\/oauth\/authorize \/\/ @scope.admin Grants read and write access to administrative information  \/\/ @x-extension-openapi {&quot;example&quot;: &quot;value on a json format&quot;}  func main() {     \/\/ ...  }<\/code><\/pre>\n<\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0410\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 API-\u043c\u0435\u0442\u043e\u0434\u043e\u0432<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"go\">\/\/ ShowAccount godoc \/\/ @Summary Show a account \/\/ @Description get string by ID \/\/ @ID get-string-by-int \/\/ @Accept  json \/\/ @Produce  json \/\/ @Param id path int true &quot;Account ID&quot; \/\/ @Success 200 {object} model.Account \/\/ @Header 200 {string} Token &quot;qwerty&quot; \/\/ @Failure 400 {object} httputil.HTTPError \/\/ @Failure 404 {object} httputil.HTTPError \/\/ @Failure 500 {object} httputil.HTTPError \/\/ @Router \/accounts\/{id} [get]  func (c *ExampleController) ShowAccount(ctx *contex.Context) {     \/\/ ... }<\/code><\/pre>\n<\/div>\n<\/div>\n<p>  <\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0438\u0441\u0447\u0435\u0440\u043f\u044b\u0432\u0430\u044e\u0449\u0430\u044f \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0441 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u043c\u0438 \u0435\u0441\u0442\u044c \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 \u043d\u0430 <a href=\"https:\/\/github.com\/swaggo\/swag\" rel=\"nofollow\">github<\/a>.<\/p>\n<p>  <\/p>\n<p>\u041e\u0442\u043b\u0438\u0447\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0443\u0436\u0435 \u043f\u043e \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u043c, \u043f\u0440\u043e\u0432\u0435\u0440\u0435\u043d\u043d\u044b\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c, \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u044e\u0449\u0438\u043c\u0441\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u043c.<\/p>\n<p>  <\/p>\n<h1 id=\"vyvod\">\u0412\u044b\u0432\u043e\u0434<\/h1>\n<p>  <\/p>\n<p>\u0421\u0435\u0439\u0447\u0430\u0441 \u043c\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0442\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0438\u043b\u0438 \u043d\u0430\u0448\u0435 \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u0441 swagger \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0435\u0439. \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043b\u0438 \u0441\u043f\u043e\u0441\u043e\u0431\u044b \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u043a\u043e\u0434\u0430 \u0438 \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u043a \u043d\u0435\u043c\u0443.<\/p>\n<p>  <\/p>\n<p>\u0418 \u044f \u0434\u0430\u0436\u0435 \u0434\u0443\u043c\u0430\u044e, \u0447\u0442\u043e \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0443\u0436\u0435 \u0432\u044b\u0431\u0440\u0430\u043b \u0434\u043b\u044f \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0432\u043e\u0435\u0433\u043e \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0438\u043b\u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u0438\u043b\u0438 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0443\u0436\u0435 \u043d\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u044b\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u044b.<\/p>\n<\/div>\n<p> \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\/post\/496098\/\"> https:\/\/habr.com\/ru\/post\/496098\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/post\/496098\/\">\n<p>\u042f \u0431\u044b \u0445\u043e\u0442\u0435\u043b \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u0432\u0430\u043c \u043e \u0442\u043e\u043c \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u0441\u0442\u0440\u043e \u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0432\u0435\u0431 \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0430 \u044f\u0437\u044b\u043a\u0435 Golang \u0441 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0435\u0439 \u043a \u043d\u0435\u043c\u0443. \u0418 \u043e \u0442\u043e\u043c \u043a\u0430\u043a\u0438\u0435 \u0435\u0441\u0442\u044c \u043f\u043e\u0434\u0445\u043e\u0434\u044b \u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u0438\u0445 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438<\/p>\n<p>  <\/p>\n<p>\u0421\u0435\u0433\u043e\u0434\u043d\u044f \u043c\u044b \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c \u044d\u0442\u0438 \u0433\u043e\u0442\u043e\u0432\u044b\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b:<\/p>\n<p>  <\/p>\n<ul>\n<li><a href=\"#swagger-codegen\">swagger-api\/swagger-codegen<\/a><\/li>\n<li><a href=\"#go-swagger\">go-swagger\/go-swagger<\/a><\/li>\n<li><a href=\"#grpc-gateway\">grpc-ecosystem\/grpc-gateway<\/a><\/li>\n<li><a href=\"#swag\">swaggo\/swag<\/a><\/li>\n<\/ul>\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-301456","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/301456","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=301456"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/301456\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=301456"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=301456"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=301456"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}