如何在node.js中处理POST请求 [英] How to handle POST request in node.js

查看:101
本文介绍了如何在node.js中处理POST请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试处理发送到node.js服务器的帖子请求。
名称为server.js的JavaScript文件在浏览器上显示一个表单。我希望在将表单值发布到node.js后端后访问它们。

I'm trying to handle a post request being sent to my node.js server. JavaScript file with a name server.js displays a form on the browser. I want access to the form values after they are posted to the node.js backend.

表单包含用户名,存储库和分支。提交表单时,我想将此数据显示回用户。

The form contains a username, repository, and branch. When the form is submitted I want to display back this data back to the user.

server.js代码:

The server.js code:

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/');


推荐答案

我将使用您提供的代码,并提供一个比你的问题所涵盖的更彻底的答案,以容纳遥远未来的人。我还将提供一个使用Vanilla JS的答案( http://www.vanilla-js.com/ )因为当你试图了解它是如何工作的时候,我想太多的时髦人士会说使用框架。我认为他们这样做的原因是因为有人告诉他们在学习如何运作时使用框架。因为他们不是黑客,他们并不关心尝试和理解这个过程,所以他们中的许多人通常不了解如何在没有框架的情况下自己做这件事(因此无处不在的使用框架)。通过了解幕后发生的事情你将成为一个更好的黑客,我希望这个答案可以帮助你。

I'm going to use the code you provided, and provide an answer more thorough than what's covered in your question to accommodate people in The Distant Future. I will also provide an answer that uses "Vanilla JS" (http://www.vanilla-js.com/) because I think too many hipsters say "use a framework" when you're trying to learn how this works. I think the reason they do that is because someone told them to "use a framework" when they were learning how this works. Because they aren't hackers, they didn't care to try and understand the process, so very often many of them do not understand how to do this on their own, without a framework (hence the ubiquitous "use a framework"). You will become a better hacker by understanding what's going on under the hood and I hope this answer helps you in that regard.

现在你想要接受POST(通过您输出的表单生成数据,有必要在服务器中提供路由机制。这意味着您将告诉您的服务器将表单提供给访问您网站的人,但如果用户提交表单,Node会将POST数据路由到一个小的处理函数。我首先提供了完整的答案,然后进一步解剖,以便让想要从代码中学习的人接受。

Now that you're wanting to accept POST (form) data via the form you're outputting, it's necessary to provide a routing mechanism in your server. This means that you'll tell your server to give the form to people visiting your site, but then if the user submits a form, Node will route the POST data to a little processing function. I've provided the complete answer first and then dissected it further down, to accommodate people wanting to learn from the code.

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);

现在解释为什么我做了我做过的事情。

And now for the breakdown explaining why I have done the things I did.

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

首先,你要添加Node的内置'querystring'模块来解析实际的表格数据。

First, you're going to add Node's built-in 'querystring' module to parse the actual form data.

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;

我已将表单输出移到我们的服务器/路由/表单处理机制之上,因为然后逻辑更容易阅读。我还在这里移动了服务器侦听端口信息,因为您只需要在一个地方而不是下面的地方更改它。

I've moved the form output up above our server/routing/form-handling mechanism, because the logic is then much easier to read. I also moved the server listening port information up here, because you then only have to change it in one place instead of many below.

http.createServer(function (request, response) {

(我通常会缩短此函数的参数req和res,但这只是我的偏好。)

(I usually shorten the parameters of this function to "req" and "res", but that's just my preference.)

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

这里我我们已经包含了一个简单的路由示例。在这种情况下,我们让我们的服务器监听favicon.ico的请求 - 这是与所有主流浏览器几乎所有初始网页请求一起提出的请求。这个文件是您可以在您访问的每个网页的标签中看到的小图标。出于我们的目的,我们不需要提供图标,我们将处理它的入站请求以显示一些基本的路由机制。

Here I've included a simple routing example. In this case, we're having our server listen for requests for "favicon.ico" -- a request made alongside almost all initial requests for a webpage by all the major browsers. This file is the little icon you can see up in the tabs of each webpage you're visiting. For our purposes, we don't need to serve a favicon, but we will handle inbound requests for it to show some basic routing mechanics.

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

如果访问者将浏览器指向服务器上的任何其他资源,则使用默认值GET方法(除了我们上面刚刚处理过的favicon.ico),我们将为它们提供表格。

If your visitors point their browser to ANY other resource on your server with the default GET method (besides the "favicon.ico" we just handled above), we will serve them the form.

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

否则,如果访问者指向POST在您的服务器上,他们很可能已经提交了他们使用之前的GET请求检索到的表单。

Otherwise, if your visitors are pointing a POST at your server, it's very likely they have submitted the form they retrieved with the previous GET request.

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

这里我们正在侦听名为/ inbound的入站请求 - 如果你发现上面的小细节 - 是我们的HTML表单的动作。您可能知道,表单的操作告诉浏览器将表单数据发送到何处。

Here we are listening for inbound requests called "/inbound" which -- if you caught the little detail above -- is the "action" of our HTML form. As you may know, the "action" of the form tells the browser where to send the form data.

      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请求可以作为多部分消息从客户端浏览器发送。只需要表单中的一些变量,就可以了我不太可能看到这一点,但随着你扩展你处理的数据量,你会看到这一点。如果你观察,你也会看到 if()询问POST数据长度的声明。恶意的人可以通过上传无限文件来杀死你的服务器,但是如果我们采取行动则不会。这会将POST数据体限制为大约10兆字节,但你应该相应调整。关于这些事情可以防止将来头痛,我不希望你头疼。

This might look a little confusing, but I promise it's not. POST requests can be sent as multi-part messages from the client browser. With something as small as a few variables in a form, you won't likely ever see this, but as you scale the amount of data you handle, you will see this. If you're observant, you'll also see the if() statement asking about the length of the POST data. A malicious person can kill your server by uploading an endless file, but not if we take action. This limits the POST data body to about ten megabytes, but you should adjust accordingly. Knowing about these things prevents a future headache, and I don't want you to have a headache.

        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的性质,这些变量名称是CASE SENSITIVE(例如UserName而不是username)。当然,您可以使用此数据执行任何操作(请记住Node的事件循环和异步特性)。

And here is where we use the form data. Because of the nature of Javascript, these variable names are CASE SENSITIVE (such as "UserName" instead of "username"). Of course, you can do anything you want with this data (keeping in mind Node's event loop and asynchronous nature).

    }
    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>');

要继续我们的路由示例,我们在这里所做的工作包括了 if()语句,它向客户端发送一个通用的404未找到回复我们尚未处理的任何POST请求。

To continue our routing example, what we've done here is included a catch-all underneath the if() statement which sends the client a generic 404 "Not Found" reply to any POST request we haven't already handled.

  } 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教授之一,有很多方法可以编写程序,通过分享作业很容易看出谁在作弊。

And now we've just finished the code off, including a little bit of code to handle requests with strange methods. There are a few things I haven't addressed (function structure, empty form data, etc.), but there are indeed many ways to accomplish your goals. As one of my CS professors once said many years ago, there are so many ways to program a program that it's easy to see who's cheating by sharing their homework.

我希望您(以及其他任何人)可以看到使用其内置模块在Node中执行操作而不依赖于Express等外部第三方库,这不是一些深奥甚至稍微困难的过程。这些图书馆在世界上占有一席之地,但不要跟随牧群:对你的代码做出明智的决定,因为在一天结束时,你是负责它的人(不是Stack Overflow上的某些人)。

I hope that you (and anyone else) can see that it's not some esoteric or even slightly difficult process to do things in Node using its built-in modules instead of relying on external third-party libraries such as Express. Those libraries have their place in the world, but don't follow the herd: Make an informed decision about your code, because at the end of the day, you're the one responsible for it (not some people on Stack Overflow).

这篇关于如何在node.js中处理POST请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆