Maison > Article > interface Web > Apprenez le nœud de 0 à 1 (2) pour créer un serveur http
Lors de l'étude préalable précédente, nous avons découvert les connexions et les différences entre les différentes spécifications de modules. Dans cette section, nous commençons officiellement l'apprentissage du nœud. Tout d'abord, nous commençons par créer un serveur http capable d'exécuter des programmes simples.
Le plus classique hello world
. Nous créons d'abord un server.js
pour enregistrer notre code :
console.log( 'hello world' );
Entrez node server.js
dans le terminal pour exécuter :
node server.js
Le terminal affichera les mots bonjour tout le monde. Mais notre programme de serveur de nœud doit toujours être accessible sur le navigateur. Ici, nous devons utiliser le module http
fourni avec le nœud :
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...');
Nous entrons node server.js
dans le terminal pour exécuter. Les mots le serveur a démarré... seront affichés dans le terminal, indiquant que le serveur a été créé et est en cours d'exécution. Ensuite, nous visitons 127.0.0.1:3000
sur le navigateur et vous pouvez. voir hello world
est affiché sur la page.
Tout à l'heure, nous venons d'afficher un simple texte sur la page, maintenant nous voulons présenter un formulaire sur la page qui permet aux utilisateurs de saisir des informations et de les soumettre :
// 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...');
Modifiez le contenu dans server.js et réexécutez :
node server.js
Après avoir actualisé la page, nous avons constaté que 3 était affiché sur les zones de texte de la page et un bouton de soumission. Étant donné que notre programme affiche uniquement la page et n'effectue aucun autre traitement, la soumission de données dans la page actualise simplement la page actuelle.
Remarque : Chaque fois que nous modifions un code dans le nœud, nous devons le redémarrer.
Nous utilisons la méthode POST dans le code ci-dessus, mais ici nous discuterons d'abord des données soumises à l'aide de la méthode GET
, nous allons ne le considérez pas en premier. La sécurité des données consiste simplement à apprendre à obtenir les données du formulaire soumises à l'aide de la méthode get, à modifier la publication pour obtenir et à l'exécuter à nouveau.
Nous savons que l'utilisation de la méthode get pour soumettre des données transmettra les données en tant que paramètres d'URL, nous obtenons donc les données en analysant les paramètres dans l'URL. La méthode du module url
est utilisée ici : <.>
// 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...');
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' }Si le deuxième paramètre est défini sur true, l'attribut de requête dans le résultat renvoyé sera analysé dans un objet et les autres attributs ne le seront pas. Change ; la valeur par défaut est false, c'est-à-dire que l'attribut de requête est une chaîne :
url.parse(request.url, true);result:Url {
...
query: {
username: '111113',
password: '123',
age: '122',
submit: 'submit' },
...
}
var query = url.parse( request.url, true ).query;
/*
{
username: '111113',
password: '123',
age: '122',
submit: 'submit'}
*/
// 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...');
pour déterminer si des données sont actuellement soumises ; request.method.toLowerCase()=='post'
Les données sont épissées dans l'événement data et traitées dans l'événement end
response.end()
end
response.end()
On peut voir dans la console que postData est une chaîne comme celle-ci :
因此我们使用query.parse
将postData解析为对象类型,以便获取提交过来的数据。
现在我们所有的逻辑都是在根目录下进行的,没有按照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。
在上面我们已经能成功提交数据了,这里来讲解如何进行图片上传并显示。使用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;
首先我们进行的是图片上传操作,首先我们要确保当前目录中存在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目录时,就会发现我们刚才上传的照片了。
将图片上传到服务器后,怎样才能把图片显示在浏览器上呢。这里我们就使用到了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();
});
刚才学习了上传数据和上传图片,这里我们将其综合一下,拟定一个题目:“设定用户名密码,并上传头像”。希望可以自己实现一下。
在第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请求即可。
这节还是写了不少的内容,最核心的就是讲解如何搭建一个简单的http服务器,进行数据和图片的提交与处理,在最后稍微讲了下接口的编写,后面有机会的话,会再具体讲解下接口的编写。