8000 nodebeginner.org/index-ru.html at master · CaioCAP/nodebeginner.org · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Latest commit

 

History

History
2838 lines (2610 loc) · 239 KB

index-ru.html

File metadata and controls

2838 lines (2610 loc) · 239 KB
class="pln"> start</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span
class="pln"><br>&nbsp; </span><span class="kwd">function</span><span class="pln"> onRequest</span><span
class="pun">(</span><span class="pln">request</span><span class="pun">,</span><span class="pln"> response</span><span
class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp; console</span><span
class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Request received."</span><span
class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
class="pln">writeHead</span><span class="pun">(</span><span class="lit">200</span><span
class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span
class="str">"Content-Type"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"text/plain"</span><span
class="pun">});</span><span class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
class="pln">write</span><span class="pun">(</span><span class="str">"Hello World"</span><span
class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
class="pln">end</span><span class="pun">();</span><span class="pln"><br>&nbsp; </span><span class="pun">}</span><span
class="pln"><br><br>&nbsp; http</span><span class="pun">.</span><span
class="pln">createServer</span><span class="pun">(</span><span class="pln">onRequest</span><span
class="pun">).</span><span class="pln">listen</span><span class="pun">(</span><span
class="lit">8888</span><span class="pun">);</span><span class="pln"><br>&nbsp; console</span><span
class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Server has started."</span><span
class="pun">);</span><span class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br>exports</span><span
class="pun">.</span><span class="pln">start </span><span class="pun">=</span><span
class="pln"> start</span><span class="pun">;</span></pre>
<p>
Теперь мы можем создать наш основной файл <em>index.js</em>, и запускать наш HTTP-сервер там, хотя код для сервера находится всё ещё в файле <em>server.js</em>.
</p>
<p>
Создаём файл <em>index.js</em> со следующим содержимым:
</p>
<pre class="prettyprint lang-js"><span class="kwd">var</span><span class="pln"> server </span><span class="pun">=</span><span
class="pln"> require</span><span class="pun">(</span><span class="str">"./server"</span><span
class="pun">);</span><span class="pln"><br><br>server</span><span class="pun">.</span><span class="pln">start</span><span
class="pun">();</span></pre>
<p>
Как вы могли видеть, мы можем использовать модуль сервера просто как внешний модуль: вызвав этот файл и определив для него переменную, экспортированные функции становятся доступны нам.
</p>
<p>
Вот и всё. Сейчас мы можем запустить наше приложение через главный скрипт и он будет делать всё то же самое, что и раньше:
</p>
<pre>node index.js</pre>
<p>
Великолепно &mdash; сейчас мы можем помещать различные части нашего приложения в разные файлы и связывать их вместе, посредством превращения их в модули.
</p>
<p>
До сих пор мы работали только с первой частью нашего приложения: получение HTTP-запроса.
Но нам надо что-нибудь с ним делать.
В зависимости от URL, запрошенного браузером у нашего сервера, мы должны реагировать по-разному.
</p>
<p>
В очень простом приложении мы могли бы делать это напрямую внутри callback-функции <em>onRequest()</em>.
Но, как я говорил, давайте добавим немного больше абстракции, чтобы сделать наш пример интереснее.
</p>
<p>
Задание соответствия между разными HTTP-запросами и разными частями нашего кода называется «маршрутизация» («routing», роутинг).
Давайте тогда создадим модуль под названием <em>router</em>.
</p>
<a name="whats-needed-to-route-requests"></a>
<h3>Что необходимо для «роутера»?</h3>
<p>
Нам нужно иметь возможность "скармливать" запрошенный URL и возможные добавочные GET/POST-параметры нашему роутеру и, с учётом этого, роутер должен определять, какой код выполнять (этот код есть третья составляющая нашего приложения: коллекция обработчиков запросов, делающие необходимую работу по определённому запросу).
</p>
<p>
Итак, нам надо рассматривать HTTP-запрос и извлекать запрошенный URL, а также GET/POST-параметры.
Можно поспорить, должен ли этот код быть частью роутера или сервера (или даже своего собственного модуля), но давайте сейчас пока просто сделаем его частью сервера.
</p>
<p>
Вся необходимая нам информация доступна через объект <em>request</em>, который передается в качестве первого параметра нашей callback-функции <em>onRequest()</em>.
Чтобы интерпретировать эту информацию, нам необходимо добавить кое-какие Node.js-модули, а именно <em>url</em> и <em>querystring</em>.
</p>
<p>
Модуль <em>url</em> поддерживает методы, которые позволяют нам извлекать различные части URL (такие как запрошенный путь (URL path) и строка параметров запроса (query string)), а <em>querystring</em> в свою очередь, используется для парсинга строки параметров запроса (query string):
</p>
<pre> url.parse(string).query
|
url.parse(string).pathname |
| |
| |
------ -----------------------
http://localhost:8888/start?foo=bar&amp;hello=world
--- -----
| |
| |
querystring(string)["foo"] |
|
querystring(string)["hello"]</pre>
<p>
Конечно, мы также можем использовать <em>querystring</em> для парсинга тела POST-запроса, как мы увидим далее.
</p>
<p>
Давайте сейчас добавим в нашу функцию <em>onRequest()</em> логику, необходимую для извлечения пути URL (pathname), запрошенного браузером:
</p>
<pre class="prettyprint lang-js"><span class="kwd">var</span><span class="pln"> http </span><span
class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span
class="str">"http"</span><span class="pun">);</span><span class="pln"><br></span><span
class="kwd">var</span><span class="pln"> url </span><span class="pun">=</span><span
class="pln"> require</span><span class="pun">(</span><span class="str">"url"</span><span
class="pun">);</span><span class="pln"><br><br></span><span class="kwd">function</span><span
class="pln"> start</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span
class="pln"><br>&nbsp; </span><span class="kwd">function</span><span class="pln"> onRequest</span><span
class="pun">(</span><span class="pln">request</span><span class="pun">,</span><span class="pln"> response</span><span
class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp; </span><span
class="kwd">var</span><span class="pln"> pathname </span><span class="pun">=</span><span class="pln"> url</span><span
class="pun">.</span><span class="pln">parse</span><span class="pun">(</span><span
class="pln">request</span><span class="pun">.</span><span class="pln">url</span><span
class="pun">).</span><span class="pln">pathname</span><span class="pun">;</span><span class="pln"><br>&nbsp; &nbsp; console</span><span
class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Request for "</span><span
class="pln"> </span><span class="pun">+</span><span class="pln"> pathname </span><span
class="pun">+</span><span class="pln"> </span><span class="str">" received."</span><span
class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
class="pln">writeHead</span><span class="pun">(</span><span class="lit">200</span><span
class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span
class="str">"Content-Type"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"text/plain"</span><span
class="pun">});</span><span class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
class="pln">write</span><span class="pun">(</span><span class="str">"Hello World"</span><span
class="pun">);</span><span class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
class="pln">end</span><span class="pun">();</span><span class="pln"><br>&nbsp; </span><span class="pun">}</span><span
class="pln"><br><br>&nbsp; http</span><span class="pun">.</span><span
class="pln">createServer</span><span class="pun">(</span><span class="pln">onRequest</span><span
class="pun">).</span><span class="pln">listen</span><span class="pun">(</span><span
class="lit">8888</span><span class="pun">);</span><span class="pln"><br>&nbsp; console</span><span
class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Server has started."</span><span
class="pun">);</span><span class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br>exports</span><span
class="pun">.</span><span class="pln">start </span><span class="pun">=</span><span
class="pln"> start</span><span class="pun">;</span></pre>
<p>
Замечательно.
Теперь наше приложение может различать запросы на основе запрошенного пути URL.
Это позволяет нам направлять запросы нашим обработчикам запросов в зависимости от пути URL, используя наш роутер.
Таким образом, мы можем строить наше приложение RESTful-путём, потому что теперь можем реализовать интерфейс, следующий принципам <em>Идентификации ресурсов</em> (смотри статью в википедии <a href="http://ru.wikipedia.org/wiki/REST">REST</a> для справки).
</p>
<p>
В контексте нашего приложения, это означает, что мы сможем обрабатывать запросы с URL <em>/start</em> и <em>/upload</em> разными частями нашего кода.
Скоро мы увидим, как всё соединяется вместе.
</p>
<p>
Теперь самое время написать наш роутер.
Создаём новый файл под названием <em>router.js</em> со следующим содержимым:
</p>
<pre class="prettyprint lang-js"><span class="kwd">function</span><span class="pln"> route</span><span
class="pun">(</span><span class="pln">pathname</span><span class="pun">)</span><span
class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; console</span><span
class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"About to route a request for "</span><span
class="pln"> </span><span class="pun">+</span><span class="pln"> pathname</span><span
class="pun">);</span><span class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br>exports</span><span
class="pun">.</span><span class="pln">route </span><span class="pun">=</span><span
class="pln"> route</span><span class="pun">;</span></pre>
<p>
Конечно этот код ничего не делает, но сейчас этого достаточно.
Давайте сначала посмотрим, как скрепить этот роутер с нашим сервером до того как поместим больше логики в роутер.
</p>
<p>
Нашему HTTP-серверу необходимо знать о роутере и использовать его.
Мы могли бы жёстко прописать эти зависимости в нашем сервере, но, так как мы знаем только сложные способы из нашего опыта в других языках программирования, мы сделаем слабосвязанную зависимость сервера и роутера через внедрение этих зависимостей (можете почитать <a href="http://martinfowler.com/articles/injection.html">отличный пост Мартина Фаулера по внедрениям зависимости на английском языке</a> или <a href="http://ru.wikipedia.org/wiki/%D0%92%D0%BD%D0%B5%D0%B4%D1%80%D0%B5%D0%BD%D0%B8%D0%B5_%D0%B7%D0%B0%D0%B2%D0%B8%D1%81%D0%B8%D0%BC%D0%BE%D1%81%D1%82%D0%B8">статью в Википедии на русском языке</a> для дополнительной информации).
</p>
<p>
Для начала, расширим нашу серверную функцию <em>start()</em>, чтобы дать нам возможность передавать функцию <em>route()</em> как параметр:
</p>
<pre class="prettyprint lang-js"><span class="kwd">var</span><span class="pln"> http </span><span
class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span
class="str">"http"</span><span class="pun">);</span><span class="pln"><br></span><span
class="kwd">var</span><span class="pln"> url </span><span class="pun">=</span><span
class="pln"> require</span><span class="pun">(</span><span class="str">"url"</span><span
class="pun">);</span><span class="pln"><br><br></span><span class="kwd">function</span><span
class="pln"> start</span><span class="pun">(</span><span class="pln">route</span><span
class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span
class="pln"><br>&nbsp; </span><span class="kwd">function</span><span class="pln"> onRequest</span><span
class="pun">(</span><span class="pln">request</span><span class="pun">,</span><span class="pln"> response</span><span
class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br>&nbsp; &nbsp; </span><span
class="kwd">var</span><span class="pln"> pathname </span><span class="pun">=</span><span class="pln"> url</span><span
class="pun">.</span><span class="pln">parse</span><span class="pun">(</span><span
class="pln">request</span><span class="pun">.</span><span class="pln">url</span><span
class="pun">).</span><span class="pln">pathname</span><span class="pun">;</span><span class="pln"><br>&nbsp; &nbsp; console</span><span
class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="str">"Request for "</span><span
class="pln"> </span><span cl 3976 ass="pun">+</span><span class="pln"> pathname </span><span
class="pun">+</span><span class="pln"> </span><span class="str">" received."</span><span
class="pun">);</span><span class="pln"><br><br>&nbsp; &nbsp; route</span><span class="pun">(</span><span
class="pln">pathname</span><span class="pun">);</span><span
class="pln"><br><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
class="pln">writeHead</span><span class="pun">(</span><span class="lit">200</span><span
class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span
class="str">"Content-Type"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"text/plain"</span><span
class="pun">});</span><span class="pln"><br>&nbsp; &nbsp; response</span><span class="pun">.</span><span
0