{"id":252685,"date":"2015-03-10T00:00:02","date_gmt":"2015-03-09T20:00:02","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=252685"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=252685","title":{"rendered":"REST \u0441\u0435\u0440\u0432\u0438\u0441 \u043d\u0430 C++: POCO+Angular TODO"},"content":{"rendered":"<p>     \t<a href=\"http:\/\/pocoproject.org\/\">POCO<\/a> \u2014 \u043a\u0440\u043e\u0441\u0441\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u0430\u044f open-source \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043d\u0430 \u0421++ \u043f\u043e\u0434 Boost Software License: <a href=\"http:\/\/ru.wikipedia.org\/wiki\/POCO\">ru.wikipedia.org\/wiki\/POCO<\/a>.<br \/>  <a href=\"http:\/\/pocoproject.org\/\">POCO<\/a> \u0438\u043c\u0435\u0435\u0442 \u0432 \u0441\u0432\u043e\u0435\u043c \u0441\u043e\u0441\u0442\u0430\u0432\u0435 \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0432\u0435\u0431-\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 c <a href=\"http:\/\/https:\/\/ru.wikipedia.org\/wiki\/REST\">RESTful API<\/a>.<br \/>  \u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0442\u0430\u043a\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 TODO.<br \/>  <img decoding=\"async\" src=\"\/\/habrastorage.org\/files\/118\/76b\/5fa\/11876b5fa78c4805b3d887b5f10cd0f2.png\"\/><br \/>  <a name=\"habracut\"><\/a><br \/>  \u041f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0435\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 TODO \u2014 \u044d\u0442\u043e \u0441\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u0434\u0430\u0447 \u0441 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u0438\u043b\u0438 \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u0438.<\/p>\n<p>  \u0417\u0430\u0434\u0430\u0447\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u0432 CTodo. \u041a\u0430\u0436\u0434\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435 \u0432 \u0441\u043f\u0438\u0441\u043a\u0435 \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 (id) \u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 (text). <br \/>  \u0421\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u0434\u0430\u0447 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u0432 CTodoList. \u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u043f\u0438\u0441\u043a\u043e\u043c \u0437\u0430\u0434\u0430\u0447 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043c\u0435\u0442\u043e\u0434\u0430\u043c\u0438 <a href=\"https:\/\/ru.wikipedia.org\/wiki\/CRUD\">CRUD<\/a> \u0414\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u043f\u0438\u0441\u043a\u0430 \u0437\u0430\u0434\u0430\u0447 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f std::map. <br \/>  Http \u0441\u0435\u0440\u0432\u0435\u0440 \u0431\u044d\u043a\u0435\u043d\u0434\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u0432 TodoServerApp. \u0414\u0430\u043d\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043c\u0435\u0442\u043e\u0434\u044b CRUD, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0441\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u0434\u0430\u0447 \u0438 \u043c\u044c\u044e\u0442\u0435\u043a\u0441 \u0434\u043b\u044f \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u043d\u0435\u043c\u0443. \u041c\u0435\u0442\u043e\u0434 main \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0438\u0437 \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 POCO ServerApplication.<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">TodoServerApp.h<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">#pragma once  #include &lt;Poco\/Mutex.h&gt; #include &lt;Poco\/Net\/HTTPServerRequest.h&gt; #include &lt;Poco\/Net\/HTTPRequestHandler.h&gt; #include &lt;Poco\/Net\/HTTPServerResponse.h&gt; #include &lt;Poco\/Net\/HTTPServer.h&gt; #include &lt;Poco\/Net\/HTTPRequestHandlerFactory.h&gt; #include &lt;Poco\/Net\/HTMLForm.h&gt; #include &lt;Poco\/Path.h&gt; #include &lt;Poco\/ScopedLock.h&gt; #include &lt;Poco\/StringTokenizer.h&gt; #include &lt;Poco\/URI.h&gt; #include &lt;Poco\/Util\/ServerApplication.h&gt;  using namespace Poco; using namespace Poco::Net; using namespace Poco::Util; using namespace std;  \/**     Todo *\/ class CTodo {     size_t id;     string text; public:     CTodo(string text): text(text){     }     \/* getters & setters *\/     size_t getId(){ return id; }     void setId(size_t id){ this-&gt;id = id; }     string getText(){ return text; } };  \/**     \u0421\u043f\u0438\u0441\u043e\u043a Todo *\/ class CTodoList {     size_t id;     map&lt;size_t, CTodo&gt; todos;  public:     CTodoList():id(0){}     \/* CRUD *\/     void create(CTodo& todo){ todo.setId(++id); todos.insert(pair&lt;size_t,CTodo&gt;(id, todo)); };     map&lt;size_t, CTodo&gt;& readList(){ return todos; }     void del(size_t id){ todos.erase(id); }; };  \/**     \u0421\u0435\u0440\u0432\u0435\u0440 *\/ class TodoServerApp : public ServerApplication { public:     \/* CRUD *\/     static void createTodo(CTodo& todo);     static CTodoList& readTodoList();     \/\/static void updateTodo(size_t id, CTodo& todo);     static void deleteTodo(size_t id);  protected:     int main(const vector&lt;string&gt; &);     static Mutex todoLock;     static CTodoList todoList; }; <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u041f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 \u043c\u0435\u0442\u043e\u0434\u0430 main \u0432 \u043a\u043b\u0430\u0441\u0441\u0435 TodoServerApp \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f Http \u0441\u0435\u0440\u0432\u0435\u0440 \u0441 \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438 (\u043f\u043e\u0440\u0442 8000 \u0438 \u0442.\u0434.). \u0422\u0430\u043a\u0436\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442\u0441\u044f \u0444\u0430\u0431\u0440\u0438\u043a\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 TodoRequestHandlerFactory. <br \/>  \u041f\u043e\u0441\u043b\u0435 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 \u0446\u0438\u043a\u043b.<br \/>  \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0444\u0430\u0431\u0440\u0438\u043a\u0430 TodoRequestHandlerFactory \u0438\u043c\u0435\u0435\u0442 \u0432\u0441\u0435\u0433\u043e \u0434\u0432\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430: CFileHandler \u0434\u043b\u044f \u043e\u0442\u0434\u0430\u0447\u0438 \u0441\u0442\u0430\u0442\u0438\u043a\u0438 \u0438 CTodoHandler \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0434\u043b\u044f \u0441\u0430\u043c\u043e\u0433\u043e REST API.<br \/>  \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a REST API CTodoHandler \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u0442\u0438\u043f \u0437\u0430\u043f\u0440\u043e\u0441\u0430 (GET\/POST\/PUT\/DELETE). \u0414\u043b\u044f \u043c\u0435\u0442\u043e\u0434\u043e\u0432 PUT\/DELETE \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u0442\u0441\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043f\u043e URI. \u0412 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0435 \u0441 \u0442\u0438\u043f\u043e\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u044f\u0442\u0441\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0441\u043f\u0438\u0441\u043a\u0430. <br \/>  \u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0434\u0430\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u043e\u0435, \u043c\u0435\u0442\u043e\u0434 PUT \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f. \u0412\u044b\u0434\u0430\u0447\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u0434\u043b\u044f GET \u043f\u043e id \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u0437\u0430\u0434\u0430\u043d\u0438\u044f \u0442\u0430\u043a\u0436\u0435 \u043d\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043e. <br \/>  \u0414\u0430\u043b\u0435\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0442\u0432\u0435\u0442\u0430 \u0432 \u0432\u044b\u0445\u043e\u0434\u043d\u043e\u0439 \u043f\u043e\u0442\u043e\u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0430. \u0421 \u044d\u0442\u043e\u0439 \u0446\u0435\u043b\u044c\u044e \u0434\u043b\u044f \u0437\u0430\u0434\u0430\u0447\u0438 CTodo \u0438 \u0441\u043f\u0438\u0441\u043a\u0430 \u0437\u0430\u0434\u0430\u0447 CTodoList \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0436\u0435\u043d \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 &lt;&lt;.<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">TodoServerApp.cpp<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">#include &lt;iostream&gt; #include &lt;string&gt;  #include &quot;TodoServerApp.h&quot;  Mutex TodoServerApp::todoLock; CTodoList TodoServerApp::todoList;  ostream& operator&lt;&lt;(ostream& os, CTodo& todo) {     os &lt;&lt; &quot;{ \\&quot;_id\\&quot;: &quot;&lt;&lt; todo.getId() &lt;&lt;  &quot;, \\&quot;text\\&quot;: \\&quot;&quot; &lt;&lt; todo.getText() &lt;&lt; &quot;\\&quot; }&quot;;     return os; }  ostream& operator&lt;&lt;(ostream& os, CTodoList& todoList) {     map&lt;size_t, CTodo&gt; todos = todoList.readList();      os &lt;&lt; &quot;[&quot;;     if(!todos.empty())     {         if(todos.size() == 1)             os &lt;&lt; todos.begin()-&gt;second;         else             for ( map&lt;size_t, CTodo&gt;::iterator it = todos.begin();;)             {                 os &lt;&lt; it-&gt;second ;                 if(++it != todos.end())                     os &lt;&lt; ',';                 else                     break;             }      }     os &lt;&lt; &quot;]\\n&quot;;      return os; }  class CTodoHandler : public HTTPRequestHandler { public:     void handleRequest(HTTPServerRequest &req, HTTPServerResponse &resp)     {         URI uri(req.getURI());         string method = req.getMethod();          cerr &lt;&lt; &quot;URI: &quot; &lt;&lt; uri.toString() &lt;&lt; endl;         cerr &lt;&lt; &quot;Method: &quot; &lt;&lt; req.getMethod() &lt;&lt; endl;          StringTokenizer tokenizer(uri.getPath(), &quot;\/&quot;, StringTokenizer::TOK_TRIM);         HTMLForm form(req,req.stream());          if(!method.compare(&quot;POST&quot;))         {             cerr &lt;&lt; &quot;Create:&quot; &lt;&lt; form.get(&quot;text&quot;) &lt;&lt; endl;             CTodo todo(form.get(&quot;text&quot;));             TodoServerApp::createTodo(todo);         }         else if(!method.compare(&quot;PUT&quot;))         {             cerr &lt;&lt; &quot;Update id:&quot; &lt;&lt; *(--tokenizer.end()) &lt;&lt; endl;             cerr &lt;&lt; &quot;Update text:&quot; &lt;&lt; form.get(&quot;text&quot;) &lt;&lt; endl;             \/\/size_t id=stoull(*(--tokenizer.end()));             \/\/TodoServerApp::updateTodo(id, form.get(&quot;text&quot;));         }         else if(!method.compare(&quot;DELETE&quot;))         {             cerr &lt;&lt; &quot;Delete id:&quot; &lt;&lt; *(--tokenizer.end()) &lt;&lt; endl;             size_t id=stoull(*(--tokenizer.end()));             TodoServerApp::deleteTodo(id);         }          resp.setStatus(HTTPResponse::HTTP_OK);         resp.setContentType(&quot;application\/json&quot;);         ostream& out = resp.send();          cerr &lt;&lt; TodoServerApp::readTodoList() &lt;&lt; endl;         out &lt;&lt; TodoServerApp::readTodoList() &lt;&lt; endl;          out.flush();     } };  #include &lt;iostream&gt;     \/\/ std::cout #include &lt;fstream&gt;      \/\/ std::ifstream #include &lt;map&gt;          \/\/ std::ifstream  class CFileHandler : public HTTPRequestHandler {     typedef std::map&lt;const std::string, const std::string&gt; TStrStrMap;     TStrStrMap CONTENT_TYPE = { #include &quot;MimeTypes.h&quot;     };      string getPath(string& path){          if(path == &quot;\/&quot;){             path=&quot;\/index.html&quot;;         }          path.insert(0, &quot;.\/www&quot;);          return path;     }      string getContentType(string& path){          string contentType(&quot;text\/plain&quot;);         Poco::Path p(path);          TStrStrMap::const_iterator i=CONTENT_TYPE.find(p.getExtension());          if (i != CONTENT_TYPE.end())         { \/* Found, i-&gt;first is f, i-&gt;second is ++-- *\/            contentType = i-&gt;second;         }          if(contentType.find(&quot;text\/&quot;) != std::string::npos)         {             contentType+=&quot;; charset=utf-8&quot;;         }          cerr &lt;&lt; path &lt;&lt; &quot; : &quot; &lt;&lt; contentType &lt;&lt; endl;          return contentType;     }  public:      void handleRequest(HTTPServerRequest &req, HTTPServerResponse &resp)     {         cerr &lt;&lt; &quot;Get static page: &quot;;         \/\/system(&quot;echo -n '1. Current Directory is '; pwd&quot;);          URI uri(req.getURI());         string path(uri.getPath());          ifstream ifs (getPath(path).c_str(), ifstream::in);          if(ifs)         {             resp.setStatus(HTTPResponse::HTTP_OK);             resp.setContentType(getContentType(path));             ostream& out = resp.send();              char c = ifs.get();              while (ifs.good()) {                 out &lt;&lt; c;                 c = ifs.get();             }              out.flush();         }         else         {             resp.setStatus(HTTPResponse::HTTP_NOT_FOUND);             ostream& out = resp.send();              out &lt;&lt; &quot;File not found&quot; &lt;&lt; endl;              out.flush();         }          ifs.close();     } };  class TodoRequestHandlerFactory : public HTTPRequestHandlerFactory { public:     virtual HTTPRequestHandler* createRequestHandler(const HTTPServerRequest & request)     {         if (!request.getURI().find(&quot;\/api\/&quot;))             return new CTodoHandler;         else             return new CFileHandler;     } };  void TodoServerApp::createTodo(CTodo& todo) {     ScopedLock&lt;Mutex&gt; lock(todoLock);     todoList.create(todo); }  CTodoList& TodoServerApp::readTodoList() {     ScopedLock&lt;Mutex&gt; lock(todoLock);     return todoList; }  void TodoServerApp::deleteTodo(size_t id) {     ScopedLock&lt;Mutex&gt; lock(todoLock);     todoList.del(id); }  int TodoServerApp::main(const vector&lt;string&gt; &) {     HTTPServerParams* pParams = new HTTPServerParams;      pParams-&gt;setMaxQueued(100);     pParams-&gt;setMaxThreads(16);      HTTPServer s(new TodoRequestHandlerFactory, ServerSocket(8000), pParams);      s.start();     cerr &lt;&lt; &quot;Server started&quot; &lt;&lt; endl;      waitForTerminationRequest();  \/\/ wait for CTRL-C or kill      cerr &lt;&lt; &quot;Shutting down...&quot; &lt;&lt; endl;     s.stop();      return Application::EXIT_OK; } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u041d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e \u043e\u0442 \u0442\u0438\u043f\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0441\u0435\u0440\u0432\u0438\u0441 \u0432\u0441\u0435\u0433\u0434\u0430 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u0434\u0430\u0447 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 <a href=\"https:\/\/ru.wikipedia.org\/wiki\/JSON\">JSON<\/a>.<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">Response.json<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">[     {         &quot;_id&quot;: 1,         &quot;text&quot;: &quot;First&quot;      },     {         &quot;_id&quot;: 2,         &quot;text&quot;: &quot;Second&quot;     } ] <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0424\u0440\u043e\u043d\u0442\u0435\u043d\u0434 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0441\u044f \u0438\u0437 .\/www\/ \u0432 \u0434\u0438\u0440\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<br \/>  \u0414\u043b\u044f \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f <a href=\"https:\/\/angularjs.org\/\">AngularJs<\/a>. \u041a\u043e\u0434 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0432\u0437\u044f\u0442 \u0438\u0437 \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/scotch.io\/tutorials\/creating-a-single-page-todo-app-with-node-and-angular\">scotch.io\/tutorials\/creating-a-single-page-todo-app-with-node-and-angular<\/a><br \/>  \u0412\u0438\u0434 \u0432 index.html \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 \u0441\u043e \u0441\u0447\u0435\u0442\u0447\u0438\u043a\u043e\u043c \u0437\u0430\u0434\u0430\u043d\u0438\u0439, \u0441\u043f\u0438\u0441\u043a\u0430 \u0437\u0430\u0434\u0430\u043d\u0438\u0439 \u0438 \u0444\u043e\u0440\u043c\u044b \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u0437\u0430\u0434\u0430\u043d\u0438\u044f.<br \/>  \u041a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 js\/app.js \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 GET \u0434\u043b\u044f \u0441\u043f\u0438\u0441\u043a\u0430 \u043f\u0440\u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438. \u0414\u0430\u043b\u0435\u0435 \u2014 POST \u043f\u0440\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u043d\u043e\u0432\u043e\u0433\u043e \u0437\u0430\u0434\u0430\u043d\u0438\u044f \u0438\u0437 \u0444\u043e\u0440\u043c\u044b, \u043b\u0438\u0431\u043e DELETE \u043f\u0440\u0438 \u043a\u043b\u0438\u043a\u0435 \u043d\u0430 \u0447\u0435\u043a\u0431\u043e\u043a\u0441 \u0437\u0430\u0434\u0430\u043d\u0438\u044f.<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">index.html<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"html\">&lt;!-- index.html --&gt; &lt;!doctype html&gt;  &lt;!-- ASSIGN OUR ANGULAR MODULE --&gt; &lt;html ng-app=&quot;pocoTodo&quot;&gt; &lt;head&gt;     &lt;!-- META --&gt;     &lt;meta charset=&quot;utf-8&quot;&gt;     &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot;&gt;&lt;!-- Optimize mobile viewport --&gt;      &lt;title&gt;POCO\/Angular Todo App&lt;\/title&gt;      &lt;!-- SCROLLS --&gt;     &lt;link rel=&quot;stylesheet&quot; href=&quot;\/\/netdna.bootstrapcdn.com\/bootstrap\/3.0.0\/css\/bootstrap.min.css&quot;&gt;&lt;!-- load bootstrap --&gt;     &lt;style&gt;         html                    { overflow-y:scroll; }         body                    { padding-top:50px; }         #todo-list              { margin-bottom:30px; }     &lt;\/style&gt;      &lt;!-- SPELLS --&gt;     &lt;script src=&quot;\/\/ajax.googleapis.com\/ajax\/libs\/jquery\/2.0.3\/jquery.min.js&quot;&gt;&lt;\/script&gt;&lt;!-- load jquery --&gt;     &lt;script src=&quot;\/\/ajax.googleapis.com\/ajax\/libs\/angularjs\/1.0.8\/angular.min.js&quot;&gt;&lt;\/script&gt;&lt;!-- load angular --&gt;     &lt;script src=&quot;js\/app.js&quot;&gt;&lt;\/script&gt;  &lt;\/head&gt; &lt;!-- SET THE CONTROLLER AND GET ALL TODOS --&gt; &lt;body ng-controller=&quot;mainController&quot;&gt;     &lt;div class=&quot;container&quot;&gt;          &lt;!-- HEADER AND TODO COUNT --&gt;         &lt;div class=&quot;jumbotron text-center&quot;&gt;             &lt;h2&gt;POCO\/Angular Todo App &lt;span class=&quot;label label-info&quot;&gt;{{ todos.length }}&lt;\/span&gt;&lt;\/h2&gt;         &lt;\/div&gt;          &lt;!-- TODO LIST --&gt;         &lt;div id=&quot;todo-list&quot; class=&quot;row&quot;&gt;             &lt;div class=&quot;col-sm-4 col-sm-offset-4&quot;&gt;                  &lt;!-- LOOP OVER THE TODOS IN $scope.todos --&gt;                 &lt;div class=&quot;checkbox&quot; ng-repeat=&quot;todo in todos&quot;&gt;                     &lt;label&gt;                         &lt;input type=&quot;checkbox&quot; ng-click=&quot;deleteTodo(todo._id)&quot;&gt; {{ todo.text }}                     &lt;\/label&gt;                 &lt;\/div&gt;              &lt;\/div&gt;         &lt;\/div&gt;          &lt;!-- FORM TO CREATE TODOS --&gt;         &lt;div id=&quot;todo-form&quot; class=&quot;row&quot;&gt;             &lt;div class=&quot;col-sm-8 col-sm-offset-2 text-center&quot;&gt;                 &lt;form&gt;                     &lt;div class=&quot;form-group&quot;&gt;                          &lt;!-- BIND THIS VALUE TO formData.text IN ANGULAR --&gt;                         &lt;input type=&quot;text&quot; class=&quot;form-control input-lg text-center&quot; placeholder=&quot;I want to buy a puppy that will love me forever&quot; ng-model=&quot;formData.text&quot;&gt;                     &lt;\/div&gt;                      &lt;!-- createToDo() WILL CREATE NEW TODOS --&gt;                     &lt;button type=&quot;submit&quot; class=&quot;btn btn-primary btn-lg&quot; ng-click=&quot;createTodo()&quot;&gt;Add&lt;\/button&gt;                 &lt;\/form&gt;             &lt;\/div&gt;         &lt;\/div&gt;      &lt;\/div&gt;  &lt;\/body&gt; &lt;\/html&gt; <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">js\/app.js<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">\/\/ js\/app.js var pocoTodo = angular.module('pocoTodo', []);  function mainController($scope, $http) {     $scope.formData = {};     $http.defaults.headers.post[&quot;Content-Type&quot;] = &quot;application\/x-www-form-urlencoded&quot;;      \/\/ when landing on the page, get all todos and show them     $http.get('\/api\/todos')         .success(function(data) {             $scope.todos = data;             console.log(data);         })         .error(function(data) {             console.log('Error: ' + data);         });      \/\/ when submitting the add form, send the text to the node API     $scope.createTodo = function() {         $http.post('\/api\/todos', $.param($scope.formData)) \/\/ $scope.formData)             .success(function(data) {                 $scope.formData = {}; \/\/ clear the form so our user is ready to enter another                 $scope.todos = data;                 console.log(data);             })             .error(function(data) {                 console.log('Error: ' + data);             });     };      \/\/ delete a todo after checking it     $scope.deleteTodo = function(id) {         $http.delete('\/api\/todos\/' + id)             .success(function(data) {                 $scope.todos = data;                 console.log(data);             })             .error(function(data) {                 console.log('Error: ' + data);             });     };  } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0420\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u043f\u0440\u043e\u0435\u043a\u0442\u0430: <a href=\"https:\/\/github.com\/spot62\/PocoAngularTodo\">github.com\/spot62\/PocoAngularTodo<\/a>      \t<\/p>\n<div class=\"clear\"><\/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=\"http:\/\/habrahabr.ru\/post\/252519\/\"> http:\/\/habrahabr.ru\/post\/252519\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>     \t<a href=\"http:\/\/pocoproject.org\/\">POCO<\/a> \u2014 \u043a\u0440\u043e\u0441\u0441\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u0430\u044f open-source \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043d\u0430 \u0421++ \u043f\u043e\u0434 Boost Software License: <a href=\"http:\/\/ru.wikipedia.org\/wiki\/POCO\">ru.wikipedia.org\/wiki\/POCO<\/a>.<br \/>  <a href=\"http:\/\/pocoproject.org\/\">POCO<\/a> \u0438\u043c\u0435\u0435\u0442 \u0432 \u0441\u0432\u043e\u0435\u043c \u0441\u043e\u0441\u0442\u0430\u0432\u0435 \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0432\u0435\u0431-\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 c <a href=\"http:\/\/https:\/\/ru.wikipedia.org\/wiki\/REST\">RESTful API<\/a>.<br \/>  \u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0442\u0430\u043a\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 TODO.<br \/>  <img decoding=\"async\" src=\"\/\/habrastorage.org\/files\/118\/76b\/5fa\/11876b5fa78c4805b3d887b5f10cd0f2.png\"\/>  <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-252685","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/252685","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=252685"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/252685\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=252685"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=252685"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=252685"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}