Learn node from 0 to 1 (2) to build an http server
In the previous pre-class study, we learned about the connections and differences between different module specifications. In this section, we officially start learning node. First, we start by building an http server that can run simple programs.
1. hello world
The most classic hello world
. First we create a server.js
to save our code:
console.log( 'hello world' );
Enter node server.js
in the terminal to run:
node server.js
The terminal will output the words hello world. But our node server program always needs to be accessed on the browser. Here we need to use the http
module that comes with node:
var http = require('http'); // 引入http模块// 创建http服务器// request : 从浏览器带来的请求信息// response : 从服务器返回给浏览器的信息http.createServer(function(request, response){ response.writeHead(200, {'content-type': 'text/plain'}); // 设置头部信息,输出text文本 response.write('hello world'); // 输出到页面中的信息 response.end(); // 返回结束}).listen(3000);console.log('server has started...');
We enter node server.js
in the terminal again to run. There will be output in the terminal server has started..., indicating that the server has been created and is running. Then we run on the browser Visit 127.0.0.1:3000
, and you can see hello world
output on the page.
2. form form
Just now we just output a simple text on the page, now we want to present a form on the page that allows users to enter information and submit:
// server.js var http = require('http'); http.createServer(function(request, response){ var html = '<html>\ <head>\ <meta charset=UTF-8" />\ </head>\ <body>\ <form action="/" method="post">\ <p>username : <input type="text" name="username" /></p>\ <p>password : <input type="password" name="password" /></p>\ <p>age : <input type="text" name="age" /></p>\ <p><input type="submit" value="submit" name="submit" /></p>\ </form>\ </body>\ </html>'; response.writeHead(200, {'content-type': 'text/html'}); // 输出html头信息 response.write(html); // 将拼接的html字符串输出到页面中 response.end(); // 结束 }).listen(3000); console.log('server has started...');
Modify the content in server.js and re-run:
node server.js
After refreshing the page, we found that 3 text boxes and 1 submit button. Because our program only renders the page and does not do any other processing, submitting data in the page just refreshes the current page.
Note: Every time we modify any code in node, we must restart it.
2.1 Get the data submitted by the form GET method
We use the POST method in the above code, but here we need to discuss the data submitted using the GET
method first. Let's not consider the security of the data first, but just learn how to obtain the form data submitted using the get method, change post to get, and run again.
We know that using the get method to submit data will pass the data as URL parameters, so we obtain the data by parsing the parameters in the URL. Here we use the url
module Method:
// server.js var http = require('http'), url = require('url'); http.createServer(function(request, response){ var html = '<html>\ <head>\ <meta charset=UTF-8" />\ </head>\ <body>\ <form action="/" method="get">\ <p>username : <input type="text" name="username" /></p>\ <p>password : <input type="password" name="password" /></p>\ <p>age : <input type="text" name="age" /></p>\ <p><input type="submit" value="submit" name="submit" /></p>\ </form>\ </body>\ </html>'; var query = url.parse( request.url, true ).query; if( query.submit ){ var data = '<p><a href="/">back</a></p>'+ '<p>username:'+query.username+'</p>'+ '<p>password:'+query.password+'</p>'+ '<p>age:'+query.age+'</p>'; response.writeHead(200, {'content-type': 'text/html'}); response.write(data); }else{ response.writeHead(200, {'content-type': 'text/html'}); response.write(html); } response.end(); // 结束 }).listen(3000); console.log('server has started...');
After we run the submission again, the data will be displayed on the page.
url.parse is used to parse URL strings and return the parsed URL object. If we only output url.parse(request.url):
url.parse(request.url); result: Url { protocol: null, slashes: null, auth: null, host: null, port: null, hostname: null, hash: null, search: '?username=111113&password=123&age=122&submit=submit', query: 'username=111113&password=123&age=122&submit=submit', pathname: '/', path: '/?username=111113&password=123&age=122&submit=submit', href: '/?username=111113&password=123&age=122&submit=submit' }
If the second parameter is set to true, the query attribute in the returned result will be parsed into an object, and other attributes will remain unchanged; The default value is false, that is, the query attribute is a string:
url.parse(request.url, true);result:Url { ... query: { username: '111113', password: '123', age: '122', submit: 'submit' }, ... }
Therefore, we can use the following statement to determine whether there is submitted data and obtain the submitted data, and then output it to:
var query = url.parse( request.url, true ).query; /* { username: '111113', password: '123', age: '122', submit: 'submit'} */
2.2 Get the data submitted by the form POST method
Now we use the post method to submit the data. Because POST requests are generally "heavy" (users may enter a large amount of content), if they are processed in a blocking manner, it will inevitably lead to blocking of user operations. Therefore, node splits the post data into many small data blocks, and then delivers these small data blocks through the data event (indicating that new small data blocks have arrived) and the end event (indicating that all data has been received). Therefore, our idea should be: obtain the data block in the data event and operate the data in the end event.
// server.js var http = require('http'), querystring = require('querystring'); http.createServer(function(request, response){ var html = '<html>\ <head>\ <meta charset=UTF-8" />\ </head>\ <body>\ <form action="/" method="post">\ <p>username : <input type="text" name="username" /></p>\ <p>password : <input type="password" name="password" /></p>\ <p>age : <input type="text" name="age" /></p>\ <p><input type="submit" value="submit" name="submit" /></p>\ </form>\ </body>\ </html>'; if( request.method.toLowerCase()=='post' ){ var postData = ''; request.addListener('data', function(chunk){ postData += chunk; }); request.addListener('end', function(){ var data = querystring.parse(postData); console.log( 'postData: '+postData ); console.log(data); var s = '<p><a href="/">back</a></p>'+ '<p>username:'+data.username+'</p>'+ '<p>password:'+data.password+'</p>'+ '<p>age:'+data.age+'</p>'; response.writeHead(200, {'content-type': 'text/html'}); response.write(s); response.end(); }) }else{ response.writeHead(200, {'content-type': 'text/html'}); response.write(html); response.end(); } }).listen(3000); console.log('server has started...');
The main changes between this code and the previous code project are:
No longer introduce the url module, use the import instead querystring module. Because we no longer operate the URL, there is no need to introduce it;
Use
request.method.toLowerCase()=='post'
to determine whether the current There is data submission;The data is spliced in the data event and processed in the end event;
response.end ()
is written inside theend
event. Because the end event is an asynchronous operation, it must be executed after the data output is completed.response.end()
We can see in the console that postData is a string like this:
'username=123&password=123&age=23&submit=submit';
因此我们使用query.parse
将postData解析为对象类型,以便获取提交过来的数据。
3. 路由
现在我们所有的逻辑都是在根目录下进行的,没有按照url区分,这里我们按照功能进行路由拆分。以上面的post请求为例,我们可以拆分为:页面初始化和form提交后的处理。
页面初始化:
// starter.js 页面初始化 function start(request, response){ var html = '<html>\ <head>\ <meta charset=UTF-8" />\ </head>\ <body>\ <form action="/show" method="post">\ <p>username : <input type="text" name="username" /></p>\ <p>password : <input type="password" name="password" /></p>\ <p>age : <input type="text" name="age" /></p>\ <p><input type="submit" value="submit" name="submit" /></p>\ </form>\ </body>\ </html>'; response.writeHead(200, {"Content-Type":"text/html"}); response.write( html ); response.end(); } exports.start = start;
展示获取的数据:
// uploader.js 展示获取的数据var querystring = require('querystring');function upload(request, response){ var postData = ''; request.addListener('data', function(chunk){ postData += chunk; }); request.addListener('end', function(){ var data = querystring.parse(postData); console.log( 'postData: '+postData ); console.log(data); var s = '<p><a href="/">back</a></p>'+ '<p>username:'+data.username+'</p>'+ '<p>password:'+data.password+'</p>'+ '<p>age:'+data.age+'</p>'; response.writeHead(200, {'content-type': 'text/html'}); response.write(s); response.end(); }) } exports.upload = upload;
然后在server.js中进行路由选择
// server.jsvar http = require('http'), url = require('url'); http.createServer(function(request, response){ var pathname = url.parse(request.url).pathname; console.log(pathname); response.end(); }).listen(3000);console.log('server has started...');
我们任意改变URL地址,会看到输出的每个地址的pathname(忽略/favicon.ico):
http://127.0.0.1:3000/ // 输出: / http://127.0.0.1:3000/show/ // 输出: /show/ http://127.0.0.1:3000/show/img/ // 输出: /show/img/ http://127.0.0.1:3000/show/?username=wenzi // 输出: /show/
因此我们就根据pathname进行路由,对路由进行方法映射:
// server.jsvar http = require('http'), url = require('url'), starter = require('./starter'), uploader = require('./uploader'); http.createServer(function(request, response){ var pathname = url.parse(request.url).pathname; var routeurl = { '/' : starter.start, '/show' : uploader.upload } if( typeof routeurl[pathname]=== 'function' ){ routeurl[pathname](request, response); }else{ console.log('404 not found!'); response.end(); } }).listen(3000);console.log('server has started...');
如果匹配到路由 /
,则执行 starter.start(request, response) ;如果匹配到路由 /show
,则执行 uploader.upload(request, response) 。如果都没匹配到,则显示404。
4. 图片上传并显示
在上面我们已经能成功提交数据了,这里来讲解如何进行图片上传并显示。使用node自带的模块处理起来非常的麻烦,这里我们使用别人已经开发好的formidable
模块进行编写,它对解析上传的文件数据做了很好的抽象。
npm install formidable --save-dev
在starter.js中,我们添加上file控件:
// starter.js function start(request, response){ var html = '<html>\ <head>\ <meta charset=UTF-8" />\ </head>\ <body>\ <form action="/upload" method="post" enctype="multipart/form-data">\ <p>file : <input type="file" name="upload" multiple="multiple" /></p>\ <p><input type="submit" value="submit" name="submit" /></p>\ </form>\ </body>\ </html>'; response.writeHead(200, {"Content-Type":"text/html"}); response.write( html ); response.end(); } exports.start = start;
4.1 图片上传
首先我们进行的是图片上传操作,首先我们要确保当前目录中存在tmp和img目录。在 uploader.js 中:
// uploader.jsvar formidable = require('formidable'), util = require('util'), fs = require('fs');function upload(request, response){ if( request.method.toLowerCase()=='post' ){ var form = new formidable.IncomingForm(); form.uploadDir = './tmp/'; form.parse(request, function(err, fields, files) { var oldname = files.upload.name, newname = Date.now() + oldname.substr(oldname.lastIndexOf('.')); fs.renameSync(files.upload.path, "./img/"+newname ); // 上传到 img 目录 response.writeHead(200, {'content-type': 'text/plain'}); response.write('received upload:\n\n'); response.end(util.inspect({fields: fields, files: files})); }); return; } } exports.upload = upload;
我们上传图片后跳转到upload路径,然后显示出相应的信息:
received upload: { fields: { // 其他控件,如input, textarea等 submit: 'submit'}, files:{ // file控件 upload:{ domain: null, _events: {}, _maxListeners: undefined, size: 5097, path: 'tmp\\upload_b1f7c3e83af224e9f3a020958cde5dcd', name: 'chrome.png', type: 'image/png', hash: null, lastModifiedDate: Thu Jan 12 2017 23:09:50 GMT+0800 (中国标准时间), _writeStream: [Object] } } }
我们再查看img目录时,就会发现我们刚才上传的照片了。
4.2 图片显示
将图片上传到服务器后,怎样才能把图片显示在浏览器上呢。这里我们就使用到了fs
模块来读取文件,创建一个shower.js
来专门展示图片:
// shower.jsvar fs = require('fs'), url = require('url');function show(request, response){ var query = url.parse(request.url, true).query, imgurl = query.src; // 读取图片并进行输出 // 这里读取链接中的src参数,指定读取哪张图片 /show?src=1484234660592.png fs.readFile('./img/'+imgurl, "binary", function(err, file){ if(err) throw err; response.writeHead(200, {"Content-Type": "image/png"}); response.write(file, "binary"); response.end(); }) } exports.show = show;
然后在 server.js 中添加上 show 的路由映射:
var routeurl = { '/' : starter.start, '/upload' : uploader.upload, '/show' : shower.show // 添加 };
最后在 upload.js 中进行图片的引用:
form.parse(request, function(err, fields, files) { var oldname = files.upload.name, newname = Date.now() + oldname.substr(oldname.lastIndexOf('.')); fs.renameSync(files.upload.path, "./img/"+newname ); // 同步上传图片 response.writeHead(200, {'content-type': 'text/html'}); var s = '<p><a href="/">back</a></p><p><img src="/show?src='+newname+'" /></p>'; // 显示刚才的图片 response.write(s); response.end(); });
5. 综合
刚才学习了上传数据和上传图片,这里我们将其综合一下,拟定一个题目:“设定用户名密码,并上传头像”。希望可以自己实现一下。
6. 接口的实现
在第2部分学习了GET和POST请求,那么在这里写一个简单json或jsonp接口应该不是什么难事儿了吧。
创建一个 inter.js :
// inter.jsvar url = require('url');function init(request, response){ if( request.method.toLowerCase()=='get' ){ var query = url.parse(request.url, true).query; var data = {"code":0, "msg":"success", "data":[{"username":"wenzi", "age":26}, {"username":"bing", "age":25}]}; if( query && query.callback ){ // jsonp response.end( query.callback + '(' + JSON.stringify(data) + ')' ); }else{ // json response.end( JSON.stringify(data) ); } } } exports.init = init;
在server中添加inter的引用和路由映射:
var routeurl = { '/' : starter.start, '/upload' : uploader.upload, '/show' : shower.show, '/inter' : inter.init // 添加};
然后对 http://127.0.0.1:3000/inter
进行json请求或jsonp请求即可。
7. 总结
这节还是写了不少的内容,最核心的就是讲解如何搭建一个简单的http服务器,进行数据和图片的提交与处理,在最后稍微讲了下接口的编写,后面有机会的话,会再具体讲解下接口的编写。

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics



Solution: 1. Check the eMule settings to make sure you have entered the correct server address and port number; 2. Check the network connection, make sure the computer is connected to the Internet, and reset the router; 3. Check whether the server is online. If your settings are If there is no problem with the network connection, you need to check whether the server is online; 4. Update the eMule version, visit the eMule official website, and download the latest version of the eMule software; 5. Seek help.

What should I do if the RPC server is unavailable and cannot be accessed on the desktop? In recent years, computers and the Internet have penetrated into every corner of our lives. As a technology for centralized computing and resource sharing, Remote Procedure Call (RPC) plays a vital role in network communication. However, sometimes we may encounter a situation where the RPC server is unavailable, resulting in the inability to enter the desktop. This article will describe some of the possible causes of this problem and provide solutions. First, we need to understand why the RPC server is unavailable. RPC server is a

As a LINUX user, we often need to install various software and servers on CentOS. This article will introduce in detail how to install fuse and set up a server on CentOS to help you complete the related operations smoothly. CentOS installation fuseFuse is a user space file system framework that allows unprivileged users to access and operate the file system through a customized file system. Installing fuse on CentOS is very simple, just follow the following steps: 1. Open the terminal and Log in as root user. 2. Use the following command to install the fuse package: ```yuminstallfuse3. Confirm the prompts during the installation process and enter `y` to continue. 4. Installation completed

The role of a DHCP relay is to forward received DHCP packets to another DHCP server on the network, even if the two servers are on different subnets. By using a DHCP relay, you can deploy a centralized DHCP server in the network center and use it to dynamically assign IP addresses to all network subnets/VLANs. Dnsmasq is a commonly used DNS and DHCP protocol server that can be configured as a DHCP relay server to help manage dynamic host configurations in the network. In this article, we will show you how to configure dnsmasq as a DHCP relay server. Content Topics: Network Topology Configuring Static IP Addresses on a DHCP Relay D on a Centralized DHCP Server

In network data transmission, IP proxy servers play an important role, helping users hide their real IP addresses, protect privacy, and improve access speeds. In this article, we will introduce the best practice guide on how to build an IP proxy server with PHP and provide specific code examples. What is an IP proxy server? An IP proxy server is an intermediate server located between the user and the target server. It acts as a transfer station between the user and the target server, forwarding the user's requests and responses. By using an IP proxy server

The steps to start the TFTP server include selecting the TFTP server software, downloading and installing the software, configuring the TFTP server, and starting and testing the server. Detailed introduction: 1. When choosing TFTP server software, you first need to choose the TFTP server software that suits your needs. Currently, there are many TFTP server software to choose from, such as Tftpd32, PumpKIN, tftp-hpa, etc., which all provide simple and easy-to-use functions. interface and configuration options; 2. Download and install TFTP server software, etc.

What should I do if I can’t enter the game when the epic server is offline? This problem must have been encountered by many friends. When this prompt appears, the genuine game cannot be started. This problem is usually caused by interference from the network and security software. So how should it be solved? The editor of this issue will explain I would like to share the solution with you, I hope today’s software tutorial can help you solve the problem. What to do if the epic server cannot enter the game when it is offline: 1. It may be interfered by security software. Close the game platform and security software and then restart. 2. The second is that the network fluctuates too much. Try restarting the router to see if it works. If the conditions are OK, you can try to use the 5g mobile network to operate. 3. Then there may be more

Detailed explanation and installation guide for PiNetwork nodes This article will introduce the PiNetwork ecosystem in detail - Pi nodes, a key role in the PiNetwork ecosystem, and provide complete steps for installation and configuration. After the launch of the PiNetwork blockchain test network, Pi nodes have become an important part of many pioneers actively participating in the testing, preparing for the upcoming main network release. If you don’t know PiNetwork yet, please refer to what is Picoin? What is the price for listing? Pi usage, mining and security analysis. What is PiNetwork? The PiNetwork project started in 2019 and owns its exclusive cryptocurrency Pi Coin. The project aims to create a one that everyone can participate
