{"id":25128,"date":"2019-12-17T08:00:26","date_gmt":"2019-12-16T23:00:26","guid":{"rendered":"https:\/\/www.techscore.com\/blog\/?p=25128"},"modified":"2019-12-17T17:13:40","modified_gmt":"2019-12-17T08:13:40","slug":"openapi-generator-oauth2-accesstoken","status":"publish","type":"post","link":"https:\/\/www.techscore.com\/blog\/2019\/12\/17\/openapi-generator-oauth2-accesstoken\/","title":{"rendered":"OpenAPI Generator \u3067 OAuth2 \u30a2\u30af\u30bb\u30b9\u30c8\u30fc\u30af\u30f3\u767a\u884c\u306e\u30b3\u30fc\u30c9\u307e\u3067\u751f\u6210\u3057\u3066\u307f\u308b"},"content":{"rendered":"

\u3053\u308c\u306f TECHSCORE Advent Calendar 2019<\/a> \u306e17\u65e5\u76ee\u306e\u8a18\u4e8b\u3067\u3059\u3002<\/p>\n

OpenAPI Generator \u306e\u30b3\u30fc\u30c9\u751f\u6210\u306b\u3064\u3044\u3066<\/h2>\n

OpenAPI Generator<\/a> \u306f OpenAPI Specification<\/a> \u306e\u5b9a\u7fa9\u30d5\u30a1\u30a4\u30eb\u304c\u3042\u308c\u3070\u3001API \u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u3084\u30b5\u30fc\u30d0\u306e\u30b9\u30bf\u30d6\u306e\u30b3\u30fc\u30c9\u3092\u81ea\u52d5\u751f\u6210\u3057\u3066\u304f\u308c\u308b\u3068\u3044\u3046\u4fbf\u5229\u306a\u4ee3\u7269\u3067\u3059\u3002<\/p>\n

\u305f\u3060\u3001\u751f\u6210\u3055\u308c\u305f\u30b3\u30fc\u30c9\u304c\u305d\u306e\u307e\u307e\u4f7f\u3048\u308b\u3068\u306f\u8a00\u3048\u307e\u305b\u3093\u3002\u4f8b\u3048\u3070\u3001OAuth2 \u3067\u4fdd\u8b77\u3055\u308c\u3066\u3044\u308b API \u306b\u30a2\u30af\u30bb\u30b9\u3059\u308b\u5834\u5408\u3001\u30a2\u30af\u30bb\u30b9\u30c8\u30fc\u30af\u30f3\u306e\u767a\u884c\u304c\u5fc5\u8981\u3067\u3059\u304c\u3001OpenAPI Generator \u306e\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u30b3\u30fc\u30c9\u751f\u6210\u3067\u306f\u30a2\u30af\u30bb\u30b9\u30c8\u30fc\u30af\u30f3\u767a\u884c\u306e\u30b3\u30fc\u30c9\u306f\u751f\u6210\u3057\u3066\u304f\u308c\u307e\u305b\u3093\u3002
\nJava \u306e\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u30b3\u30fc\u30c9\u3092\u751f\u6210\u3057\u305f\u5834\u5408\u3001README \u306b\u4ee5\u4e0b\u306e\u3088\u3046\u306a\u30b5\u30f3\u30d7\u30eb\u30b3\u30fc\u30c9\u304c\u51fa\u529b\u3055\u308c\u307e\u3059\u304c\u3001 setAccessToken \u3057\u3066\u306d\u3001\u3068\u3044\u3046\u3053\u3068\u304f\u3089\u3044\u3057\u304b\u66f8\u304b\u308c\u3066\u304a\u3089\u305a\u3001\u30a2\u30af\u30bb\u30b9\u30c8\u30fc\u30af\u30f3\u306e\u767a\u884c\u306e\u90e8\u5206\u306b\u306f\u89e6\u308c\u3089\u308c\u3066\u3044\u307e\u305b\u3093\u3002
\n(Java \u306e\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u30b3\u30fc\u30c9\u751f\u6210\u3067\u306f\u3001\u30c7\u30d5\u30a9\u30eb\u30c8\u3067
OkHttp 3<\/a> \u3092\u5229\u7528\u3057\u305f\u30b3\u30fc\u30c9\u304c\u751f\u6210\u3055\u308c\u307e\u3059\u3002OkHttp 3 \u306e\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u30b3\u30fc\u30c9\u306e\u5834\u5408\u3001\u4e00\u5fdc\u30a2\u30af\u30bb\u30b9\u30c8\u30fc\u30af\u30f3\u767a\u884c\u306e\u30b3\u30fc\u30c9\u306f\u751f\u6210\u3055\u308c\u307e\u3059\u304c\u3001Apache Oltu<\/a> \u3068\u3044\u3046\u65e2\u306b\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u7d42\u4e86\u3057\u305f\u30e9\u30a4\u30d6\u30e9\u30ea\u3092\u4f7f\u3063\u305f\u30b3\u30fc\u30c9\u306a\u306e\u3067\u3001\u3042\u307e\u308a\u5b9f\u6848\u4ef6\u3067\u306f\u4f7f\u3044\u305f\u304f\u3042\u308a\u307e\u305b\u3093\uff09<\/p>\n

    public static void main(String[] args) {\n        ApiClient defaultClient = Configuration.getDefaultApiClient();\n        defaultClient.setBasePath(\"https:\/\/mail.paas.crmstyle.com\/e\");\n        \n        \/\/ Configure OAuth2 access token for authorization: mail_oauth\n        OAuth mail_oauth = (OAuth) defaultClient.getAuthentication(\"mail_oauth\");\n        mail_oauth.setAccessToken(\"YOUR ACCESS TOKEN\");\n\n        DefaultApi apiInstance = new DefaultApi(defaultClient);\n        String user = \"user_example\"; \/\/ String | user name\n        DeliverySettingRequest deliverySettingRequest = new DeliverySettingRequest(); \/\/ DeliverySettingRequest | \n        try {\n            DeliveryResponse result = apiInstance.createMailDeliverySetting(user, deliverySettingRequest);\n            System.out.println(result);\n        } catch (ApiException e) {\n            System.err.println(\"Exception when calling DefaultApi#createMailDeliverySetting\");\n            System.err.println(\"Status code: \" + e.getCode());\n            System.err.println(\"Reason: \" + e.getResponseBody());\n            System.err.println(\"Response headers: \" + e.getResponseHeaders());\n            e.printStackTrace();\n        }\n    }\n<\/pre>\n

\u307e\u305f\u3001Spring WebFlux<\/a> \u3092\u30e9\u30a4\u30d6\u30e9\u30ea\u3068\u3057\u3066\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u30b3\u30fc\u30c9\u751f\u6210\u3082\u53ef\u80fd\u3067\u3059\u304c\u3001\u3053\u308c\u306b\u95a2\u3057\u3066\u306f\u30a2\u30af\u30bb\u30b9\u30c8\u30fc\u30af\u30f3\u767a\u884c\u306f\u304a\u308d\u304b\u3001\u305d\u306e\u307e\u307e\u30d3\u30eb\u30c9\u3082\u901a\u3089\u306a\u3044\u3068\u3044\u3046\u72b6\u6cc1\u3067\u3059\u3002<\/p>\n

\u4eca\u56de\u306f\u3001 OpenAPI Generator \u3067 Spring WebFlux \u306e\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u30b3\u30fc\u30c9\u3092 OAuth2 \u306e\u30a2\u30af\u30bb\u30b9\u30c8\u30fc\u30af\u30f3\u767a\u884c\u4ed8\u304d\u3067\u751f\u6210\u3059\u308b\u3068\u3053\u308d\u307e\u3067\u3092\u8a66\u3057\u3066\u307f\u307e\u3057\u305f\u3002
\n\u5b9f\u884c\u74b0\u5883\u306f\u4ee5\u4e0b\u306e\u901a\u308a\u3067\u3059\u3002OpenAPI Generator \u306e\u30d0\u30fc\u30b8\u30e7\u30f3\u306f\u3001\u73fe\u6642\u70b9\u306e\u6700\u65b0\u5b89\u5b9a\u7248\u306e 4.2.2 \u3092\u4f7f\u3044\u307e\u3057\u305f\u3002<\/p>\n

$ java -version\njava version \"1.8.0_144\"\nJava(TM) SE Runtime Environment (build 1.8.0_144-b01)\nJava HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)\n<\/pre>\n

\u30b5\u30f3\u30d7\u30eb\u30b3\u30fc\u30c9\u306f\u3053\u3061\u3089<\/a>\u306b\u3042\u308a\u307e\u3059\u3002
\nOpenAPI \u306e\u5b9a\u7fa9\u30d5\u30a1\u30a4\u30eb\u306f\u3001
Synergy! \u30e1\u30fc\u30ebAPI<\/a> \u3092\u30d9\u30fc\u30b9\u306b\u3057\u305f\u3082\u306e\u3092\u4f7f\u3063\u3066\u3044\u307e\u3059\u3002<\/p>\n

Groovy \u3092\u4f7f\u3046<\/h2>\n

OpenAPI Generator \u304c\u751f\u6210\u3059\u308b\u30b3\u30fc\u30c9\u3092\u5909\u66f4\u3057\u305f\u3044\u5834\u5408\u3001\u666e\u901a\u306a\u3089 Github \u30ea\u30dd\u30b8\u30c8\u30ea<\/a> \u304b\u3089\u30bd\u30fc\u30b9\u30b3\u30fc\u30c9\u3092\u843d\u3068\u3057\u3066\u304d\u3066\u3001Java \u306e\u30b3\u30fc\u30c9\u3092\u4fee\u6b63\u3057\u3066 Maven \u3067\u30d3\u30eb\u30c9\u3057\u3066..\u3068\u3044\u3046\u611f\u3058\u306b\u306a\u308b\u3068\u601d\u3044\u307e\u3059\u304c\u3001 Clone \u3059\u308b\u624b\u9593\u3084 Maven \u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3057\u305f\u308a\u3061\u3087\u3063\u3068\u9762\u5012\u3067\u3059\u3002<\/p>\n

Groovy<\/a> \u3092\u4f7f\u3046\u3053\u3068\u3067\u3001\u5fc5\u8981\u306a\u30af\u30e9\u30b9\u306f @Grab \u3092\u6307\u5b9a\u3059\u308b\u3053\u3068\u3067\u5b9f\u884c\u6642\u306b\u89e3\u6c7a\u3067\u304d\u3001Maven \u306f\u4e0d\u8981\u306b\u306a\u308b\u306e\u3067\u3001Groovy \u3092\u4f7f\u3044\u307e\u3059\u3002\u79c1\u306f\u666e\u6bb5 Mac \u3067\u958b\u767a\u3057\u3066\u3044\u308b\u305f\u3081\u3001Homebrew \u3067 Groovy \u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3057\u307e\u3057\u305f\u3002<\/p>\n

\u624b\u59cb\u3081\u3068\u3057\u3066\u3001JavaClientCodegen<\/a> \u3092\u7d99\u627f\u3057\u305f\u30af\u30e9\u30b9\u3092\u5b9f\u884c\u3059\u308b Groovy \u30b9\u30af\u30ea\u30d7\u30c8\u3092\u4f5c\u308a\u307e\u3059\u3002<\/p>\n

@Grab(group = 'org.openapitools', module = 'openapi-generator-cli', version = '4.2.2')\nimport org.openapitools.codegen.*\nimport org.openapitools.codegen.languages.*\n\nclass TechscoreJavaClientCodegen extends JavaClientCodegen {\n\n  static main(String[] args) {\n    OpenAPIGenerator.main(args)\n  }\n\n  TechscoreJavaClientCodegen() {\n    super()\n  }\n\n  String name = \"techscore-codegen\"\n}\n<\/pre>\n

\u4e0a\u8a18\u3092\u30d5\u30a1\u30a4\u30eb\u540d techscore-client-codegen.groovy \u3068\u3057\u3066\u4fdd\u5b58\u5f8c\u3001\u4ee5\u4e0b\u306e\u30b3\u30de\u30f3\u30c9\u5b9f\u884c\u3067\u3001output \u30d5\u30a9\u30eb\u30c0\u306b Spring WebFlux \u306e\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u30b3\u30fc\u30c9\u304c\u751f\u6210\u3055\u308c\u307e\u3059\u3002<\/p>\n

groovy \\\n  .\/techscore-client-codegen.groovy \\\n  generate \\\n  -i .\/openapi.yml \\\n  -g TechscoreJavaClientCodegen \\\n  -o .\/output \\\n  --library webclient\n<\/pre>\n

\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u306e\u30ab\u30b9\u30bf\u30de\u30a4\u30ba<\/h2>\n

\u4e0a\u8a18\u3067\u751f\u6210\u3055\u308c\u308b\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u30b3\u30fc\u30c9\u306f\u3001\u524d\u8ff0\u3057\u305f\u3068\u304a\u308a\u305d\u306e\u307e\u307e\u3067\u306f\u30d3\u30eb\u30c9\u304c\u901a\u3089\u306a\u3044\u3001\u30a2\u30af\u30bb\u30b9\u30c8\u30fc\u30af\u30f3\u767a\u884c\u306e\u30b3\u30fc\u30c9\u304c\u751f\u6210\u3055\u308c\u306a\u3044\u306a\u3069\u3068\u3044\u3063\u305f\u72b6\u614b\u3067\u3059\u3002<\/p>\n

\u751f\u6210\u3055\u308c\u308b\u30d5\u30a1\u30a4\u30eb\u3092\u4fee\u6b63\u30fb\u8ffd\u52a0\u3059\u308b<\/h3>\n

\u30d3\u30eb\u30c9\u304c\u901a\u3089\u306a\u3044\u306e\u306f\u3001\u751f\u6210\u3055\u308c\u308b build.gradle \u306b Spring \u95a2\u4fc2\u306e\u4f9d\u5b58\u95a2\u4fc2\u306b\u3064\u3044\u3066\u4e00\u5207\u8a18\u8f09\u304c\u7121\u3044\u3053\u3068\u304c\u539f\u56e0\u3067\u3059\u3002
\n\u3053\u308c\u3092\u89e3\u6d88\u3059\u308b\u305f\u3081\u306b\u3001OpenAPI Generator \u306f\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u304b\u3089\u30b3\u30fc\u30c9\u751f\u6210\u3059\u308b\u305f\u3081\u3001OpenAPI Generator \u306e\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u3092\u30ab\u30b9\u30bf\u30de\u30a4\u30ba\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002<\/p>\n

Java \u306e\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u30b3\u30fc\u30c9\u306e\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u306f\u3001\u3053\u3061\u3089<\/a> \u304b\u3089\u53d6\u5f97\u3067\u304d\u307e\u3059\u3002
\n\u3053\u308c\u3092\u30b3\u30d4\u30fc\u3057\u3066\u3001\u30d5\u30a1\u30a4\u30eb\u3092\u4fee\u6b63\u30fb\u8ffd\u52a0\u3059\u308b\u3053\u3068\u3067\u751f\u6210\u3055\u308c\u308b\u30b3\u30fc\u30c9\u3092\u5909\u66f4\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002
\n\u4ee5\u4e0b\u306e\u3088\u3046\u306b\u3057\u3066\u3001template \u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u914d\u4e0b\u306b\u30b3\u30d4\u30fc\u3057\u307e\u3059\u3002<\/p>\n

mkdir -p {repodir,template} && cd repodir\ngit init\ngit remote add origin https:\/\/github.com\/OpenAPITools\/openapi-generator.git\ngit config core.sparsecheckout true\nvi .git\/info\/sparse-checkout \u2190 modules\/openapi-generator\/src\/main\/resources\/Java\/ \u3092\u8ffd\u8a18 \ngit fetch origin\ngit checkout v4.2.2\ngit pull origin v4.2.2\ncp -pR modules\/openapi-generator\/src\/main\/resources\/Java\/* ..\/template\/\ncd ..\/ && rm -Rf repodir\n<\/pre>\n

template \u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u306e\u4e2d\u306f\u4ee5\u4e0b\u306e\u3088\u3046\u306a\u69cb\u6210\u306b\u306a\u3063\u3066\u3044\u307e\u3059\u3002\u62e1\u5f35\u5b50 .mustcache \u306f OpenAPI Generator \u304c\u5229\u7528\u3057\u3066\u3044\u308b\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u30a8\u30f3\u30b8\u30f3 Mustache<\/a> \u306e\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u30d5\u30a1\u30a4\u30eb\u3067\u3059\u3002<\/p>\n

$ tree -L 3 template\ntemplate\n\u251c\u2500\u2500 auth\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 ApiKeyAuth.mustache\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 Authentication.mustache\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 HttpBasicAuth.mustache\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 HttpBearerAuth.mustache\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 OAuth.mustache\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 OAuthFlow.mustache\n\u251c\u2500\u2500 libraries\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 feign\n\u2502\u00a0\u00a0 (\u7565)\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 webclient\n\u2502\u00a0\u00a0     \u251c\u2500\u2500 auth\n\u2502\u00a0\u00a0     \u251c\u2500\u2500 ApiClient.mustache\n\u2502\u00a0\u00a0     \u251c\u2500\u2500 README.mustache\n\u2502\u00a0\u00a0     \u251c\u2500\u2500 api.mustache\n\u2502\u00a0\u00a0     \u251c\u2500\u2500 api_test.mustache\n\u2502\u00a0\u00a0     \u2514\u2500\u2500 pom.mustache\n\u251c\u2500\u2500 ApiClient.mustache\n(\u7565)\n\u251c\u2500\u2500 build.gradle.mustache\n\u251c\u2500\u2500 build.sbt.mustache\n(\u7565)\n\u2514\u2500\u2500 xmlAnnotation.mustache\n<\/pre>\n

\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u30b3\u30fc\u30c9\u751f\u6210\u6642\u3001--library webclient<\/code> (Spring WebFlux\u306e\u30b3\u30fc\u30c9\u751f\u6210)\u3092\u6307\u5b9a\u3059\u308b\u3068\u3001 libraries\/webclient \u306e\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u304c\u4f7f\u308f\u308c\u308b\u3053\u3068\u306b\u306a\u308a\u307e\u3059\u3002
\n\u4eca\u56de\u306e\u5834\u5408\u3001 libraries\/webclient\/build.gradle.mustache \u3092\u4f5c\u6210\u3059\u308c\u3070\u3001build.gradle \u3092\u5909\u66f4\u3067\u304d\u307e\u3059\u3002
\nbuild.gradle.mustache \u306e\u5185\u5bb9\u306f
\u3053\u3061\u3089<\/a>\u3092\u53c2\u7167\u304f\u3060\u3055\u3044\u3002
\n\u4ee5\u4e0b\u306e\u3088\u3046\u306b -t \u30aa\u30d7\u30b7\u30e7\u30f3\u3092\u8ffd\u52a0\u3057\u3066\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u6307\u5b9a\u3059\u308b\u3053\u3068\u3067\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u306e\u5dee\u3057\u66ff\u3048\u304c\u53ef\u80fd\u3067\u3059\u3002<\/p>\n

groovy \\\n  .\/techscore-client-codegen.groovy \\\n  generate \\\n  -i .\/openapi.yml \\\n  -g TechscoreJavaClientCodegen \\\n  -o .\/output \\\n  -t .\/template \\\n  --library webclient\n<\/pre>\n

\u30a2\u30af\u30bb\u30b9\u30c8\u30fc\u30af\u30f3\u767a\u884c\u306e\u30b3\u30fc\u30c9\u3092\u751f\u6210\u3059\u308b\u305f\u3081\u306b\u306f\u3001\u65b0\u3057\u304f\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u30d5\u30a1\u30a4\u30eb\u3092\u8ffd\u52a0\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002
\n\u4eca\u56de\u306f\u3001Spring WebFlux \u306e\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u30b3\u30fc\u30c9\u306e\u305f\u3081\u3001
WebClient<\/a> \u3092 DI \u3067\u304d\u308b\u3088\u3046\u306b\u3001\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u3092\u4f5c\u6210\u3057 libraries\/webclient\/WebClientConfig.mustache<\/a> \u306b\u767b\u9332\u3057\u307e\u3057\u305f\u3002
\n
Synergy! \u30e1\u30fc\u30ebAPI<\/a> \u3067\u306f\u30a2\u30af\u30bb\u30b9\u30c8\u30fc\u30af\u30f3\u767a\u884c\u6642\u306b scope \u3068 audience \u3092\u30ea\u30af\u30a8\u30b9\u30c8\u30dc\u30c7\u30a3\u306b\u542b\u3081\u308b\u5fc5\u8981\u304c\u3042\u308b\u305f\u3081\u3001\u305d\u306e\u3088\u3046\u306a\u5b9f\u88c5\u3092\u3057\u3066\u3044\u307e\u3059\u3002\u307e\u305f\u3001\u30a2\u30af\u30bb\u30b9\u30c8\u30fc\u30af\u30f3\u306f\u3042\u308b\u7a0b\u5ea6\u30ad\u30e3\u30c3\u30b7\u30e5\u3092\u5229\u7528\u3059\u308b\u3088\u3046\u306b\u3057\u3066\u3044\u307e\u3059\u3002\u5b9f\u88c5\u5185\u5bb9\u306f\u30ea\u30f3\u30af\u5148<\/a>\u3092\u53c2\u7167\u3044\u305f\u3060\u3051\u308c\u3070\u3068\u601d\u3044\u307e\u3059\u3002<\/p>\n

\u307e\u305f\u3001ApiClient.mustache<\/a>, api.mustache<\/a> \u3082\u3001\u4e0a\u8a18 WebClient \u3092 DI \u3067\u304d\u308b\u3088\u3046\u306b\u5c11\u3057\u305a\u3064\u5185\u5bb9\u3092\u5909\u66f4\u3057\u3066\u3044\u307e\u3059\u3002\u3053\u3061\u3089\u3082\u5185\u5bb9\u306f\u30ea\u30f3\u30af\u5148\u3092\u53c2\u7167\u304f\u3060\u3055\u3044\u3002<\/p>\n

\u305f\u3060\u3057\u3001\u65b0\u3057\u3044\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u3092\u8ffd\u52a0\u3057\u3066\u3082\u3001\u305d\u308c\u3060\u3051\u3067\u306f\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u3092\u8aad\u307f\u53d6\u3063\u3066\u304f\u308c\u307e\u305b\u3093\u3002Groovy \u306b\u4ee5\u4e0b\u306e Override \u30e1\u30bd\u30c3\u30c9\u3092\u8ffd\u52a0\u3057\u3066\u3001\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u3092\u8aad\u307f\u53d6\u308b\u3088\u3046\u306b\u3057\u307e\u3059\u3002<\/p>\n

  @Override\n  public void processOpts() {\n    final String invokerFolder = (sourceFolder + '\/' + invokerPackage).replace(\".\", \"\/\");\n    final String apiFolder = (sourceFolder + '\/' + apiPackage).replace(\".\", \"\/\");\n    super.processOpts()\n\n    if (WEBCLIENT.equals(getLibrary())) {\n      \/\/ add WebClientConfig\n      supportingFiles.add(new SupportingFile(\"WebClientConfig.mustache\", invokerFolder, \"WebClientConfig.java\"))\n    }\n  }\n<\/pre>\n

Spring Boot \u306e\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb application.yml \u3092\u8ffd\u52a0\u3059\u308b<\/h3>\n

\u5148\u307b\u3069\u89e6\u308c\u307e\u305b\u3093\u3067\u3057\u305f\u304c\u3001\u4e0a\u8a18\u306e WebClientConfig.mustache \u3092\u5143\u306b\u751f\u6210\u3055\u308c\u308b WebClientConfig.java \u306f\u3001Spring Boot \u306e\u5b9a\u7fa9\u30d5\u30a1\u30a4\u30eb\u3067\u3042\u308b application.yml \u304b\u3089 OAuth2 \u95a2\u9023\u306e\u8a2d\u5b9a\u5185\u5bb9\u3092\u8aad\u307f\u53d6\u308b\u3053\u3068\u3092\u524d\u63d0\u3068\u3057\u3066\u3044\u307e\u3059\u3002(\u3053\u306e\u8fba\u308a<\/a>\u3084\u3001\u3053\u306e\u8fba\u308a<\/a>\u3067\u3059\u3002)<\/p>\n

application.yml \u3082\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u30d5\u30a1\u30a4\u30eb\u304c\u5b58\u5728\u3057\u306a\u3044\u305f\u3081\u3001\u5148\u307b\u3069\u540c\u69d8\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u30d5\u30a1\u30a4\u30eb\u3092\u4f5c\u6210\u3057\u3066\u3001\u305d\u308c\u3092\u8aad\u307f\u53d6\u308b\u30b3\u30fc\u30c9\u3092 Groovy \u30b9\u30af\u30ea\u30d7\u30c8\u306b\u8ffd\u8a18\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002<\/p>\n

{{#authMethods}}{{#isOAuth}}\nspring:\n  security.oauth2.client:\n    provider:\n      paas:\n        token-uri: https:\/\/auth.paas.crmstyle.com\/oauth2\/token\n    registration:\n      paas:\n        authorization-grant-type: client_credentials\n        client-id: your-client-id\n        client-secret: your-client-secret\n        scope:\n          - mail:send\n          - mail:result\n        audience: https:\/\/mail.paas.crmstyle.com{{\/isOAuth}}{{\/authMethods}}\nlogging:\n  level:\n    reactor.netty: DEBUG\n<\/pre>\n
  @Override\n  public void processOpts() {\n    final String invokerFolder = (sourceFolder + '\/' + invokerPackage).replace(\".\", \"\/\");\n    final String apiFolder = (sourceFolder + '\/' + apiPackage).replace(\".\", \"\/\");\n    super.processOpts()\n\n    if (WEBCLIENT.equals(getLibrary())) {\n      \/\/ add WebClientConfig\n      supportingFiles.add(new SupportingFile(\"WebClientConfig.mustache\", invokerFolder, \"WebClientConfig.java\"))\n      \/\/ add application.yml \u2605\u8ffd\u8a18\n      supportingFiles.add(new SupportingFile(\"application.yml.mustache\", projectFolder + '\/resources', \"application.yml\"))\n    }\n  }\n<\/pre>\n

SecuritySchemes \u3092\u8aad\u307f\u53d6\u3063\u3066\u7f6e\u63db\u3059\u308b<\/h3>\n

\u5148\u307b\u3069\u306e application.yml \u306e\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u306f\u3001\u30a2\u30af\u30bb\u30b9\u30c8\u30fc\u30af\u30f3\u767a\u884c URL \u3084\u30b9\u30b3\u30fc\u30d7\u3001audience \u3092\u56fa\u5b9a\u3067\u8a18\u8f09\u3057\u3066\u3044\u307e\u3057\u305f\u3002\uff08\u4ee5\u4e0b\u306e\u2605\u30de\u30fc\u30af\u3092\u3064\u3051\u3066\u3044\u308b\u90e8\u5206\u3067\u3059\u3002\uff09<\/p>\n

{{#authMethods}}{{#isOAuth}}\nspring:\n  security.oauth2.client:\n    provider:\n      paas:\n        token-uri: https:\/\/auth.paas.crmstyle.com\/oauth2\/token \u2605\u3053\u3053\n    registration:\n      paas:\n        authorization-grant-type: client_credentials\n        client-id: your-client-id\n        client-secret: your-client-secret\n        scope: \u2605\u3053\u3053\n          - mail:send\n          - mail:result\n        audience: https:\/\/mail.paas.crmstyle.com \u2605\u3053\u3053{{\/isOAuth}}{{\/authMethods}}\nlogging:\n  level:\n    reactor.netty: DEBUG\n<\/pre>\n

\u3069\u3046\u305b\u306a\u3089\u3001OpenAPI \u306e\u5b9a\u7fa9\u30d5\u30a1\u30a4\u30eb\u306e SecuritySchemes \u304b\u3089\u8aad\u307f\u53d6\u3063\u305f\u5185\u5bb9\u3067\u7f6e\u63db\u3057\u305f\u3044\u3067\u3059\u3002<\/p>\n

  securitySchemes:\n    mail_oauth:\n      type: oauth2\n      description: mail auth\n      flows:\n        clientCredentials:\n          tokenUrl: \"https:\/\/auth.paas.crmstyle.com\/oauth2\/token\" \u2605\u3053\u308c\u306b\u52d5\u7684\u306b\u5dee\u3057\u66ff\u3048\u305f\u3044\n          scopes: \u2605\u3053\u308c\u306b\u52d5\u7684\u306b\u5dee\u3057\u66ff\u3048\u305f\u3044\n            mail:send: \"delivery\"\n            mail:result: \"get the delivery results\"\n          x-audience: \"https:\/\/mail.paas.crmstyle.com\" \u2605\u3053\u308c\u306b\u52d5\u7684\u306b\u5dee\u3057\u66ff\u3048\u305f\u3044\n<\/pre>\n

\u30a2\u30af\u30bb\u30b9\u30c8\u30fc\u30af\u30f3\u767a\u884c URL \u3084\u30b9\u30b3\u30fc\u30d7\u306f\u3001\u30c7\u30d5\u30a9\u30eb\u30c8\u306e\u72b6\u614b\u3067 OpenAPI \u5b9a\u7fa9\u30d5\u30a1\u30a4\u30eb\u304b\u3089\u5185\u5bb9\u3092\u8aad\u307f\u53d6\u3063\u3066\u304f\u308c\u307e\u3059\u3002
\napplication.yml \u306e\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u3092\u4ee5\u4e0b\u306e\u3088\u3046\u306b\u5909\u66f4\u3059\u308b\u3053\u3068\u3067\u3001\u5dee\u3057\u66ff\u3048\u304c\u53ef\u80fd\u3067\u3059\u3002<\/p>\n

{{#authMethods}}{{#isOAuth}}\nspring:\n  security.oauth2.client:\n    provider:\n      paas:\n        token-uri: {{tokenUrl}} \u2605\u3053\u308c\u3067\u5dee\u3057\u66ff\u3048\u53ef\u80fd\n    registration:\n      paas:\n        authorization-grant-type: client_credentials\n        client-id: your-client-id\n        client-secret: your-client-secret\n        scope: \u2605\u3053\u308c\u3067\u5dee\u3057\u66ff\u3048\u53ef\u80fd\n        {{#scopes}}\n          - \"{{scope}}\"\n        {{\/scopes}}\n        audience: https:\/\/mail.paas.crmstyle.com \u2605\u307e\u3060\u7f6e\u63db\u3067\u304d\u306a\u3044 {{\/isOAuth}}{{\/authMethods}}\nlogging:\n  level:\n    reactor.netty: DEBUG\n<\/pre>\n

audience \u306b\u95a2\u3057\u3066\u306f\u3001 OpenAPI \u306e\u6a19\u6e96\u4ed5\u69d8\u306b\u306f\u542b\u307e\u308c\u3066\u3044\u306a\u3044\u5185\u5bb9\u3068\u306a\u308a\u3001Specification Extensions<\/a> \u3068\u3057\u3066\u5b9a\u7fa9\u3059\u308b\u5fc5\u8981\u304c\u3042\u308b\u305f\u3081\u3001\u30c7\u30d5\u30a9\u30eb\u30c8\u3067\u306f OpenAPI Generator \u3067\u306f\u8aad\u307f\u53d6\u3063\u3066\u304f\u308c\u307e\u305b\u3093\u3002<\/p>\n

OpenAPI Generator \u3067\u306e SecuritySchemes \u306e\u8aad\u307f\u53d6\u308a\u306f\u3001DefaultCodegen#fromSecurity<\/a> \u304c\u884c\u306a\u3063\u3066\u3044\u307e\u3059\u3002
\nDefaultCodegen \u306f\u3001 JavaClientCodegen \u306e\u4e00\u756a\u7956\u5148\u306e\u7d99\u627f\u5143\u3067\u3059\u3002
\n\u5185\u5bb9\u3092\u898b\u308b\u3068\u3001SecuritySchemes \u304b\u3089\u8aad\u307f\u53d6\u3063\u305f\u5185\u5bb9\u3092\u3001CodegenSecurity \u3068\u3044\u3046\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306b\u8a70\u3081\u3066\u3044\u3063\u3066\u3044\u308b\u3088\u3046\u306b\u898b\u3048\u307e\u3059\u3002<\/p>\n

    \/**\n     * Convert map of OAS SecurityScheme objects to a list of Codegen Security objects\n     *\n     * @param securitySchemeMap a map of OAS SecuritySchemeDefinition object\n     * @return a list of Codegen Security objects\n     *\/\n    @SuppressWarnings(\"static-method\")\n    public List fromSecurity(Map<String, SecurityScheme> securitySchemeMap) {\n        if (securitySchemeMap == null) {\n            return Collections.emptyList();\n        }\n\n        List codegenSecurities = new ArrayList(securitySchemeMap.size());\n        for (String key : securitySchemeMap.keySet()) {\n            final SecurityScheme securityScheme = securitySchemeMap.get(key);\n\n            CodegenSecurity cs = CodegenModelFactory.newInstance(CodegenModelType.SECURITY);\n            cs.name = key;\n            cs.type = securityScheme.getType().toString();\n            cs.isCode = cs.isPassword = cs.isApplication = cs.isImplicit = false;\n            cs.isBasicBasic = cs.isBasicBearer = false;\n            cs.scheme = securityScheme.getScheme();\n\n            if (SecurityScheme.Type.APIKEY.equals(securityScheme.getType())) {\n                cs.isBasic = cs.isOAuth = false;\n                cs.isApiKey = true;\n                cs.keyParamName = securityScheme.getName();\n                cs.isKeyInHeader = securityScheme.getIn() == SecurityScheme.In.HEADER;\n                cs.isKeyInQuery = securityScheme.getIn() == SecurityScheme.In.QUERY;\n                cs.isKeyInCookie = securityScheme.getIn() == SecurityScheme.In.COOKIE;  \/\/it assumes a validation step prior to generation. (cookie-auth supported from OpenAPI 3.0.0)\n            } else if (SecurityScheme.Type.HTTP.equals(securityScheme.getType())) {\n                cs.isKeyInHeader = cs.isKeyInQuery = cs.isKeyInCookie = cs.isApiKey = cs.isOAuth = false;\n                cs.isBasic = true;\n                if (\"basic\".equals(securityScheme.getScheme())) {\n                    cs.isBasicBasic = true;\n                } else if (\"bearer\".equals(securityScheme.getScheme())) {\n                    cs.isBasicBearer = true;\n                    cs.bearerFormat = securityScheme.getBearerFormat();\n                }\n            } else if (SecurityScheme.Type.OAUTH2.equals(securityScheme.getType())) {\n                cs.isKeyInHeader = cs.isKeyInQuery = cs.isKeyInCookie = cs.isApiKey = cs.isBasic = false;\n                cs.isOAuth = true;\n                final OAuthFlows flows = securityScheme.getFlows();\n                if (securityScheme.getFlows() == null) {\n                    throw new RuntimeException(\"missing oauth flow in \" + cs.name);\n                }\n                if (flows.getPassword() != null) {\n                    setOauth2Info(cs, flows.getPassword());\n                    cs.isPassword = true;\n                    cs.flow = \"password\";\n                } else if (flows.getImplicit() != null) {\n                    setOauth2Info(cs, flows.getImplicit());\n                    cs.isImplicit = true;\n                    cs.flow = \"implicit\";\n                } else if (flows.getClientCredentials() != null) {\n                    setOauth2Info(cs, flows.getClientCredentials());\n                    cs.isApplication = true;\n                    cs.flow = \"application\";\n                } else if (flows.getAuthorizationCode() != null) {\n                    setOauth2Info(cs, flows.getAuthorizationCode());\n                    cs.isCode = true;\n                    cs.flow = \"accessCode\";\n                } else {\n                    throw new RuntimeException(\"Could not identify any oauth2 flow in \" + cs.name);\n                }\n            }\n\n            codegenSecurities.add(cs);\n        }\n    }\n<\/pre>\n

fromSecurity \u304b\u3089\u3055\u3089\u306b\u3001 DefaultCodegen#setOAuth2Info<\/a> \u3068\u3044\u3046 private \u30e1\u30bd\u30c3\u30c9\u304c\u547c\u3070\u308c\u3066\u3044\u307e\u3059\u3002
\n\u5b9f\u88c5\u3092\u898b\u308b\u3068\u3001
OAuth Flow Object<\/a> \u306e\u5185\u5bb9\u3092\u3001CodegenSecurity \u306b\u8a70\u3081\u3066\u3044\u308b\u3088\u3046\u3067\u3059\u3002<\/p>\n

    private void setOauth2Info(CodegenSecurity codegenSecurity, OAuthFlow flow) {\n        codegenSecurity.authorizationUrl = flow.getAuthorizationUrl();\n        codegenSecurity.tokenUrl = flow.getTokenUrl();\n\n        if (flow.getScopes() != null && !flow.getScopes().isEmpty()) {\n            List<Map<String, Object>> scopes = new ArrayList<Map<String, Object>>();\n            int count = 0, numScopes = flow.getScopes().size();\n            for (Map.Entry<String, String> scopeEntry : flow.getScopes().entrySet()) {\n                Map<String, Object> scope = new HashMap<String, Object>();\n                scope.put(\"scope\", scopeEntry.getKey());\n                scope.put(\"description\", escapeText(scopeEntry.getValue()));\n\n                count += 1;\n                if (count < numScopes) {\n                    scope.put(\"hasMore\", \"true\");\n                } else {\n                    scope.put(\"hasMore\", null);\n                }\n\n                scopes.add(scope);\n            }\n            codegenSecurity.scopes = scopes;\n        }\n    }\n<\/pre>\n

\u3055\u3089\u306b\u8aad\u307f\u9032\u3081\u308b\u3068\u3001OAuthFlow \u306b getExtensions<\/a> \u3068\u3044\u3046\u30e1\u30bd\u30c3\u30c9\u304c\u3042\u308a\u3001
\nCodegenSecurity \u306b\u3001
vendorExtensions<\/a> \u3068\u3044\u3046\u30d7\u30ed\u30d1\u30c6\u30a3\u304c\u7528\u610f\u3055\u308c\u3066\u3044\u308b\u3053\u3068\u304c\u5206\u304b\u308a\u307e\u3059\u3002
\nSpecification Extensions \u306e\u5185\u5bb9\u3092 OAuthFlow#getExtensions\u304b\u3089\u8aad\u307f\u53d6\u3063\u3066\u3001 CodegenSecurity \u306e vendorExtensions \u306b\u30bb\u30c3\u30c8\u3059\u308c\u3070\u3001\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u30d5\u30a1\u30a4\u30eb\u306e\u7f6e\u63db\u304c\u53ef\u80fd\u3068\u306a\u308b\u306e\u3067\u306f\u3068\u63a8\u6e2c\u3067\u304d\u307e\u3059\u3002<\/p>\n

\u5b9f\u969b\u306b Groovy \u30b9\u30af\u30ea\u30d7\u30c8\u3092\u4ee5\u4e0b\u306e\u3088\u3046\u306b\u5909\u66f4\u3057\u3066\u307f\u3066\u8a66\u3057\u3066\u307f\u307e\u3059\u3002setOAuth2Info \u306f private \u30b9\u30b3\u30fc\u30d7\u306a\u306e\u3067\u3001\u5185\u5bb9\u3092 DefaultCodegen \u304b\u3089\u305d\u306e\u307e\u307e\u6301\u3063\u3066\u304d\u3066 getExtension \u3059\u308b\u30b3\u30fc\u30c9\u3092\u8ffd\u8a18\u3057\u3066\u3044\u307e\u3059\u3002
\nfromSecurity \u304c setOAuth2Info \u3092\u547c\u3076\u4f5c\u308a\u306b\u306a\u3063\u3066\u3044\u308b\u305f\u3081\u3001fromSecurity \u3082\u5185\u5bb9\u306f\u5909\u66f4\u305b\u305a\u30aa\u30fc\u30d0\u30fc\u30e9\u30a4\u30c9\u3057\u3066\u3044\u307e\u3059\u3002<\/p>\n

@Grab(group = 'org.openapitools', module = 'openapi-generator-cli', version = '4.2.2')\nimport org.openapitools.codegen.*\nimport org.openapitools.codegen.languages.*\nimport io.swagger.v3.oas.models.security.*;\n\nclass TechscoreJavaClientCodegen extends JavaClientCodegen {\n\n  static main(String[] args) {\n    OpenAPIGenerator.main(args)\n  }\n\n  TechscoreJavaClientCodegen() {\n    super()\n  }\n\n  String name = \"techscore-codegen\"\n  \n  @Override\n  public void processOpts() {\n    final String invokerFolder = (sourceFolder + '\/' + invokerPackage).replace(\".\", \"\/\");\n    final String apiFolder = (sourceFolder + '\/' + apiPackage).replace(\".\", \"\/\");\n    super.processOpts()\n\n    if (WEBCLIENT.equals(getLibrary())) {\n      \/\/ add WebClientConfig\n      supportingFiles.add(new SupportingFile(\"WebClientConfig.mustache\", invokerFolder, \"WebClientConfig.java\"))\n      \/\/ add application.yml\n      supportingFiles.add(new SupportingFile(\"application.yml.mustache\", projectFolder + '\/resources', \"application.yml\"))\n    }\n  }\n\n  @Override\n  @SuppressWarnings(\"static-method\")\n  public List fromSecurity(Map<String, SecurityScheme> securitySchemeMap) {\n      if (securitySchemeMap == null) {\n          return Collections.emptyList();\n      } \n      (\u7565)\n      return codegenSecurities;\n  }\n\n  private void setOauth2Info(CodegenSecurity codegenSecurity, OAuthFlow flow) {\n        codegenSecurity.authorizationUrl = flow.getAuthorizationUrl();\n        codegenSecurity.tokenUrl = flow.getTokenUrl();\n\n        if (flow.getScopes() != null && !flow.getScopes().isEmpty()) {\n            List<Map<String, Object>> scopes = new ArrayList<Map<String, Object>>();\n            int count = 0, numScopes = flow.getScopes().size();\n            for (Map.Entry<String, String> scopeEntry : flow.getScopes().entrySet()) {\n                Map<String, Object> scope = new HashMap<String, Object>();\n                scope.put(\"scope\", scopeEntry.getKey());\n                scope.put(\"description\", escapeText(scopeEntry.getValue()));\n\n                count += 1;\n                if (count < numScopes) {\n                    scope.put(\"hasMore\", \"true\");\n                } else {\n                    scope.put(\"hasMore\", null);\n                }\n\n                scopes.add(scope);\n            }\n            codegenSecurity.scopes = scopes;\n        }\n        \/\/ Specification Extensions \u3092\u30bb\u30c3\u30c8\n        if (flow.getExtensions() != null) {\n          Map<String, Object> extensions = flow.getExtensions();\n          codegenSecurity.vendorExtensions = extensions;\n        }\n    }\n}\n<\/pre>\n

\u6b21\u306b application.yml \u306e\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u30d5\u30a1\u30a4\u30eb\u3092\u4ee5\u4e0b\u306e\u3088\u3046\u306b\u5909\u66f4\u3057\u307e\u3059\u3002<\/p>\n

{{#authMethods}}{{#isOAuth}}\nspring:\n  security.oauth2.client:\n    provider:\n      paas:\n        token-uri: {{tokenUrl}}\n    registration:\n      paas:\n        authorization-grant-type: client_credentials\n        client-id: your-client-id\n        client-secret: your-client-secret\n        scope:\n        {{#scopes}}\n          - \"{{scope}}\"\n        {{\/scopes}}\n        {{#vendorExtensions}} \u2605 \u5909\u66f4\n        audience: {{x-audience}}{{\/vendorExtensions}}{{\/isOAuth}}{{\/authMethods}}\nlogging:\n  level:\n    reactor.netty: DEBUG\n<\/pre>\n

\u3053\u306e\u72b6\u614b\u3067 Groovy \u3092\u5b9f\u884c\u3059\u308b\u3068\u3001SecuritySchemes \u304b\u3089\u5185\u5bb9\u3092\u8aad\u307f\u53d6\u3063\u305f src\/main\/resources\/application.yml \u3092\u5f97\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002<\/p>\n

spring:\n  security.oauth2.client:\n    provider:\n      paas:\n        token-uri: https:\/\/auth.paas.crmstyle.com\/oauth2\/token\n    registration:\n      paas:\n        authorization-grant-type: client_credentials\n        client-id: your-client-id\n        client-secret: your-client-secret\n        scope:\n          - \"mail:send\"\n          - \"mail:result\"\n        audience: https:\/\/mail.paas.crmstyle.com\nlogging:\n  level:\n    reactor.netty: DEBUG\n<\/pre>\n

\u7d42\u308f\u308a\u306b<\/h2>\n

\u4eca\u56de\u306f Java + Spring WebFlux \u306e\u4f8b\u3067 OpenAPI Generator \u306e\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u30b3\u30fc\u30c9\u751f\u6210\u306e\u30ab\u30b9\u30bf\u30de\u30a4\u30ba\u306b\u3064\u3044\u3066\u8aac\u660e\u3057\u307e\u3057\u305f\u3002ClientCodegen \u3092\u7d99\u627f\u3057\u305f\u30af\u30e9\u30b9\u3092\u4f5c\u308a\u3001\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u3092\u4fee\u6b63\u30fb\u8ffd\u8a18\u3059\u308b\u3053\u3068\u3067\u3001\u4ed6\u306e\u30b5\u30dd\u30fc\u30c8\u3055\u308c\u3066\u3044\u308b\u8a00\u8a9e\u306e\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u30b3\u30fc\u30c9\u3082\u81ea\u5206\u306e\u597d\u304d\u306a\u3088\u3046\u306b\u5909\u66f4\u3059\u308b\u3053\u3068\u304c\u53ef\u80fd\u3068\u601d\u3044\u307e\u3059\u3002\uff08OpenAPI Generator \u306e\u30b3\u30fc\u30c9\u306f\u8aad\u307f\u89e3\u304f\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u304c\uff09
\n\u7686\u3055\u3093\u3082\u662f\u975e\u4e00\u5ea6\u8a66\u3057\u3066\u307f\u3066\u306f\u3044\u304b\u304c\u3067\u3057\u3087\u3046\u304b\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"

\u3053\u308c\u306f TECHSCORE Advent Calendar 2019 \u306e17\u65e5\u76ee\u306e\u8a18\u4e8b\u3067\u3059\u3002
\u7d9a\u304d\u3092\u8aad\u3080...<\/a><\/p>\n","protected":false},"author":40,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[332,18],"tags":[141,327,348],"_links":{"self":[{"href":"https:\/\/www.techscore.com\/blog\/wp-json\/wp\/v2\/posts\/25128"}],"collection":[{"href":"https:\/\/www.techscore.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.techscore.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.techscore.com\/blog\/wp-json\/wp\/v2\/users\/40"}],"replies":[{"embeddable":true,"href":"https:\/\/www.techscore.com\/blog\/wp-json\/wp\/v2\/comments?post=25128"}],"version-history":[{"count":31,"href":"https:\/\/www.techscore.com\/blog\/wp-json\/wp\/v2\/posts\/25128\/revisions"}],"predecessor-version":[{"id":25161,"href":"https:\/\/www.techscore.com\/blog\/wp-json\/wp\/v2\/posts\/25128\/revisions\/25161"}],"wp:attachment":[{"href":"https:\/\/www.techscore.com\/blog\/wp-json\/wp\/v2\/media?parent=25128"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.techscore.com\/blog\/wp-json\/wp\/v2\/categories?post=25128"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.techscore.com\/blog\/wp-json\/wp\/v2\/tags?post=25128"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}