Maison  >  Article  >  interface Web  >  Apprenez le nœud de 0 à 1 (2) pour créer un serveur http

Apprenez le nœud de 0 à 1 (2) pour créer un serveur http

大家讲道理
大家讲道理original
2017-01-24 15:40:401164parcourir

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.

1. Bonjour tout le monde

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.

2. formulaire

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 = &#39;<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>&#39;;

    response.writeHead(200, {&#39;content-type&#39;: &#39;text/html&#39;}); // 输出html头信息
    response.write(html); // 将拼接的html字符串输出到页面中
    response.end(); // 结束
}).listen(3000);
console.log(&#39;server has started...&#39;);

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.

2.1 Récupérer les données soumises par la méthode GET du formulaire

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(&#39;http&#39;),
url = require(&#39;url&#39;);

http.createServer(function(request, response){
    var html = &#39;<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>&#39;;
    
    var query = url.parse( request.url, true ).query;
    if( query.submit ){
        var data = &#39;<p><a href="/">back</a></p>&#39;+
            &#39;<p>username:&#39;+query.username+&#39;</p>&#39;+
            &#39;<p>password:&#39;+query.password+&#39;</p>&#39;+
            &#39;<p>age:&#39;+query.age+&#39;</p>&#39;;
         
        response.writeHead(200, {&#39;content-type&#39;: &#39;text/html&#39;});
        response.write(data);
    }else{
        response.writeHead(200, {&#39;content-type&#39;: &#39;text/html&#39;});
        response.write(html);
    }
    response.end(); // 结束
}).listen(3000);
console.log(&#39;server has started...&#39;);
Après avoir réexécuté la soumission, les données seront affichées sur la page.

url.parse est utilisé pour analyser les chaînes d'URL et renvoyer l'objet URL analysé. Si nous produisons uniquement 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: &#39;?username=111113&password=123&age=122&submit=submit&#39;,    
      query: &#39;username=111113&password=123&age=122&submit=submit&#39;,   
       pathname: &#39;/&#39;,    
       path: &#39;/?username=111113&password=123&age=122&submit=submit&#39;,    
       href: &#39;/?username=111113&password=123&age=122&submit=submit&#39;
       }
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: &#39;111113&#39;,
    password: &#39;123&#39;,
    age: &#39;122&#39;,
    submit: &#39;submit&#39; },
...
}
Par conséquent, nous pouvons utiliser l'instruction suivante pour déterminer s'il y a des données soumises et obtenir les données soumises, puis envoyez-les vers Cliquez simplement dessus :

var query = url.parse( request.url, true ).query;
/*
{
    username: &#39;111113&#39;,
    password: &#39;123&#39;,
    age: &#39;122&#39;,
    submit: &#39;submit&#39;}
*/
2.2 Obtenez les données soumises par la méthode POST sous la forme

Maintenant, nous utilisons la méthode post pour soumettre des données. Étant donné que les requêtes POST sont généralement « lourdes » (les utilisateurs peuvent saisir une grande quantité de contenu), si elles sont traitées de manière bloquante, cela entraînera inévitablement le blocage des opérations de l'utilisateur. Par conséquent, le nœud divise les données de publication en plusieurs petits blocs de données, puis transmet ces petits blocs de données via l'événement de données (indiquant que de nouveaux petits blocs de données sont arrivés) et l'événement de fin (indiquant que toutes les données ont été reçues). Par conséquent, notre idée devrait être : obtenir le bloc de données dans l'événement de données et exploiter les données dans l'événement final.

// server.js
var http = require(&#39;http&#39;),
querystring = require(&#39;querystring&#39;);

http.createServer(function(request, response){
    var html = &#39;<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>&#39;;
    
    if( request.method.toLowerCase()==&#39;post&#39; ){
        var postData = &#39;&#39;;

        request.addListener(&#39;data&#39;, function(chunk){
            postData += chunk;
        });

        request.addListener(&#39;end&#39;, function(){
            var data = querystring.parse(postData);
            console.log( &#39;postData: &#39;+postData );
            console.log(data);
    
            var s = &#39;<p><a href="/">back</a></p>&#39;+
                &#39;<p>username:&#39;+data.username+&#39;</p>&#39;+
                &#39;<p>password:&#39;+data.password+&#39;</p>&#39;+
                &#39;<p>age:&#39;+data.age+&#39;</p>&#39;;

            response.writeHead(200, {&#39;content-type&#39;: &#39;text/html&#39;});
            response.write(s);
            response.end();
        })
    }else{
        response.writeHead(200, {&#39;content-type&#39;: &#39;text/html&#39;});
        response.write(html);
        response.end();
    }
}).listen(3000);
console.log(&#39;server has started...&#39;);
Les principaux changements entre ce code et le projet de code précédent sont :

  1. Ne plus introduire le module url, modifier Utiliser le module de chaîne de requête. Parce que nous n'exploitons plus l'URL, il n'est pas nécessaire de l'introduire

  2. Utilisez

    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

  3. est écrite à l'intérieur de l'événement
  4. , car l'événement end est un fonctionnement asynchrone, donc ça doit être
  5. response.end()endresponse.end()On peut voir dans la console que postData est une chaîne comme celle-ci :

因此我们使用query.parse将postData解析为对象类型,以便获取提交过来的数据。

3. 路由

现在我们所有的逻辑都是在根目录下进行的,没有按照url区分,这里我们按照功能进行路由拆分。以上面的post请求为例,我们可以拆分为:页面初始化和form提交后的处理。

页面初始化:

// starter.js  页面初始化

function start(request, response){
    var html = &#39;<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>&#39;;
    
    response.writeHead(200, {"Content-Type":"text/html"});
    response.write( html );
    response.end();
}
exports.start = start;

展示获取的数据:

// uploader.js 展示获取的数据var querystring = require(&#39;querystring&#39;);function upload(request, response){    var postData = &#39;&#39;;

    request.addListener(&#39;data&#39;, function(chunk){
      postData += chunk;
    });
    
    request.addListener(&#39;end&#39;, function(){        var data = querystring.parse(postData);        console.log( &#39;postData: &#39;+postData );        console.log(data);        var s = &#39;<p><a href="/">back</a></p>&#39;+            &#39;<p>username:&#39;+data.username+&#39;</p>&#39;+            &#39;<p>password:&#39;+data.password+&#39;</p>&#39;+            &#39;<p>age:&#39;+data.age+&#39;</p>&#39;;

        response.writeHead(200, {&#39;content-type&#39;: &#39;text/html&#39;});
        response.write(s);
        response.end();
    })
}
exports.upload = upload;

然后在server.js中进行路由选择

// server.jsvar http = require(&#39;http&#39;),
url = require(&#39;url&#39;);

http.createServer(function(request, response){    var pathname = url.parse(request.url).pathname;    console.log(pathname);
    response.end();
}).listen(3000);console.log(&#39;server has started...&#39;);

我们任意改变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(&#39;http&#39;),
url = require(&#39;url&#39;),
starter = require(&#39;./starter&#39;),
uploader = require(&#39;./uploader&#39;);

http.createServer(function(request, response){    var pathname = url.parse(request.url).pathname;    var routeurl = {        &#39;/&#39; : starter.start,        &#39;/show&#39; : uploader.upload
    }    if( typeof routeurl[pathname]=== &#39;function&#39; ){
        routeurl[pathname](request, response);
    }else{        console.log(&#39;404 not found!&#39;);
        response.end();
    }
}).listen(3000);console.log(&#39;server has started...&#39;);

如果匹配到路由 / ,则执行 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 = &#39;<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>&#39;;
    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(&#39;formidable&#39;),
util = require(&#39;util&#39;),
fs = require(&#39;fs&#39;);function upload(request, response){    if( request.method.toLowerCase()==&#39;post&#39; ){        var form = new formidable.IncomingForm();

        form.uploadDir = &#39;./tmp/&#39;;
        form.parse(request, function(err, fields, files) {            var oldname = files.upload.name,
                newname = Date.now() + oldname.substr(oldname.lastIndexOf(&#39;.&#39;));
            fs.renameSync(files.upload.path, "./img/"+newname ); // 上传到 img 目录

            response.writeHead(200, {&#39;content-type&#39;: &#39;text/plain&#39;});
            response.write(&#39;received upload:\n\n&#39;);
            response.end(util.inspect({fields: fields, files: files}));
        });        return;
    }
}
exports.upload = upload;

我们上传图片后跳转到upload路径,然后显示出相应的信息:

received upload:

{
    fields: { // 其他控件,如input, textarea等
    submit: &#39;submit&#39;},
files:{ // file控件
    upload:{
            domain: null,
            _events: {},
            _maxListeners: undefined,
            size: 5097,
            path: &#39;tmp\\upload_b1f7c3e83af224e9f3a020958cde5dcd&#39;,
            name: &#39;chrome.png&#39;,
            type: &#39;image/png&#39;,
            hash: null,
            lastModifiedDate: Thu Jan 12 2017 23:09:50 GMT+0800 (中国标准时间),
            _writeStream: [Object]
        }
    }
}

我们再查看img目录时,就会发现我们刚才上传的照片了。

4.2 图片显示

将图片上传到服务器后,怎样才能把图片显示在浏览器上呢。这里我们就使用到了fs模块来读取文件,创建一个shower.js来专门展示图片:

// shower.jsvar fs = require(&#39;fs&#39;),
url = require(&#39;url&#39;);function show(request, response){    var query = url.parse(request.url, true).query,
        imgurl = query.src;    // 读取图片并进行输出
    // 这里读取链接中的src参数,指定读取哪张图片  /show?src=1484234660592.png
    fs.readFile(&#39;./img/&#39;+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 = {  
  &#39;/&#39; : starter.start,   
   &#39;/upload&#39; : uploader.upload,  
   &#39;/show&#39; : shower.show 
   // 添加
   };


最后在 upload.js 中进行图片的引用:

form.parse(request, function(err, fields, files) {    var oldname = files.upload.name,
        newname = Date.now() + oldname.substr(oldname.lastIndexOf(&#39;.&#39;));
    fs.renameSync(files.upload.path, "./img/"+newname ); // 同步上传图片

    response.writeHead(200, {&#39;content-type&#39;: &#39;text/html&#39;});    var s = &#39;<p><a href="/">back</a></p><p><img src="/show?src=&#39;+newname+&#39;" /></p>&#39;; // 显示刚才的图片
    response.write(s);
    response.end();
});

5. 综合

刚才学习了上传数据和上传图片,这里我们将其综合一下,拟定一个题目:“设定用户名密码,并上传头像”。希望可以自己实现一下。

6. 接口的实现

在第2部分学习了GET和POST请求,那么在这里写一个简单json或jsonp接口应该不是什么难事儿了吧。

创建一个 inter.js :

// inter.jsvar url = require(&#39;url&#39;);function init(request, response){    if( request.method.toLowerCase()==&#39;get&#39; ){        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 + &#39;(&#39; + JSON.stringify(data) + &#39;)&#39; );
         }else{            // json
            response.end( JSON.stringify(data) );
        }
    }
}
exports.init = init;

在server中添加inter的引用和路由映射:

var routeurl = {    &#39;/&#39; : starter.start,    &#39;/upload&#39; : uploader.upload,    &#39;/show&#39; : shower.show,    &#39;/inter&#39; : inter.init // 添加};

然后对 http://127.0.0.1:3000/inter 进行json请求或jsonp请求即可。

7. 总结

这节还是写了不少的内容,最核心的就是讲解如何搭建一个简单的http服务器,进行数据和图片的提交与处理,在最后稍微讲了下接口的编写,后面有机会的话,会再具体讲解下接口的编写。


Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn