zoukankan      html  css  js  c++  java
  • Node教程——HTTP协议,开发一个简单的静态网站

    明确目标:

    我们要开发一个静态的网站,下面就是它的网站首页

    四、做一些开发前的知识储备

    重要!:在js中的事件监听一般都是这样的格式

    obj.on(event,callback)
    
    表示的意思是:我们的对象正在监听event事件的发生,一旦发生了 我们有一个处理函数(回调函数callback)去处理它
    

    (一)、 有关于服务器嗨哟客户端之间的通信

    这个非常的重要,你要知道所有的app之间是要建立起通信的,要不然你只是一个单机的版本,这就没什么意思了,只有联网,才能让你的应用更加的出色

    开发网站服务器第一步建立起浏览器还有服务器之间的通信?

    1. 建立通信的第一步:找到对应服务器的地址还有端口,这就需要问你的URL地址

    URL的组成:传输协议://服务器ip或则域名:端口/资源所在的位置,

    注意:端口80是默认可以省略的

    实例:https://y.qq.com/n/yqq/playlist/7382629476.html

    https:是协议
    这里的y.qq.com是网站的域名,
    n/yqq/playlist/7382629476.html是请求支援所在的路径
    注意这里的端口号没有了,其实是有一个默认的80端口,这里80是可以省略的
    也就是你怎么写也是ok的
    https://www.baidu.com:80

    1. 服务器是什么?
      我们的客户端是浏览器,我们的服务器就是node,其实就是一个软件,这个软件里面跑的就是我们的网站代码

    我们如何通过URL访问在本电脑下的服务端呢?答案就是通过
    本机域名:localhost
    本机ip:127.0.0.1
    别着急接下里我们来创建一个网站服务器,让你了解

    1. 创建web服务器

    网站服务器实际上就是一台电脑

    • 下面的代码都是固定死的,你记住就好
      下面的代码在app.js中
    // nodejs和js一样都是事件驱动,当什么什么时,做是什么什么事情
    
    // 1.用于创建网站服务器的模块
    const http = require('http');
    
    // 2. app对象就是网站服务器对象
    const app = http.createServer(); //返回的是一个----对象
    // 3. 当客户端有请求来的时候
    app.on('request', (req, res) => { 
        // 响应
        // req表示的就是请求,res表示的就是回送
        res.end('哈哈哈哈')
    });
    // 4. 监听端口
    app.listen(3000);
    
    console.log('网站服务器启动成功');
    

    在之后,去到命令行,node app.js
    你看:一个非常简单的node服务器就启动成功了
    然后你去到浏览器地址栏输入 localhost:3000就能访问我们的服务器了

    (二)、 详解http协议

    必背单词-请求:request,简写req
    必背单词-响应:response,简写res

    所谓的http协议指的就是服务器还有客户端之间的沟通介质
    http介质里面 包含的传输的数据块 就是报文

    报文有两类,

    报文在哪儿看?

    打开你游览器的控制台就能看到了

    我们随便点开一个报文看看里面都 有什么

    1. 请求报文

    简称 req

    给服务器发数据 使用的报文就是请求报文。有如下的请求方式

    • get请求数据。post发送数据

    接下来我们来看看,req报文(请求报文 以下简称req)里面的数据如何获得和如何处理

    
    // 1.req对象, req对象里面就包含了 请求的所有信息,不管你是post还是get 只要是req,你们req对象里面就是你的请求数据
    
    // 2.  服务器拿到req之后,你就可以使用对应的方法去处理请求报文里的数据了
    // 3. 处理报文
    
    // 3.1 req.method  获取请求方式就是看看你是get还是post
    // console.log(req.method);
    
    // 3.2 获取请求地址
    // req.url
    // console.log(req.url);
    // 3.3 获取请求报文信息
    // req.headers
    // console.log(req.headers['accept']);//其实这个就是对象[]键的方式就ok了
    
    
    
    
    1. 响应报文
    // res就是我们响应出去的报文,以下简称res(响应报文)
    
    
    // 1.首先我们来了解以下HTTP状态码,这也是我们res做的事情之一
    // 200 请求成功
    // 404 请求的资源没有被找到
    // 500 服务器端错误
    // 400 客户端请求有语法错误
    
    
    // 2.我们看看如何设置响应的内容类型,下面的就是我们的可以定义的res类型,
    // text/html
    // text/css
    // application/javascript
    // image/jpeg
    // application/json
    
    //3.代码示例writeHead是一个res的方法,可以用来设置HTTP状态码还有相应数据类型
    app.on('request', (req, res) => {
         // 设置响应报文,
         res.writeHead(200, {'Content-Type': 'text/html;charset=utf8‘
         });
     });
    
    
    1. 如何在报文中传递数据

    其实这个也非常的简单,主要有如下的几种格式

    注意啊,这里说的格式是就像你写信的格式还有写作文的格式,而他们的本质都是字写在纸上,在我们的http中,不管你是用那种格式传输 ,最终都是以字符串的形式传递出去!这一点 你一定要注意

    • 对于get请求参数
      参数的形式

    url?键1=值1&键2=值2&....
    多个键值对用&隔开

    代码举例:http://localhost:3000/?name=zhangsan&age=20
    这个就代表你给服务器发了这样的数据:
    name(键)=zhangsan(值)&age(键)=20(值)

    那么问题来了,我们如何获得req中的url?
    别担心,我们有内置的url系统模块,接下来我们就来详细的介绍以下它的使用

    代码示例:

    +++
     // 1.导入url系统模块 用于处理url地址
     const url = require('url');
     
     app.on('request', (req, res) => {
         // 将url路径的各个部分解析出来并返回对象
         // true 代表将参数解析为对象格式,然后我们在起那面用另一个对象的query去接收它
         console.log(url.parse(req.url);//你发现它这个对象里面有所有的关于url的数据,其中有一个query就是表示的是rul后面的请求参数
         
         /*你将会获得如下的数据
        Url {
            protocol: null,
            slashes: null,
            auth: null,
            host: null,
            port: null,
            hostname: null,
            hash: null,
            search: '?name=zhangsan&age=20',
            query: 'name=zhangsan&age=20',
            pathname: '/',
            path: '/?name=zhangsan&age=20',
            href: '/?name=zhangsan&age=20' }
    
         */
    
    
         //我们把query解构出来,放到一个对象里面
         let {query} = url.parse(req.url, true);
         console.log(query);
    //你能获得的结果:{ name: 'zhangsan', age: '20' }
    
     });
     app.listen(3000);
    
    
    //url.paares是一个方法,在经过它处理之后会返回一个对象,true就是该方法的选项,它的作用是参数解析成对象形式,说白了就是把返回对象里面的query搞成对象,这里做了一个解构
    let { query, pathname } = url.parse(req.url, true);
        console.log(query.name)
        console.log(query.age)
    
    • 对于POST的请求,

    首先你需要明白我们的post的参数是附在报文里的,get是附在url上的,也就是说post比较安全

    1. 对于get的请求的发送给服务器还是比较简单的,直接在浏览器rul里附加就完事,但是问题又来了,难不成我们每次请求都在浏览器后面输入?那么肯定不是这样的,接下里我们通过一个 html表单的提交事件,来演示 到底如何发数据给服务器,在真实的网页中
    <body>
        <!--
            method: 指定当前表单提交的方式.,有get还有post处理方式
            action: 指定当前表单提交的地址
            action:指定提交给谁
    
    	-->
        <form method="post" action="http://localhost:3000">
            <input type="text" name="username">
            <input type="password" name="password">
            <input type="submit">
        </form>
    </body>
    
    说明:通过post的方式我的请求数据就丢到了报文里面 ,接下里我们就去服务器看看如何处理这些post请求数据
    
    

    我们看一下post的报文请求信息在哪儿,由于我们的

    1. 说完了我们的发送之后,我们看一下post的请求参数在服务器中如何处理
      注意:我们在这里又要用到我们的一个系统模块,这个模块专门用来处理POST的请求数据
     // 1.导入系统模块querystring 用于将HTTP参数转换为对象格式
     // 注意:万物皆对象的思想是非常非常的重要的
    
     const querystring = require('querystring');
     
     app.on('request', (req, res) => {
         let postData = '';
    
         // 2.监听参数传输事件
         req.on('data', (chunk) => postData += chunk;);
         // 3.监听参数传输完毕事件
         req.on('end', () => { 
             console.log(querystring.parse(postData)); 
         }); 
     });
    
    说明:在post请求参数比较特殊,在服务器它不是一下子就给你获取完的,而是一点一点的获取。所以有一个传输事件data。还有一个传输完成事件end,
    
    注意一些data事件发生后都会出一个数据,我们用chunk去接受它,然后就拼在我们的postData变量中,注意这个chunk不一定是chunk随便你定义,总之你data后会给一个数据处理结果出来,我们拿一个变量接受它就完事
    
    最后我们end的时候,用querystring对象下的parse()方法可以处理一下数据。把字符串转对象,如何取出来
    

    (三)、 路由

    指的是:请求什么就响应什么,请求还有响应要一一对应起来,完成这件事的就是路由,本质上就是一段判断代码,这样的业务逻辑非常的简单,这里就不一一讲解了

    接下来我们演示最原始的处理

    // 1.引入系统模块http
    // 2.创建网站服务器
    // 3.为网站服务器对象添加请求事件
    // 4.实现路由功能 需求分析:默认的就是给出首页提示,如果是index也是给出首页提示 如果是list给出列表页提示,如果是没有,提示不存在
    // 	1.获取客户端的请求方式
    // 	2.获取客户端的请求地址
    
    // 1-引入相关的模块
    const http = require('http');
    const url = require('url');
    
    // 2-创建服务器
    const app = http.createServer();
    
    app.on('request', (req, res) => {
    
        //5-业务逻辑-
        /*
            核心孙算法:根据url地址给出不同响应
        */
        // 获取请求方式 tolowcat装换成小小写
        const method = req.method.toLowerCase();
        // 获取请求地址,弄成一个 不带参数的请求地址 获取的是请求地址,
        const pathname = url.parse(req.url).pathname;
        
        //这里的是,响应报文的处理
        res.writeHead(200, {
            'content-type': 'text/html;charset=utf8'
        });
    
        // 注意:对于请求是地址的,两个方法都是一样的 get 和post
        if (method == 'get') {
    
            if (pathname == '/' || pathname == '/index') {
                res.end('欢迎来到首页')
            } else if (pathname == '/list') {
                res.end('欢迎来到列表页')
            } else {
                res.end('您访问的页面不存在')
            }
    
        } else if (method == 'post') {
    
        }
    
    });
    //4-监听端口
    app.listen(3000);
    console.log('服务器启动成功')
    
    

    (四)、 资源

    有两种,静态的还有动态的,两者搭配是最妙的

    1. 静态资源
      指的是:服务器端不需要处理,可以直接响应给客户端的资源就是静态资源,比如css比如js比如img等等

    2. 动态资源
      指的是:相同的请求地址不同的响应资源,这种资源就是动态资源。

    3. 实战
      接下来我们来做这样的一个事情:

    先说一个事情:我们现在处于初级阶段,这里的访问指的是 我们直接在地址栏中输入

    我的app同级目录下有一个静态页面,我需要在访问http://localhost:3000的时候或则http://localhost:3000/index.html的时候就能直接到我们的index页面,如果我访问http://localhost:3000/list.html就能去到对应的页面,如果我输入
    http://localhost:3000/images/1.jpg我也能拿到对应的图片

    核心算法分析

    其实就是更几乎url里面的请求地址拿出来。进行判断,如何用fs把对于的路径文件响应回去就可以,同时要足以细节,我们的响应类型,应该根据我们的url走,你拿什么我就给什么,而且要注意路径的拼接问题
    
    1. 1 首先我们把文件目录搭建起来
      img

    2. 2 搭建核心代码

    //处理服务器的业务逻辑
    
    //1.引入模块
    const http = require('http');
    const url = require('url');//处理url
    const path = require('path'); //路径拼接的模块
    const fs = require('fs'); ////文件处理的模块
    
    //这个是一个第三方某块。这个模块就是可以判断路径从而返回资源的类型
    const mime = require('mime');
    //2.创建服务器
    const app = http.createServer();
    //3.开启
    app.on('request', (req, res) => {
        
        // 5.核心业务代码
        // 5.1 获取用户的请求路径,注意我们获取的是路径们也就是,url.parse(req.url)身上的pathname
        let pathname = url.parse(req.url).pathname;
    
        //5.2 拼接 注意这里的三元运算符
        pathname = pathname == '/' ? '/default.html' : pathname;
    
        //  5.3 将用户的请求路径转换为实际的服务器硬盘路径
        // __dirname获取当前文件所在的绝对路径
        let realPath = path.join(__dirname, 'public' + pathname);
        let type = mime.getType(realPath)//拿到请求类型,这个方法没有必要深究,反正就是可以获取出来
        
        
    
        // 5.4 读取文件,第二个是可选参数,读取文件然后返送回去
        fs.readFile(realPath, (error, result) => {
            // 如果文件读取失败
            if (error != null) {
                res.writeHead(404, {
                    'content-type': 'text/html;charset=utf8' 
                })
                res.end('文件读取失败');
                return;
            }
    
            // 5.5 给一个200的响应,然后重新设置类型
            res.writeHead(200, {
                'content-type': type //由于 你是不知道返回的是什么类型的文件,因为有外链情况
            })
    
            res.end(result);
        });
    });
    //4.监听端口
    app.listen(3000);
    console.log('服务器启动成功')
    
    

    一定要注意外联文件的情况,我们的核心算法:
    根据当前请求的类型返回对应的类型资源

  • 相关阅读:
    项目流程
    Html5 经验
    knockoutjs 经验总结
    redmine处理规范
    用fiddler监控移动端的通讯
    git
    es6 中的 Promise
    html5游戏的横屏问题
    jQuery 学习笔记
    jQuery 里的 Promise
  • 原文地址:https://www.cnblogs.com/BM-laoli/p/12655453.html
Copyright © 2011-2022 走看看