Nodejs (二) 服务器


服务器基础概念

URL

URL,统一资源定位符

URL组成

传输协议://服务器IP或域名:端口/资源所在位置标识
http:超文本传输协议,提供了一种发布和接受HTML页面的方法

域名:由于IP地址难于记忆,所以产生了域名的概念,所谓域名就是平时上网所使用的网址。
http://www.itheima.com => http://124.165.219.100/
虽然在地址栏中输入的是网址, 但是最终还是会将域名转换为ip才能访问到指定的网站服务器

浏览器自动加默认端口

先通过IP或域名找到服务器,再根据端口找需要的服务

客户端服务器端说明

客户端服务器端使用同一台电脑
客户端:浏览器
服务器端:node

本机域名:localhost
本地IP:127.0.0.1

创建web服务器

系统模块 http

    const http = require('http');
    const app = http.createServer();

    //当客户端有请求来时
    app.on('request',(req, res)=>{
        
        //获取请求方式
        // req.method
        console.log(req.method);

        res.end('<h2>hello user</h2>');
    })

    //监听端口向外界发送服务
    app.listen(3000);
    console.log('网站服务器启动成功')

    

HTTP协议

规定了客户端和服务器端请求和响应的标准
规定了客户端和服务器端如何进行请求响应
超文本:除了文字以外包含图片视频音频(html)

报文

请求和响应的过程中传递的数据块叫报文,
浏览器开发者工具 network 可以查看报文信息

请求报文

1.请求方式

  • GET 请求数据
  • POST 发送数据
    浏览器输入网址是GET请求
    发送post请求需要form表单

form.html:

    <!--form标签的属性 
        method: 指定当前表单提交方式 (不写默认是GET)
        action: 指定当前表单提交的地址 
    -->
    
    <form method="post" action="http://localhost:3000">
        <input type="submit" name = "">
    </form>

req.method 返回 POST/GET
可以根据不同的请求方式做不同的事

    app.on('request', (req, res) => {
        req.headers  // 获取请求报文
        req.url      // 获取请求地址 端口后的  '/index'
        req.method   // 获取请求方法
    });

根据不同的url执行不同程序
req.url 在不输入请求地址的时候返回 ‘/’
req.headers 返回对象 中括号写键值获取特定报文

请求报文和响应报文都是键值对

响应报文

writeHead设置状态码和响应头信息

  1. HTTP状态码:
  • 200 请求成功 (默认值)
  • 404 请求的资源没有被找到
  • 500 服务器端错误
  • 400 客户端请求有语法错误

status是状态码

res参数是响应对象

res.writeHead 设置状态码 不写默认是200

    app.on('request',(req,res)=>{
        res.writeHead(404);
    })
  1. 内容类型
    根据返回内容设置
  • text/html
  • text/css
  • application/javascript
  • image/jpeg
  • application/json

writeHead还有第二个参数是响应报文信息(对象)

    res.writeHead(200,{
        'content-type': 'text/plain' // 纯文本 不指定的默认值
    });

编码也加到content-type 中
'content-type': 'text/html;charset=utf8'
后面整体不能有空格!!
(都是字符串加引号)

HTTP请求与响应处理

请求参数

客户端向服务器发送请求时需要携带信息,即通过请求参数的形式传递到服务器端

GEt请求

请求地址后有个问号 后面就是传递参数的键值对
http://localhost:3000/index?name=zhangsan&age=20
name和age两个键 &号隔开
上面这个链接的 req.url = ‘/index?name=zhangsan&age=20’
可以用字符串方法截取问号后面的数据但是麻烦
引入url模块↓

参数获取需要借助系统模块url,url模块用来处理url地址

    const url = require('url');

    url下面有parse方法
    url.parse(req.url, true)返回一个对象 
    
    方法接收两个参数:
    1. 要解析的url地址
    2. 将查询参数解析成对象形式
    返回的对象有一项是query 加true后 query变成对象
    {
        name: zhangsan,
        age: 20
    }
    不加true的query是"name=zhangsan&age=20"(字符串)

   
    /index?name=li&age=20 (req.url)
    
    url.parse(req.url)的返回结果:
    Url {
        protocol: null,
        slashes: null,
        auth: null,
        host: null,
        port: null,
        hostname: null,
        hash: null,
        search: '?name=li&age=20',
        query: 'name=li&age=20',
        pathname: '/index',
        path: '/index?name=li&age=20',
        href: '/index?name=li&age=20'
    }

    url.parse(req.url,true)的返回结果:
    Url {
        protocol: null,
        slashes: null,
        auth: null,
        host: null,
        port: null,
        hostname: null,
        hash: null,
        search: '?name=li&age=20',
        query: [Object: null prototype] { name: 'li', age: '20' },
        pathname: '/index',
        path: '/index?name=li&age=20',
        href: '/index?name=li&age=20'
    }

    区别在query

req.url既包含了请求地址(req.pathname)又包含了请 求参数

POST请求

GET请求的参数是在地址栏中的 而POST请求的参数在请求报文当中
通过form表单进行POST请求
chrome network中的formdata
参数格式和GET请求一样 name=li&age=20

由于参数不在地址栏不能用req.url接收
post参数由事件接收: data end

    const http = require('http');
    const app = http.createServer();

    app.on('request',(req, res)=>{
        //post参数可以无上限  所以不是一次接收
        let postParams ='';  // 用于拼接每次传递的参数

        //借助两个事件:
        //data  有请求参数传输的时候
        //end  参数传输完成的时候
        req.on('data',(params)=>{
            postParams += params;
        })

        req.on('end',()=>{
            console.log(postParams);
        }

        //客户端的每次请求服务器端都得有响应 (end)  否则客户单处于等待的状态
        res.end('ok');
    })
    //监听端口向外界发送服务
    app.listen(3000);

现在的postParams是name=li&age=20这样的字符串
于是又提供了一个内置模块来处理这种字符串
querystring模块
该模块的parse方法用来解析字符串成对象

    const querystring = require('querystring');
    ...
    console.log(querystring.parse(postParams));

    现在输出的结果是
    {name:'li', age:'20'}
  • POST小结
  1. 参数被放置在请求体中进行传输(请求报文)
  2. 获取POST参数需要使用data事件和end事件 (多次data事件)
  3. 使用querystring系统模块将参数转换为对象格式

路由

路由代码是指客户端请求地址与服务器端程序代码的对应关系,即请求什么响应什么(判断代码)
通过req.url和url模块的parse方法获取不带参数的地址(pathname)

// 1.引入系统模块http
// 2.创建网站服务器
// 3.为网站服务器对象添加请求事件
// 4.实现路由功能

const http = require('http');
const app = http.createServer();
const url = require('url');

// 1.获取客户端的请求方式
// 2.请求地址
app.on('request',(req,res)=>{
    const method = req.method.toLowerCase(); // req.method返回的是大写 用方法转换成小写方便判断

    const pathname = url.parse(req.url).pathname;

    res.writeHead(200,{
        'content-type': 'text/html;charset=utf8'
    });

    if(method == 'get'){
        
        if(pathname =='/' || pathname =='/index'){
            res.end('欢迎来到首页');
        })else if(pathname == '/list'){
            res.end('欢迎来到列表页');
        }else{
            res.end('您访问的页面不存在');
        }
    }else if (method == 'post'){
        //...
    }
});
app.listen(3000);
console.log('服务器启动成功');

资源访问

静态资源

服务器不需要处理,可以直接响应给客户端的资源,比如html、css、image等
eg. http://www.baidu.com/images/logo.png

请求路径(网址)只是字符串 和服务器的文件目录可以不一样
所以需要拼接路径 补全没有的文件夹 拼接成实际的硬盘路径

成功时响应报文类型需要规定 但不知道具体类型是什么 有可能是各种类型
第三方模块mime:
根据当前请求路径分析出文件类型
mine.getType(路径)方法返回文件类型 ‘text/html’

const http = require('http');
const url = require('url');
const path = require('path');
const fs = require('fs');
const mime = require('mime');

const app = http.createServer();

app.on('request', (req, res) => {
	// 获取用户的请求路径
	let pathname = url.parse(req.url).pathname;

	pathname = pathname == '/' ? '/default.html' : pathname;

	// 将用户的请求路径转换为实际的服务器硬盘路径
	let realPath = path.join(__dirname, 'public' + pathname);

	let type = mime.getType(realPath) //文件类型

	// 读取文件
	fs.readFile(realPath, (error, result) => {
		// 如果文件读取失败
		if (error != null) {
			res.writeHead(404, {
				'content-type': 'text/html;charset=utf8'
			})
			res.end('文件读取失败');
			return;
		}

        // 成功时要告诉资源类型
		res.writeHead(200, {
			'content-type': type
		})

		res.end(result); //读取内容返回给浏览器
	});
});

app.listen(3000);
console.log('服务器启动成功')

如果不申明 network中就没有’content-type’
新的浏览器没有也能显示正常 但旧版可能是隐患
所以必须要指定返回类型

动态资源

相同的请求的请求地址 传递不同的请求参数
http://www.a.com/title?id=1
http://www.a.com/title?id=2
两个的参数id不一样返回的也不一样

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值