web-dev-qa-db-ja.com

node.jsでのPOSTリクエストの処理方法

Node.jsサーバーに送信される送信リクエストを処理しようとしています。 server.jsという名前のJavaScriptファイルは、ブラウザーにフォームを表示します。 node.jsバックエンドに投稿された後、フォームの値にアクセスしたい。

フォームには、ユーザー名、リポジトリ、およびブランチが含まれます。フォームが送信されたら、このデータをユーザーに表示します。

Server.jsコード:

var http = require('http');

http.createServer(function (request, response) {
response.writeHead(200, {'Content-Type': 'text/html'});
response.end('<html><body>'
    + '<h1>XYZ Repository Commit Monitor</h1>'
    + '<form method="post" action="." enctype="application/x-www-form-urlencoded"><fieldset>'
    + '<div><label for="UserName">User Name:</label><input type="text" id="UserName" name="UserName" /></div>'
    + '<div><label for="Repository">Repository:</label><input type="text" id="Repository" name="Repository" /></div>'
    + '<div><label for="Branch">Branch:</label><input type="text" id="Branch" name="Branch" value="master" /></div>'
    + '<div><input id="ListCommits" type="submit" value="List Commits" /></div>'
    + '</fieldset></form>'
    + '</body></html>');
}).listen(8124);

console.log('Server running at http://127.0.0.1:8124/');
45
Sau

あなたが提供したコードを使用し、遠い未来の人々に対応するためにあなたの質問でカバーされているものよりも徹底的な答えを提供します。また、「Vanilla JS」( http://www.Vanilla-js.com/ )を使用する回答も提供します。これがどのように機能するかを学ぶために。彼らがそうする理由は、これがどのように機能するかを学んでいたときに誰かが「フレームワークを使う」ように言ったからだと思います。彼らはハッカーではないため、プロセスを試して理解しようとはしませんでした。そのため、多くの人はフレームワークなしで自分でこれを行う方法を理解していません。あなたは内部で何が起こっているかを理解することで、より良いハッカーになります。この点でこの答えがあなたの役に立つことを願っています。

出力しているフォームを介してPOST(フォーム)データを受け入れたいので、サーバーにルーティングメカニズムを提供する必要があります。これは、あなたのサイトを訪れる人々にフォームを提供するようにサーバーに指示することを意味しますが、ユーザーがフォームを送信すると、NodeはPOSTデータを小さな処理にルーティングします関数。コードから学びたい人に対応するために、最初に完全な回答を提供し、それからさらに詳しく分析しました。

var http = require('http');
var qs = require('querystring');
var formOutput = '<html><body>'
  + '<h1>XYZ Repository Commit Monitor</h1>'
  + '<form method="post" action="inbound" enctype="application/x-www-form-urlencoded"><fieldset>'
  + '<div><label for="UserName">User Name:</label><input type="text" id="UserName" name="UserName" /></div>'
  + '<div><label for="Repository">Repository:</label><input type="text" id="Repository" name="Repository" /></div>'
  + '<div><label for="Branch">Branch:</label><input type="text" id="Branch" name="Branch" value="master" /></div>'
  + '<div><input id="ListCommits" type="submit" value="List Commits" /></div></fieldset></form></body></html>';
var serverPort = 8124;
http.createServer(function (request, response) {
  if(request.method === "GET") {
    if (request.url === "/favicon.ico") {
      response.writeHead(404, {'Content-Type': 'text/html'});
      response.write('<!doctype html><html><head><title>404</title></head><body>404: Resource Not Found</body></html>');
      response.end();
    } else {
      response.writeHead(200, {'Content-Type': 'text/html'});
      response.end(formOutput);
    }
  } else if(request.method === "POST") {
    if (request.url === "/inbound") {
      var requestBody = '';
      request.on('data', function(data) {
        requestBody += data;
        if(requestBody.length > 1e7) {
          response.writeHead(413, 'Request Entity Too Large', {'Content-Type': 'text/html'});
          response.end('<!doctype html><html><head><title>413</title></head><body>413: Request Entity Too Large</body></html>');
        }
      });
      request.on('end', function() {
        var formData = qs.parse(requestBody);
        response.writeHead(200, {'Content-Type': 'text/html'});
        response.write('<!doctype html><html><head><title>response</title></head><body>');
        response.write('Thanks for the data!<br />User Name: '+formData.UserName);
        response.write('<br />Repository Name: '+formData.Repository);
        response.write('<br />Branch: '+formData.Branch);
        response.end('</body></html>');
      });
    } else {
      response.writeHead(404, 'Resource Not Found', {'Content-Type': 'text/html'});
      response.end('<!doctype html><html><head><title>404</title></head><body>404: Resource Not Found</body></html>');
    }
  } else {
    response.writeHead(405, 'Method Not Supported', {'Content-Type': 'text/html'});
    return response.end('<!doctype html><html><head><title>405</title></head><body>405: Method Not Supported</body></html>');
  }
}).listen(serverPort);
console.log('Server running at localhost:'+serverPort);

そして今、私がやったことをやった理由を説明する内訳について。

var http = require('http');
var qs = require('querystring');

最初に、実際のフォームデータを解析するためにNodeの組み込み 'querystring'モジュールを追加します。

var formOutput = '<html><body>'
  + '<h1>XYZ Repository Commit Monitor</h1>'
  + '<form method="post" action="/inbound" enctype="application/x-www-form-urlencoded"><fieldset>'
  + '<div><label for="UserName">User Name:</label><input type="text" id="UserName" name="UserName" /></div>'
  + '<div><label for="Repository">Repository:</label><input type="text" id="Repository" name="Repository" /></div>'
  + '<div><label for="Branch">Branch:</label><input type="text" id="Branch" name="Branch" value="master" /></div>'
  + '<div><input id="ListCommits" type="submit" value="List Commits" /></div></fieldset></form></body></html>';
var serverPort = 8124;

フォームの出力をサーバー/ルーティング/フォーム処理メカニズムの上に移動しました。ロジックが読みやすくなったためです。また、サーバーのリッスンポート情報をここに移動しました。これは、下にある多くの場所ではなく、1か所で変更するだけで済むためです。

http.createServer(function (request, response) {

(通常、この関数のパラメーターを「req」と「res」に短縮しますが、それは私の好みです。)

  if(request.method === "GET") {
    if (request.url === "/favicon.ico") {
      response.writeHead(404, {'Content-Type': 'text/html'});
      response.write(notFound);
      response.end();

ここに、簡単なルーティングの例を含めました。この場合、サーバーは「favicon.ico」のリクエストをリッスンしています。これは、すべての主要なブラウザーによるWebページのほぼすべての初期リクエストと一緒に行われたリクエストです。このファイルは、訪問している各Webページのタブに表示される小さなアイコンです。この目的のために、ファビコンを提供する必要はありませんが、基本的なルーティングの仕組みを示すために、ファビコンのインバウンドリクエストを処理します。

    } else {
      response.writeHead(200, {'Content-Type': 'text/html'});
      response.end(formOutput);
    }

訪問者がデフォルトのGETメソッド(上記で処理した "favicon.ico"を除く)を使用して、サーバー上の他のリソースにブラウザーを向けた場合、フォームを提供します。

  } else if(request.method === "POST") {

それ以外の場合、訪問者がサーバーでPOSTを指している場合、以前のGETリクエストで取得したフォームを送信した可能性が非常に高くなります。

    if (request.url === "/inbound") {

ここでは、「/ inbound」と呼ばれるインバウンドリクエストをリッスンしています。これは、上記の詳細を把握できれば、HTMLフォームの「アクション」です。ご存知のように、フォームの「アクション」は、ブラウザにフォームデータの送信先を指示します。

      var requestBody = '';
      request.on('data', function(data) {
        requestBody += data;
        if(requestBody.length > 1e7) {
          response.writeHead(413, 'Request Entity Too Large', {'Content-Type': 'text/html'});
          response.end('<!doctype html><html><head><title>413</title></head><body>413: Request Entity Too Large</body></html>');
        }
      });
      request.on('end', function() {
        var formData = qs.parse(requestBody);

これは少しわかりにくいかもしれませんが、そうではないと約束します。 POSTリクエストは、クライアントブラウザからマルチパートメッセージとして送信できます。フォーム内のいくつかの変数と同じくらい小さいものでは、おそらくこれは表示されませんが、処理するデータ量をスケーリングすると、これが表示されます。注意深く見ると、POSTデータの長さを尋ねるif()ステートメントも表示されます。悪意のある人は無限のファイルをアップロードすることでサーバーを殺すことができますが、私たちが行動を起こした場合はできません。これにより、POSTデータ本体が約10メガバイトに制限されますが、それに応じて調整する必要があります。これらのことを知ることで、将来の頭痛を防ぐことができます。頭痛がしたくありません。

        response.writeHead(200, {'Content-Type': 'text/html'});
        response.write('<!doctype html><html><head><title>response</title></head><body>');
        response.write('Thanks for the data!<br />User Name: '+formData.UserName);
        response.write('<br />Repository Name: '+formData.Repository);
        response.write('<br />Branch: '+formData.Branch);
        response.end('</body></html>');
      });

そして、ここでフォームデータを使用します。 Javascriptの性質上、これらの変数名は大文字と小文字が区別されます(「ユーザー名」ではなく「ユーザー名」など)。もちろん、このデータを使って何でもできます(Nodeのイベントループと非同期の性質に留意してください)。

    }
    response.writeHead(404, 'Resource Not Found', {'Content-Type': 'text/html'});
    return response.end('<!doctype html><html><head><title>404</title></head><body>413: Request Entity Too Large</body></html>');

ルーティングの例を続けるために、ここで行ったことは、すべてのPOSTリクエストに対する一般的な404 "Not Found"応答をクライアントに送信するif()ステートメントの下にキャッチオールが含まれています。まだ処理されていません。

  } else {
    response.writeHead(405, 'Method Not Supported', {'Content-Type': 'text/html'});
    return response.end('<!doctype html><html><head><title>405</title></head><body>405: Method Not Supported</body></html>');
  }
}).listen(serverPort);
console.log('Server running at localhost:'+serverPort);

そして、奇妙なメソッドでリクエストを処理するためのコードを少し含めて、コードを完成させました。対処していないことがいくつかあります(関数構造、空のフォームデータなど)が、実際には目標を達成するための多くの方法があります。私のCS教授の一人がかつて何年も前に言ったように、プログラムをプログラムする方法は非常に多く、宿題を共有することでだれが不正行為をしているのかを簡単に確認できます。

Expressなどの外部のサードパーティライブラリに依存するのではなく、組み込みモジュールを使用してNodeで何かを行うことは、難解なプロセスでも少し難しいプロセスでもないことを、あなた(および他の誰も)が理解できることを願っています。これらのライブラリーは世界でその場所を持っていますが、群れに従ってはいけません:結局のところ、コードについて十分な情報に基づいた決定を下してください(スタックオーバーフローの一部の人ではない)。

146
L0j1k