>  기사  >  웹 프론트엔드  >  http 서버 구축을 위해 노드를 0부터 1(2)까지 학습합니다.

http 서버 구축을 위해 노드를 0부터 1(2)까지 학습합니다.

大家讲道理
大家讲道理원래의
2017-01-24 15:40:401126검색

이전 수업 전 학습에서는 다양한 모듈 사양 간의 연관성과 차이점에 대해 배웠습니다. 이번 섹션에서는 본격적으로 노드 학습을 시작합니다. 먼저 간단한 프로그램을 실행할 수 있는 http 서버를 구축하는 것부터 시작합니다.

1. Hello World

가장 클래식한 hello world. 먼저 코드를 저장하기 위해 server.js을 생성합니다:

console.log( 'hello world' );

실행하려면 터미널에 node server.js를 입력합니다:

node server.js

터미널 hello world라는 단어를 출력합니다. 하지만 노드 서버 프로그램은 항상 브라우저에서 액세스해야 합니다. 여기서는 노드와 함께 제공되는 http 모듈을 사용해야 합니다.

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

여기에 다시 node server.js를 입력합니다. 터미널에 서버가 시작되었습니다...라는 메시지가 터미널에 출력되어 서버가 생성되어 실행 중임을 나타냅니다. 그런 다음 브라우저에서 127.0.0.1:3000을 방문합니다. hello world 페이지가 출력되는 것을 볼 수 있습니다.

2. 양식

지금은 페이지에 간단한 텍스트를 출력했지만 이제 사용자가 정보를 입력하고 제출할 수 있는 양식을 페이지에 표시하려고 합니다.

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

server.js의 콘텐츠를 수정하고 다시 실행하세요.

node server.js

페이지를 새로 고친 후 텍스트 상자 3개와 제출 버튼 1개를 발견했습니다. 우리 프로그램은 페이지만 렌더링하고 다른 처리는 수행하지 않기 때문에 페이지에 데이터를 제출하면 현재 페이지가 새로 고쳐집니다.

참고: 노드의 코드를 수정할 때마다 다시 시작해야 합니다.

2.1 GET 방식으로 제출된 데이터 가져오기

위 코드에서는 POST 방식을 사용했지만, 여기서는 먼저 GET 방식으로 제출된 데이터에 대해 살펴보겠습니다. 먼저 생각하지 마십시오. 데이터 보안은 get 메소드를 사용하여 제출된 양식 데이터를 얻는 방법을 배우고, post를 get으로 변경하고, 다시 실행하는 것입니다.

get 메소드를 사용하여 데이터를 제출하면 데이터가 URL 매개변수로 전달된다는 것을 알고 있으므로 URL의 매개변수를 구문 분석하여 데이터를 얻습니다. 여기서는 url 모듈의 메소드가 사용됩니다. 🎜 >

// 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;);
제출을 다시 실행하면 데이터가 페이지에 표시됩니다.

url.parse는 URL 문자열을 구문 분석하고 구문 분석된 URL 객체를 반환하는 데 사용됩니다. 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;
       }

두 번째 매개변수가 true로 설정되면 반환된 결과의 쿼리 속성이 객체로 구문 분석되고 다른 속성은 변경되지 않습니다. 기본값은 false입니다. 즉, 쿼리 속성은 문자열입니다:

url.parse(request.url, true);result:Url {
...
query: {
    username: &#39;111113&#39;,
    password: &#39;123&#39;,
    age: &#39;122&#39;,
    submit: &#39;submit&#39; },
...
}
따라서 다음 명령문을 사용하여 제출된 데이터가 있는지 확인하고 제출된 데이터를 얻을 수 있습니다.

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 POST 형식으로 제출된 데이터 가져오기

이제 post 메서드를 사용하여 데이터를 제출합니다. POST 요청은 일반적으로 "무거우므로"(사용자가 많은 양의 콘텐츠를 입력할 수 있음) 차단 방식으로 처리되면 필연적으로 사용자 작업이 차단됩니다. 따라서 노드는 post 데이터를 여러 개의 작은 데이터 블록으로 분할한 후, 이 작은 데이터 블록을 data 이벤트(새로운 작은 데이터 블록이 도착했음을 나타냄)와 end 이벤트(모든 데이터가 수신되었음을 나타냄)를 통해 전달합니다. 따라서 우리의 아이디어는 데이터 이벤트에서 데이터 블록을 획득하고 종료 이벤트에서 데이터를 조작하는 것이어야 합니다.

// 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;);
이 코드와 이전 코드 프로젝트 간의 주요 변경 사항은 다음과 같습니다.

  1. 더 이상 URL 모듈을 도입하지 않고 쿼리 문자열 대신 가져오기를 사용합니다. 기준 치수. 더 이상 URL을 운영하지 않으므로 소개할 필요가 없습니다.

  2. 현재 제출된 데이터가 있는지 확인하려면

    request.method.toLowerCase()=='post'

  3. 데이터는 데이터 이벤트에 연결되어 종료 이벤트에서 처리됩니다.
  4. 이벤트 내부에 기록됩니다. 비동기 작업이므로 반드시 데이터 출력이 완료된 후에만 실행할 수 있습니다. response.end()endresponse.end()

  5. 콘솔에서 postData가 다음과 같은 문자열임을 확인할 수 있습니다.

아아아아

因此我们使用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服务器,进行数据和图片的提交与处理,在最后稍微讲了下接口的编写,后面有机会的话,会再具体讲解下接口的编写。


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.