{"id":5542,"date":"2021-02-18T10:00:05","date_gmt":"2021-02-18T01:00:05","guid":{"rendered":"https:\/\/hldc.co.jp\/blog\/?p=5542"},"modified":"2023-11-14T11:47:42","modified_gmt":"2023-11-14T02:47:42","slug":"%e5%ae%a2%e5%85%88%e3%81%a7%e3%81%97%e3%81%8b%e7%99%ba%e7%94%9f%e3%81%97%e3%81%aa%e3%81%84%e4%b8%8d%e5%85%b7%e5%90%88%e3%81%a7%e5%9b%b0%e3%81%a3%e3%81%a6%e3%81%be%e3%81%99%e3%83%bb%e3%83%bb-10-2-2-2-9","status":"publish","type":"post","link":"https:\/\/hldc.co.jp\/blog\/2021\/02\/18\/5542\/","title":{"rendered":"cpprestsdk \u3092\u4f7f\u3063\u3066 Redmine \u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306e\u5de5\u6570\u5206\u6790\u3092\u81ea\u52d5\u5316\uff01"},"content":{"rendered":"<p>Redmine \u306f\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306e\u9032\u884c\u7ba1\u7406\u3084\u4e0d\u5177\u5408\u7ba1\u7406\u306e\u6a5f\u80fd\u3092\u5099\u3048\u3066\u3044\u308b\u30aa\u30fc\u30d7\u30f3\u30bd\u30fc\u30b9\u30bd\u30d5\u30c8\u30a6\u30a7\u30a2\u3067\u3059\u3002\u8cbb\u7528\u304c\u304b\u304b\u3089\u305a\u74b0\u5883\u69cb\u7bc9\u3082\u5bb9\u6613\u3067\u3042\u308b\u305f\u3081\u3001\u69d8\u3005\u306a\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3067\u4f7f\u7528\u3055\u308c\u3066\u3044\u307e\u3059\u3002<\/p>\n<p>Redmine \u306f REST API \u3092\u516c\u958b\u3057\u3066\u304a\u308a\u3001\u5916\u90e8\u306e\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306f\u3053\u308c\u3092\u4f7f\u3046\u3053\u3068\u3067 Redmine \u304c\u7ba1\u7406\u3057\u3066\u3044\u308b\u60c5\u5831\u3078\u7c21\u5358\u306b\u30a2\u30af\u30bb\u30b9\u3067\u304d\u307e\u3059\u3002\u3053\u308c\u306b\u3088\u3063\u3066\u5de5\u6570\u306e\u96c6\u8a08\u3092\u81ea\u52d5\u5316\u3057\u305f\u308a\u3001\u30c7\u30fc\u30bf\u3092\u53ef\u8996\u5316\u3059\u308b\u3068\u3044\u3063\u305f\u30bf\u30b9\u30af\u3092\u5b9f\u73fe\u3057\u3084\u3059\u304f\u306a\u308a\u307e\u3059\u3002\u307e\u305fHTTP\u901a\u4fe1\u3092\u884c\u3046\u305f\u3081\u306e\u30e9\u30a4\u30d6\u30e9\u30ea\u306f\u591a\u304f\u306e\u30d7\u30ed\u30b0\u30e9\u30df\u30f3\u30b0\u8a00\u8a9e\u3067\u63d0\u4f9b\u3055\u308c\u3066\u304a\u308a\u3001\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u958b\u767a\u3092\u8a00\u8a9e\u3092\u554f\u308f\u305a\u884c\u3046\u3053\u3068\u304c\u3067\u304d\u308b\u306e\u306f REST API \u306e\u30e1\u30ea\u30c3\u30c8\u306e\u3072\u3068\u3064\u3067\u3059\u3002<\/p>\n<p>\u305d\u3053\u3067\u4eca\u56de\u306f\u3001cpprestsdk \u3068\u3044\u3046 C++ \u8a00\u8a9e\u304b\u3089 REST API \u3092\u5229\u7528\u3059\u308b\u305f\u3081\u306e\u30e9\u30a4\u30d6\u30e9\u30ea\u3092\u4f7f\u3044\u3001Redmine \u304b\u3089\u81ea\u52d5\u7684\u306b\u5de5\u6570\u30c7\u30fc\u30bf\u3092\u96c6\u3081\u3066\u307f\u307e\u3059\u3002<\/p>\n<h1>\u4f7f\u7528\u3059\u308b\u30c4\u30fc\u30eb<\/h1>\n<h2><a href=\"https:\/\/github.com\/microsoft\/cpprestsdk\">cpprestsdk<\/a><\/h2>\n<p>cpprestsdk \u306f Microsoft \u304c\u30aa\u30fc\u30d7\u30f3\u30bd\u30fc\u30b9\u3067\u958b\u767a\u3057\u3066\u3044\u308b\u3001REST API \u306e\u305f\u3081\u306e\u30af\u30ed\u30b9\u30d7\u30e9\u30c3\u30c8\u30d5\u30a9\u30fc\u30e0\u306a HTTP \u901a\u4fe1\u30e9\u30a4\u30d6\u30e9\u30ea\u3067\u3059\u3002<\/p>\n<p>\u975e\u540c\u671f\u51e6\u7406\u3092\u524d\u63d0\u3068\u3057\u305f\u30e2\u30c0\u30f3\u306a API \u3092\u6301\u3061\u3001\u7279\u306b GUI \u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3068\u306e\u76f8\u6027\u304c\u826f\u304f\u3001\u307e\u305f JSON \u3092\u6271\u3046\u6a5f\u80fd\u3082\u5185\u5305\u3057\u3066\u3044\u308b\u305f\u3081\u3059\u3050\u306b REST \u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u958b\u767a\u3092\u59cb\u3081\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002<\/p>\n<h2><a href=\"https:\/\/github.com\/microsoft\/vcpkg\">vcpkg<\/a><\/h2>\n<p>vcpkg \u306f Microsoft \u304c\u958b\u767a\u3057\u3066\u3044\u308b\u3001\u30af\u30ed\u30b9\u30d7\u30e9\u30c3\u30c8\u30d5\u30a9\u30fc\u30e0\u306e\u30aa\u30fc\u30d7\u30f3\u30bd\u30fc\u30b9 \u30d1\u30c3\u30b1\u30fc\u30b8\u30de\u30cd\u30fc\u30b8\u30e3\u30fc\u3067\u3059\u3002\u4eca\u56de\u306f cpprestsdk \u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3059\u308b\u305f\u3081\u306b\u4f7f\u3044\u307e\u3059\u3002<\/p>\n<p>vcpkg \u306b\u306f cpprestsdk \u4ee5\u5916\u306b\u3082\u3001OpenCV \u3084 FFmpeg \u306e\u3088\u3046\u306a\u30e1\u30b8\u30e3\u30fc\u306a\u3082\u306e\u304b\u3089 LLVM \u3068\u3044\u3063\u305f\u5927\u898f\u6a21\u306a\u30e9\u30a4\u30d6\u30e9\u30ea\u307e\u3067\u5e45\u5e83\u304f\u767b\u9332\u3055\u308c\u3066\u3044\u307e\u3059\u3002\u3055\u3089\u306bVisual Studio \u3078\u7d71\u5408\u3059\u308b\u3053\u3068\u3067\u3001\u5f93\u6765\u306f\u624b\u52d5\u3067\u8a2d\u5b9a\u3057\u3066\u3044\u305f\u30a4\u30f3\u30af\u30eb\u30fc\u30c9\u30d1\u30b9\u3084\u30e9\u30a4\u30d6\u30e9\u30ea\u30d1\u30b9\u3092\u81ea\u52d5\u7684\u306b\u89e3\u6c7a\u3057\u3066\u304f\u308c\u307e\u3059\u3002<\/p>\n<h1>\u4f5c\u696d\u74b0\u5883<\/h1>\n<ul>\n<li>Windows10 x64<\/li>\n<li>Visual Studio 2019<\/li>\n<li>Git<\/li>\n<\/ul>\n<h1>vcpkg \u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3059\u308b<\/h1>\n<p>vcpkg \u3092\u4f7f\u3046\u305f\u3081\u306b\u306f\u3001\u30bd\u30fc\u30b9\u30b3\u30fc\u30c9\u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3057\u3066\u30d3\u30eb\u30c9\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002\u3068\u8a00\u3063\u3066\u3082\u96e3\u3057\u3044\u8a2d\u5b9a\u306f\u4e0d\u8981\u3067\u3059\u3002\u30d0\u30c3\u30c1\u30d5\u30a1\u30a4\u30eb\u3092\u5b9f\u884c\u3059\u308b\u3053\u3068\u3067\u30d3\u30eb\u30c9\u3067\u304d\u308b\u3088\u3046\u306b\u306a\u3063\u3066\u3044\u307e\u3059\u306e\u3067\u3001\u305d\u308c\u3092\u4f7f\u3044\u307e\u3059\u3002<\/p>\n<p>\u307e\u305a\u306f vcpkg \u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3057\u307e\u3059\u3002\u4eca\u5f8c\u306f\u3053\u306e\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u5834\u6240\u3092 vcpkg \u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u30d5\u30a9\u30eb\u30c0\u3068\u3057\u3066\u4f7f\u7528\u3057\u3066\u3044\u304d\u307e\u3059\u306e\u3067\u3001&#8221;C:\\tools\\vcpkg&#8221; \u306a\u3069\u308f\u304b\u308a\u3084\u3059\u3044\u5834\u6240\u306b\u3059\u308b\u3068\u826f\u3044\u3067\u3057\u3087\u3046\u3002<br \/>\ngit clone \u3092\u4f7f\u3044\u3001\u30bf\u30b0\u306e\u4ed8\u3044\u305f\u30d0\u30fc\u30b8\u30e7\u30f3\u3092\u53d6\u5f97\u3057\u307e\u3059\u3002<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\" data-enlighter-theme=\"monokai\" data-enlighter-linenumbers=\"false\">git clone -b 2020.11 https:\/\/github.com\/microsoft\/vcpkg.git<\/pre>\n<p>\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3057\u305f\u30d5\u30a9\u30eb\u30c0\u5185\u306b\u3042\u308b bat \u30d5\u30a1\u30a4\u30eb\u3092\u5b9f\u884c\u3057\u3001\u30d3\u30eb\u30c9\u3092\u958b\u59cb\u3057\u307e\u3059\u3002<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\" data-enlighter-theme=\"monokai\" data-enlighter-linenumbers=\"false\">.\\bootstrap-vcpkg.bat<\/pre>\n<p>\u6210\u529f\u3059\u308b\u3068 vcpkg.exe \u304c\u4f5c\u6210\u3055\u308c\u307e\u3059\u3002\u52d5\u4f5c\u78ba\u8a8d\u3068\u3057\u3066\u3001\u30d0\u30fc\u30b8\u30e7\u30f3\u3092\u8868\u793a\u3057\u3066\u307f\u307e\u3059\u3002<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\" data-enlighter-theme=\"monokai\" data-enlighter-linenumbers=\"false\">.\\vcpkg version\nVcpkg package management program version 2020.06.15-nohash<\/pre>\n<p>\u6700\u5f8c\u306b Visual Studio \u3078\u7d71\u5408\u3057\u307e\u3059\u3002\u3053\u308c\u306b\u3088\u308a\u3001\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3057\u305f\u30e9\u30a4\u30d6\u30e9\u30ea\u306f\u30a4\u30f3\u30af\u30eb\u30fc\u30c9\u30d1\u30b9\u306a\u3069\u3092\u8ffd\u52a0\u8a2d\u5b9a\u3059\u308b\u3053\u3068\u306a\u304f\u4f7f\u7528\u3067\u304d\u308b\u3088\u3046\u306b\u306a\u308a\u307e\u3059\u3002<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\" data-enlighter-theme=\"monokai\" data-enlighter-linenumbers=\"false\">.\\vcpkg integrate install<\/pre>\n<p>\u4ee5\u4e0a\u3067\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u306f\u5b8c\u4e86\u3068\u306a\u308a\u307e\u3059\u304c\u3001\u30a2\u30f3\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3059\u308b\u5834\u5408\u306f &#8220;.\\vcpkg integrate remove&#8221; \u3092\u5b9f\u884c\u3057\u3066\u7d71\u5408\u3092\u89e3\u9664\u3057\u305f\u5f8c\u3001vcpkg \u30d5\u30a9\u30eb\u30c0\u81ea\u4f53\u3092\u524a\u9664\u3057\u307e\u3059\u3002<\/p>\n<h1>cpprestsdk \u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3059\u308b<\/h1>\n<p>\u6b21\u306e\u30b3\u30de\u30f3\u30c9\u3067\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3057\u307e\u3059\u3002<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\" data-enlighter-theme=\"monokai\" data-enlighter-linenumbers=\"false\">.\\vcpkg install cpprestsdk<\/pre>\n<p>\u30b3\u30de\u30f3\u30c9\u3092\u5b9f\u884c\u3059\u308b\u3068\u30e9\u30a4\u30d6\u30e9\u30ea\u306e\u30bd\u30fc\u30b9\u30b3\u30fc\u30c9\u304c\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3055\u308c\u3001\u30d3\u30eb\u30c9\u304c\u59cb\u307e\u308a\u307e\u3059\u3002<\/p>\n<p>\u6210\u529f\u3059\u308b\u3068\u3001vcpkg \u306e installed \u30d5\u30a9\u30eb\u30c0\u4ee5\u4e0b\u306b\u5fc5\u8981\u306a\u30d5\u30a1\u30a4\u30eb\u304c\u51fa\u529b\u3055\u308c\u307e\u3059\u3002<\/p>\n<h1>\u30c1\u30b1\u30c3\u30c8\u306e\u4e00\u89a7\u3092\u53d6\u5f97\u3059\u308b<\/h1>\n<p>\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u304c\u5b8c\u4e86\u3057\u305f\u3089\u3001\u307e\u305a\u306f cpprestsdk \u3068 Redmine REST API \u306e\u4f7f\u3044\u65b9\u3092\u78ba\u8a8d\u3059\u308b\u305f\u3081\u3001\u3042\u308b\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u5185\u306e\u30c1\u30b1\u30c3\u30c8\u306e\u4e00\u89a7\u3092\u53d6\u5f97\u3057\u3066\u307f\u307e\u3059\u3002<\/p>\n<p>Redmine \u306e\u30c1\u30b1\u30c3\u30c8\u306f\u3001API \u4e0a\u3067\u306f &#8220;issue&#8221; \u3068\u3044\u3046\u30c7\u30fc\u30bf\u69cb\u9020\u3067\u8868\u3055\u308c\u307e\u3059\u3002<a href=\"https:\/\/www.redmine.org\/projects\/redmine\/wiki\/rest_issues\" target=\"_blank\" rel=\"noopener\">\u30ea\u30d5\u30a1\u30ec\u30f3\u30b9<\/a>\u3092\u53c2\u8003\u306b\u3001&#8221;https:\/\/&#8230;\/issues.json&#8221; \u306e\u3088\u3046\u306a URL \u3078\u30a2\u30af\u30bb\u30b9\u3057\u307e\u3059\u3002<\/p>\n<p>VisualStudio \u3067\u30b3\u30f3\u30bd\u30fc\u30eb\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3092\u4f5c\u6210\u3057\u3001\u4ee5\u4e0b\u306e\u30d7\u30ed\u30b0\u30e9\u30e0\u3092\u6253\u3061\u8fbc\u307f\u307e\u3059\u3002\u306a\u304a\u5b9f\u884c\u3059\u308b\u5834\u5408\u3001\u4e8b\u524d\u306b\u6b21\u306e\u8981\u7d20\u3092\u5b9a\u6570\u306b\u30b3\u30d4\u30fc\u3057\u3066\u304f\u3060\u3055\u3044\u3002<\/p>\n<ul>\n<li>Redmine \u306e URL \u2192 BASE_URL<\/li>\n<li>Redmine \u306e API \u30ad\u30fc \u2192 API_KEY<\/li>\n<li>Redmine \u306e\u30d7\u30ed\u30b8\u30a7\u30af\u30c8ID \u2192 PROJECT_ID<\/li>\n<\/ul>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"atomic\" data-enlighter-linenumbers=\"false\">#include &lt;iostream&gt;\n#include &lt;clocale&gt;\n#include &lt;cpprest\/http_client.h&gt;\n#pragma comment(lib, \"Crypt32.lib\")\n#pragma comment(lib, \"Bcrypt.lib\")\n#pragma comment(lib, \"Winhttp.lib\")\n\nusing namespace web;\nusing namespace web::http;\nusing namespace web::http::client;\nusing namespace utility;\n\nconst string_t BASE_URL = L\"https:\/\/...\";  \/\/ Redmine \u306e URL\nconst string_t API_KEY = L\"...\";           \/\/ API \u30ad\u30fc\nconst string_t PROJECT_ID = L\"...\";        \/\/ \u30d7\u30ed\u30b8\u30a7\u30af\u30c8ID\n\n\nint main()\n{\n    \/\/ wchar_t \u3092\u6a19\u6e96\u51fa\u529b\u3067\u304d\u308b\u3088\u3046\u306b\u3059\u308b\n    std::setlocale(LC_ALL, \"\");\n\n    \/\/ URL \u3092\u4f5c\u6210\u3059\u308b\n    auto uri = uri_builder(L\"issues.json\")\n        .append_query(L\"key\", API_KEY)\n        .append_query(L\"project_id\", PROJECT_ID)\n        .append_query(L\"status_id\", L\"closed\")\n        .append_query(L\"limit\", L\"100\")\n        .to_string();\n\n    \/\/ \u30c1\u30b1\u30c3\u30c8\u306e\u4e00\u89a7\u3092\u53d6\u5f97\u3057\u3066\u8868\u793a\u3059\u308b\n    auto client = http_client(BASE_URL);\n    client.request(methods::GET, uri)   \/\/ GET \u30ea\u30af\u30a8\u30b9\u30c8\u3092\u9001\u4fe1\u3059\u308b\n        .then([](http_response response) {   \/\/ \u30ec\u30b9\u30dd\u30f3\u30b9\u304c\u8fd4\u3063\u3066\u304d\u305f\u3089\u3001JSON \u30c7\u30fc\u30bf\u69cb\u9020\u3092\u69cb\u7bc9\u3059\u308b\n            return response.extract_json();\n        })\n        .then([](json::value json) {   \/\/ JSON \u30c7\u30fc\u30bf\u69cb\u9020\u306e\u69cb\u7bc9\u304c\u5b8c\u4e86\u3057\u305f\u3089\u3001\u5fc5\u8981\u306a\u60c5\u5831\u3092\u8aad\u307f\u53d6\u308b\n            for (auto&amp; issue : json[L\"issues\"].as_array()) {\n                std::wcout &lt;&lt; L\"#\" &lt;&lt; issue[L\"id\"].as_integer() &lt;&lt; \" \" &lt;&lt; issue[L\"subject\"].as_string() &lt;&lt; std::endl;\n            }\n        })\n        .wait();   \/\/ \u5168\u3066\u306e\u51e6\u7406\u304c\u7d42\u308f\u308b\u307e\u3067\u5f85\u3064\n\n    return 0;\n}<\/pre>\n<p>\u5b9f\u884c\u7d50\u679c\u306f\u6b21\u306e\u3088\u3046\u306b\u306a\u308a\u307e\u3059\u3002<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"monokai\" data-enlighter-linenumbers=\"false\">#4674 \u898b\u7a4d\u30c6\u30b9\u30c8\u30c1\u30b1\u30c3\u30c81\n#4655 \u898b\u7a4d\u30c6\u30b9\u30c8\u30c1\u30b1\u30c3\u30c82\n#4652 \u898b\u7a4d\u30c6\u30b9\u30c8\u30c1\u30b1\u30c3\u30c83\n#4588 \u898b\u7a4d\u30c6\u30b9\u30c8\u30c1\u30b1\u30c3\u30c84\n#4587 \u898b\u7a4d\u30c6\u30b9\u30c8\u30c1\u30b1\u30c3\u30c85<\/pre>\n<p>cpprestsdk \u306e\u7279\u5fb4\u7684\u306a\u3068\u3053\u308d\u306f\u3001request() \u306e\u623b\u308a\u5024\u304c\u975e\u540c\u671f\u3067\u5b9f\u884c\u3057\u305f\u3044\u51e6\u7406\u3092\u3064\u306a\u3052\u308b\u305f\u3081\u306e task&lt;&gt; \u30af\u30e9\u30b9\u306b\u306a\u3063\u3066\u3044\u308b\u3068\u3053\u308d\u3067\u3059\u3002\u3053\u308c\u306b then() \u3092\u4f7f\u3063\u3066\u3001\u5b9f\u884c\u3057\u305f\u3044\u51e6\u7406\u3092\u9806\u306b\u8a2d\u5b9a\u3057\u3066\u3044\u304d\u307e\u3059\u3002<\/p>\n<p>\u3053\u306e\u30b9\u30bf\u30a4\u30eb\u306f <a href=\"https:\/\/developer.mozilla.org\/ja\/docs\/Web\/API\/Fetch_API\" target=\"_blank\" rel=\"noopener\">JavaScript \u306e Fetch API<\/a> \u3068\u3088\u304f\u4f3c\u3066\u3044\u307e\u3059\u3002\u305f\u3060\u3057\u3001then() \u306b\u6307\u5b9a\u3057\u305f\u51e6\u7406\u306f\u5225\u306e\u30b9\u30ec\u30c3\u30c9\u304b\u3089\u30b3\u30fc\u30eb\u3055\u308c\u307e\u3059\u3002\u4eca\u56de\u306f\u30b7\u30f3\u30d7\u30eb\u306a\u30b3\u30f3\u30bd\u30fc\u30eb\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3067\u3042\u308b\u305f\u3081\u3053\u306e\u70b9\u3092\u610f\u8b58\u3059\u308b\u5fc5\u8981\u306f\u3042\u308a\u307e\u305b\u3093\u304c\u3001\u5b9f\u969b\u306bGUI\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3078\u7d44\u307f\u8fbc\u3080\u969b\u306f\u30c7\u30fc\u30bf\u30a2\u30af\u30bb\u30b9\u306e\u7af6\u5408\u3084\u30d7\u30ed\u30b0\u30ec\u30b9\u30d0\u30fc\u306a\u3069GUI\u30b3\u30f3\u30c8\u30ed\u30fc\u30eb\u306e\u64cd\u4f5c\u306b\u6ce8\u610f\u304c\u5fc5\u8981\u3067\u3059\u3002<\/p>\n<h1>\u898b\u7a4d\u6642\u9593\u3068\u5b9f\u7e3e\u6642\u9593\u3092\u96c6\u8a08\u3059\u308b<\/h1>\n<p>\u898b\u7a4d\u6642\u9593\u306f&nbsp; Issue \u306e\u30d5\u30a3\u30fc\u30eb\u30c9\u3067\u3042\u308b &#8220;estimated_hours&#8221; \u304b\u3089\u53d6\u5f97\u3057\u307e\u3059\u3002<br \/>\n\u5b9f\u7e3e\u6642\u9593\u306f&nbsp; Issue \u3068\u306f\u5225\u306e <a href=\"https:\/\/www.redmine.org\/projects\/redmine\/wiki\/Rest_TimeEntries\" target=\"_blank\" rel=\"noopener\">TimeEntries<\/a> \u3068\u3044\u3046\u30c7\u30fc\u30bf\u3068\u3057\u3066\u4fdd\u5b58\u3055\u308c\u3066\u3044\u307e\u3059\u306e\u3067\u3001\u305d\u3053\u304b\u3089\u53d6\u5f97\u3057\u307e\u3059\u3002<\/p>\n<p>\u3053\u308c\u3089\u3092\u96c6\u8a08\u3057\u3001\u898b\u7a4d\u306b\u5bfe\u3059\u308b\u5b9f\u7e3e\u6642\u9593\u306e\u591a\u3055\u3092\u30c1\u30b1\u30c3\u30c8\u3054\u3068\u306b\u30d1\u30fc\u30bb\u30f3\u30c6\u30fc\u30b8\u3067\u8868\u793a\u3057\u3066\u307f\u307e\u3059\u3002<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"atomic\" data-enlighter-linenumbers=\"false\">#include &lt;iostream&gt;\n#include &lt;clocale&gt;\n#include &lt;cpprest\/http_client.h&gt;\n#pragma comment(lib, \"Crypt32.lib\")\n#pragma comment(lib, \"Bcrypt.lib\")\n#pragma comment(lib, \"Winhttp.lib\")\n\nusing namespace web;\nusing namespace web::http;\nusing namespace web::http::client;\nusing namespace utility;\n\nconst string_t BASE_URL = L\"https:\/\/...\";  \/\/ Redmine \u306e URL\nconst string_t API_KEY = L\"...\";           \/\/ API \u30ad\u30fc\nconst string_t PROJECT_ID = L\"...\";        \/\/ \u30d7\u30ed\u30b8\u30a7\u30af\u30c8ID\n\nstruct Issue\n{\n    int id;                     \/\/ \u30c1\u30b1\u30c3\u30c8ID\n    string_t subject;           \/\/ \u30c1\u30b1\u30c3\u30c8\u30bf\u30a4\u30c8\u30eb\n    double estimated_hours;     \/\/ \u898b\u7a4d\u5de5\u6570\n    double total_time_entiries; \/\/ \u5b9f\u7e3e\u5de5\u6570\n};\n\nint main()\n{\n    \/\/ wchar_t \u3092\u6a19\u6e96\u51fa\u529b\u3067\u304d\u308b\u3088\u3046\u306b\u3059\u308b\n    std::setlocale(LC_ALL, \"\");\n\n    \/\/ URL \u3092\u4f5c\u6210\u3059\u308b\n    auto uri = uri_builder(L\"issues.json\")\n        .append_query(L\"key\", API_KEY)\n        .append_query(L\"project_id\", PROJECT_ID)\n        .append_query(L\"limit\", L\"100\")\n        .append_query(L\"status_id\", L\"closed\")\n        .to_string();\n\n    \/\/ \u30c1\u30b1\u30c3\u30c8\u306e\u4e00\u89a7\u3092\u53d6\u5f97\u3059\u308b\n    auto client = http_client(BASE_URL);\n    auto issues = client.request(methods::GET, uri) \/\/ GET \u30ea\u30af\u30a8\u30b9\u30c8\u3092\u9001\u4fe1\u3059\u308b\n        .then([](http_response response) { \/\/ \u30ec\u30b9\u30dd\u30f3\u30b9\u304c\u8fd4\u3063\u3066\u304d\u305f\u3089\u3001JSON \u30c7\u30fc\u30bf\u69cb\u9020\u3092\u4f5c\u6210\u3059\u308b\n            return response.extract_json();\n        })\n        .then([](json::value json) { \/\/ JSON \u30c7\u30fc\u30bf\u69cb\u9020\u306e\u4f5c\u6210\u304c\u5b8c\u4e86\u3057\u305f\u3089\u3001\u5fc5\u8981\u306a\u60c5\u5831\u3092\u8aad\u307f\u53d6\u308b\n            std::vector&lt;Issue&gt; result;\n            for (auto&amp; issue : json[L\"issues\"].as_array()) {\n                result.push_back(Issue{\n                    issue[L\"id\"].as_integer(),\n                    issue[L\"subject\"].as_string(),\n                    issue[L\"estimated_hours\"].is_double() ? issue[L\"estimated_hours\"].as_double() : 0.0,\n                    0.0,\n                });\n            }\n            return result;\n        })\n        .get(); \/\/ \u5168\u3066\u306e\u51e6\u7406\u304c\u7d42\u308f\u308b\u307e\u3067\u5f85\u3064\u3002\u5b8c\u4e86\u3057\u305f\u3089 std::vector&lt;Issue&gt; \u304c\u8fd4\u3063\u3066\u304f\u308b\n        \n    \/\/ \u30c1\u30b1\u30c3\u30c8\u3054\u3068\u306b\u4f5c\u696d\u6642\u9593\u3092\u96c6\u8a08\u3059\u308b\n    for (auto&amp; issue : issues) {\n        auto uri = uri_builder(L\"time_entries.json\")\n            .append_query(L\"key\", API_KEY)\n            .append_query(L\"issue_id\", std::to_wstring(issue.id))\n            .append_query(L\"status_id\", L\"closed\")\n            .append_query(L\"limit\", L\"100\")\n            .to_string();\n\n        issue.total_time_entiries = client.request(methods::GET, uri)\n            .then([](http_response response) {\n                return response.extract_json();\n            })\n            .then([](json::value json) {\n                double total = 0.0;\n                for (auto&amp; time_entiry : json[L\"time_entries\"].as_array()) {\n                    auto hours = time_entiry[L\"hours\"];\n                    total += hours.is_double() ? hours.as_double() : 0.0;\n                }\n                return total;\n            })\n            .get();\n    }\n\n    \/\/ \u7d50\u679c\u3092\u8868\u793a\u3059\u308b\n    for (auto&amp; issue : issues) {\n        std::wcout\n            &lt;&lt; \"#\" &lt;&lt; issue.id &lt;&lt; \" \"\n            &lt;&lt; issue.subject &lt;&lt; \" \"\n            &lt;&lt; \"(\" &lt;&lt; static_cast&lt;int&gt;(100 * (issue.total_time_entiries \/ issue.estimated_hours)) &lt;&lt; \"%) \"\n            &lt;&lt; issue.total_time_entiries &lt;&lt; \"\/\" &lt;&lt; issue.estimated_hours &lt;&lt; \" \"\n            &lt;&lt; std::endl;\n    }\n\n    return 0;\n}<\/pre>\n<p>\u5b9f\u884c\u7d50\u679c\u306f\u6b21\u306e\u3088\u3046\u306b\u306a\u308a\u307e\u3059\u3002\u8868\u793a\u306f\u3001&#8221;(\u8d85\u904e\u7387%) \u5b9f\u7e3e\u6642\u9593\/\u898b\u7a4d\u6642\u9593&#8221; \u3067\u3059\u3002<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"raw\" data-enlighter-theme=\"monokai\" data-enlighter-linenumbers=\"false\">#4959 \u898b\u7a4d\u30c6\u30b9\u30c8\u30c1\u30b1\u30c3\u30c820    (100%) 1\/1\n#4957 \u898b\u7a4d\u30c6\u30b9\u30c8\u30c1\u30b1\u30c3\u30c821    (58%) 3.5\/6\n#4955 \u898b\u7a4d\u30c6\u30b9\u30c8\u30c1\u30b1\u30c3\u30c822    (62%) 1.25\/2\n#4953 \u898b\u7a4d\u30c6\u30b9\u30c8\u30c1\u30b1\u30c3\u30c823    (87%) 1.75\/2\n#4951 \u898b\u7a4d\u30c6\u30b9\u30c8\u30c1\u30b1\u30c3\u30c824    (112%) 2.25\/2\n#4946 \u898b\u7a4d\u30c6\u30b9\u30c8\u30c1\u30b1\u30c3\u30c825    (87%) 1.75\/2<\/pre>\n<h1>Redmine \u306e API \u3067 100 \u4ef6\u4ee5\u4e0a\u306e\u30c7\u30fc\u30bf\u3092\u53d6\u5f97\u3059\u308b\u969b\u306e\u6ce8\u610f\u70b9<\/h1>\n<p>\u4eca\u56de\u306f URL \u306e\u30af\u30a8\u30ea\u30d1\u30e9\u30e1\u30fc\u30bf\u3068\u3057\u3066 limit=100 \u3092\u6307\u5b9a\u3057\u3066\u304a\u308a\u3001\u4e00\u5ea6\u306b100\u4ef6\u306e\u30c7\u30fc\u30bf\u3092\u53d6\u5f97\u3067\u304d\u307e\u3059\u3002\u3057\u304b\u3057 Redmine \u306e\u5236\u7d04\u3068\u3057\u3066 100 \u4ef6\u3088\u308a\u591a\u304f\u306e\u30c7\u30fc\u30bf\u3092\u4e00\u5ea6\u306b\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3002<\/p>\n<p>\u4efb\u610f\u306e\u7bc4\u56f2\u306e\u30c7\u30fc\u30bf\u3092\u53d6\u5f97\u3059\u308b\u306b\u306f\u3001API \u306b &#8220;page&#8221; \u3068\u3044\u3046\u30af\u30a8\u30ea\u30d1\u30e9\u30e1\u30fc\u30bf\u3092\u6307\u5b9a\u3057\u307e\u3059\u3002100 \u4ef6\u305a\u3064\u53d6\u5f97\u3059\u308b\u5834\u5408\u306f\u4f8b\u3048\u3070\u3001<\/p>\n<ul>\n<li>1\uff5e100 \u3092\u53d6\u5f97\u3059\u308b\u306b\u306f &#8220;page=1&#8221;<\/li>\n<li>101\uff5e200 \u3092\u53d6\u5f97\u3059\u308b\u306b\u306f &#8220;page=2&#8221;<\/li>\n<li>201\uff5e300 \u3092\u53d6\u5f97\u3059\u308b\u306b\u306f &#8220;page=3&#8221;<\/li>\n<\/ul>\n<p>\u30fb\u30fb\u30fb\u3068\u3044\u3063\u305f\u3088\u3046\u306b\u3001page \u756a\u53f7\u3092\u6307\u5b9a\u3057\u306a\u304c\u3089\u8907\u6570\u56de\u306e\u30ea\u30af\u30a8\u30b9\u30c8\u3092\u9001\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002<\/p>\n<p>\u4f8b\u3048\u3070\u3001Issue \u306e\u53d6\u5f97\u306f\u6b21\u306e\u3088\u3046\u306b\u4fee\u6b63\u3067\u304d\u307e\u3059\u3002<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"atomic\" data-enlighter-linenumbers=\"false\">int main()\n{\n    \/\/ wchar_t \u3092\u6a19\u6e96\u51fa\u529b\u3067\u304d\u308b\u3088\u3046\u306b\u3059\u308b\n    std::setlocale(LC_ALL, \"\");\n\n    auto client = http_client(BASE_URL);\n\n    \/\/ \u30da\u30fc\u30b8\u6570\u3092\u53d6\u5f97\u3059\u308b\n    int page_count = 0;\n    {\n        auto uri = uri_builder(L\"issues.json\")\n            .append_query(L\"key\", API_KEY)\n            .append_query(L\"project_id\", PROJECT_ID)\n            .append_query(L\"status_id\", L\"closed\")\n            .to_string();\n\n        page_count = client.request(methods::GET, uri)\n            .then([](http_response response) {\n                return response.extract_json();\n            })\n            .then([](json::value json) {\n                return (json[L\"total_count\"].as_integer() \/ 100) + 1;\n            })\n            .get();\n    }\n\n    for (int i = 0; i &lt; page_count; i++) {  \/\/ \u30da\u30fc\u30b8\u6570\u3060\u3051\u7e70\u308a\u8fd4\u3059\n        \/\/ URL \u3092\u4f5c\u6210\u3059\u308b\n        auto uri = uri_builder(L\"issues.json\")\n            .append_query(L\"key\", API_KEY)\n            .append_query(L\"project_id\", PROJECT_ID)\n            .append_query(L\"status_id\", L\"closed\")\n            .append_query(L\"limit\", L\"100\")\n            .append_query(L\"page\", std::to_wstring(i + 1))  \/\/ \u30da\u30fc\u30b8\u756a\u53f7\u3092\u6307\u5b9a\u3059\u308b\n            .to_string();\n\n        \/\/ \u30c1\u30b1\u30c3\u30c8\u306e\u4e00\u89a7\u3092\u53d6\u5f97\u3059\u308b\n        client.request(methods::GET, uri)\n            .then([](http_response response) { \n                return response.extract_json();\n            })\n            .then([](json::value json) {\n                for (auto&amp; issue : json[L\"issues\"].as_array()) {\n                    std::wcout &lt;&lt; L\"#\" &lt;&lt; issue[L\"id\"].as_integer() &lt;&lt; \" \" &lt;&lt; issue[L\"subject\"].as_string() &lt;&lt; std::endl;\n                }\n            })\n            .wait();\n    }\n \n    return 0;\n}<\/pre>\n<h1>\u307e\u3068\u3081<\/h1>\n<p>vcpkg \u3068 cpprestsdk \u3092\u4f7f\u3063\u3066\u3001Redmine \u304b\u3089\u5de5\u6570\u5b9f\u7e3e\u3092\u53d6\u5f97\u3057\u3066\u307f\u307e\u3057\u305f\u3002<\/p>\n<p>\u5c11\u3057\u524d\u307e\u3067\u306e C++ \u306b\u306f\u3053\u306e\u3088\u3046\u306a\u30d1\u30c3\u30b1\u30fc\u30b8\u7ba1\u7406\u3084\u30e9\u30a4\u30d6\u30e9\u30ea\u306f\u7121\u304f\u3001HTTP \u901a\u4fe1\u3092\u3059\u308b\u3060\u3051\u3067\u3082\u3001\u96e3\u3057\u3044\u74b0\u5883\u69cb\u7bc9\u3084\u5197\u9577\u306a\u30b3\u30fc\u30c9\u3092\u66f8\u304b\u3056\u308b\u3092\u5f97\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u3057\u304b\u3057\u4eca\u56de\u3067\u3001\u975e\u5e38\u306b\u30b7\u30f3\u30d7\u30eb\u306a\u30b3\u30fc\u30c9\u3067 REST API \u306b\u30a2\u30af\u30bb\u30b9\u3067\u304d\u308b\u3053\u3068\u304c\u78ba\u8a8d\u3067\u304d\u307e\u3057\u305f\u3002<\/p>\n<p>\u305f\u3060\u4eca\u56de\u306e\u30b5\u30f3\u30d7\u30eb\u306f\u30b3\u30f3\u30bd\u30fc\u30eb\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3067\u3042\u308b\u305f\u3081\u3001\u8996\u899a\u7684\u306a\u8868\u73fe\u3068\u3044\u3046\u3068\u3053\u308d\u306b\u306f\u307e\u3060\u307e\u3060\u53ca\u3073\u307e\u305b\u3093\u3002\u30b0\u30e9\u30d5\u30a3\u30ab\u30eb\u306a\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3068\u7d44\u307f\u5408\u308f\u305b\u305f\u8868\u73fe\u306e\u7814\u7a76\u306f\u3053\u308c\u304b\u3089\u306e\u8ab2\u984c\u3068\u306a\u308a\u305d\u3046\u3067\u3059\u3002<\/p>\n<p>\u4eca\u5f8c\u3082\u3001\u30c7\u30fc\u30bf\u306e\u53d6\u308a\u6271\u3044\u306e\u81ea\u52d5\u5316\u3084\u30c7\u30fc\u30bf\u30d3\u30b8\u30e5\u30a2\u30e9\u30a4\u30bc\u30fc\u30b7\u30e7\u30f3\u306b\u3064\u3044\u3066\u691c\u8a3c\u3057\u3066\u3044\u304d\u307e\u3059\u3002<\/p>\n<div class=\"box_border_gray\">\u30cf\u30fc\u30c8\u30e9\u30f3\u30c9\u306e\u3042\u305f\u3089\u3057\u3044\u30c6\u30b9\u30c8\u30c4\u30fc\u30eb\u300cDT+\u30b7\u30ea\u30fc\u30ba\u300d<br \/>\n\u958b\u767a\u306b\u3042\u305f\u308a\u3001\u672c\u7a3f\u3067\u3082\u7d39\u4ecb\u3057\u3066\u3044\u308b&#8221;Redmine&#8221;\u3092\u4f7f\u7528\u3057\u307e\u3057\u305f!<\/p>\n<h5>\u52d5\u7684\u3001\u7d99\u627f\u3002DT+\u30b7\u30ea\u30fc\u30ba\u3001\u65b0\u767b\u5834\u3002<\/h5>\n<p>\u4eca\u307e\u3067\u306eDT\u30b7\u30ea\u30fc\u30ba\u306e\u6a5f\u80fd\u306f\u305d\u306e\u307e\u307e\u306b\u3001<br \/>\n\u30d1\u30fc\u30bd\u30ca\u30eb\u306a\u30c7\u30d0\u30c3\u30b0\u304b\u3089\u3001\u30c6\u30b9\u30c8\u306e\u81ea\u52d5\u5316\u3001\u30ea\u30e2\u30fc\u30c8\u30c6\u30b9\u30c8\u307e\u3067\u3001<br \/>\n\u591a\u69d8\u306a\u958b\u767a\u30b9\u30bf\u30a4\u30eb\u306b\u5e45\u5e83\u304f\u5bfe\u5fdc\u3067\u304d\u308b\u3001\u9032\u5316\u3059\u308b\u52d5\u7684\u30c6\u30b9\u30c8\u30c4\u30fc\u30eb\u3001<br \/>\n\u305d\u308c\u304cDT+\u3002<\/p>\n<div>\n<p style=\"padding-top: 15px;\"><a class=\"button button-blue\" target=\"_blank\" href=\"https:\/\/hldc.co.jp\/product_service\/development\/dtplus\/\" onclick=\"gtag('event', 'Click', {'event_category': 'Link_bottom','event_label': '\u300c\u52d5\u7684\u300d\u65b0\u6642\u4ee3 Vol.2_\u88fd\u54c1\u60c5\u5831\u306f\u3053\u3061\u3089'});\">\uff1e \u88fd\u54c1\u60c5\u5831\u306f\u3053\u3061\u3089<\/a><\/p>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Redmine \u306f REST API \u3092\u516c\u958b\u3057\u3066\u304a\u308a\u3001\u5916\u90e8\u306e\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306f\u3053\u308c\u3092\u4f7f\u3046\u3053\u3068\u3067 Redmine \u304c\u7ba1\u7406\u3057\u3066\u3044\u308b\u60c5\u5831\u3078\u7c21\u5358\u306b\u30a2\u30af\u30bb\u30b9\u3067\u304d\u307e\u3059\u3002\u3053\u308c\u306b\u3088\u3063\u3066\u5de5\u6570\u306e\u96c6\u8a08\u3092\u81ea\u52d5\u5316\u3057\u305f\u308a\u3001\u30c7\u30fc\u30bf\u3092\u53ef\u8996\u5316\u3059\u308b\u3068\u3044\u3063\u305f\u30bf\u30b9\u30af\u3092\u5b9f\u73fe\u3057\u3084\u3059\u304f\u306a\u308a\u307e\u3059\u3002\u4eca\u56de\u306f\u3001cpprestsdk \u3068\u3044\u3046 C++ \u8a00\u8a9e\u304b\u3089 REST API \u3092\u5229\u7528\u3059\u308b\u305f\u3081\u306e\u30e9\u30a4\u30d6\u30e9\u30ea\u3092\u4f7f\u3044\u3001Redmine \u304b\u3089\u81ea\u52d5\u7684\u306b\u5de5\u6570\u30c7\u30fc\u30bf\u3092\u96c6\u3081\u3066\u307f\u307e\u3059\u3002<\/p>\n","protected":false},"author":5,"featured_media":5886,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_et_pb_use_builder":"","_et_pb_old_content":"","_et_gb_content_width":"","_links_to":"","_links_to_target":""},"categories":[2,13],"tags":[],"featured_image_src":"https:\/\/hldc.co.jp\/blog\/wp-content\/uploads\/2021\/02\/4212478_l-400x250.jpg","post_categories":[{"term_id":2,"name":"\u6280\u8853\u60c5\u5831","link":"https:\/\/hldc.co.jp\/blog\/category\/technical\/"},{"term_id":13,"name":"\u81ea\u52d5\u5316","link":"https:\/\/hldc.co.jp\/blog\/category\/%e8%87%aa%e5%8b%95%e5%8c%96\/"}],"_links":{"self":[{"href":"https:\/\/hldc.co.jp\/blog\/wp-json\/wp\/v2\/posts\/5542"}],"collection":[{"href":"https:\/\/hldc.co.jp\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/hldc.co.jp\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/hldc.co.jp\/blog\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/hldc.co.jp\/blog\/wp-json\/wp\/v2\/comments?post=5542"}],"version-history":[{"count":2,"href":"https:\/\/hldc.co.jp\/blog\/wp-json\/wp\/v2\/posts\/5542\/revisions"}],"predecessor-version":[{"id":13032,"href":"https:\/\/hldc.co.jp\/blog\/wp-json\/wp\/v2\/posts\/5542\/revisions\/13032"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/hldc.co.jp\/blog\/wp-json\/wp\/v2\/media\/5886"}],"wp:attachment":[{"href":"https:\/\/hldc.co.jp\/blog\/wp-json\/wp\/v2\/media?parent=5542"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hldc.co.jp\/blog\/wp-json\/wp\/v2\/categories?post=5542"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hldc.co.jp\/blog\/wp-json\/wp\/v2\/tags?post=5542"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}