05-http模块

目录

一、创建HTTP服务

 二、浏览器查看HTTP报文

1.GET请求

 2.POST请求

三、获取HTTP请求报文

1.获取请求头

 2.获取请求体

3.获取请求路径和查询字符串

 1. url模块

 2. 实例化URL对象

 4.HTTP请求练习

四、设置HTTP响应报文

1.设置http响应报文

 2.HTTP响应练习

1. 单独的html文件

2.引入多个文件资源

五、网页加载过程中向服务器发送了几个请求?

1.静态资源和动态资源

2.搭建静态资源服务

六、设置资源类型(mime类型)

七、GET和POST请求的区别


一、创建HTTP服务

const http = require('http');

//1.创建服务对象 内部调用时接收两个实参
//request 对请求报文的封装对象
//response 对响应报文的封装
const server = http.createServer((request,response)=>{
    response.end('hello')//设置响应体,并结束
});

//2.监听端口,启动服务
server.listen(9000,()=>{
    console.log('9000服务已经启动')
})

注意:

1.停止服务 ctrl + c

2.代码更新问题,必须重新启动服务。nodemon可以解决这个问题,不需要频繁重新启动服务。

3.响应内容中文乱码问题

response.setHeader('content-type','text/html;charset=utf-8');

4.端口号被占用问题。停止启动服务;更换端口号

5.HTTP默认端口80,HTTPS默认端口443。HTTP开发常用端口3000,808,8090,900

如果端口被其他程序占用,可以使用资源监视器查找占用端口的程序的PID,然后使用任务管理器关闭对于的程序。

 二、浏览器查看HTTP报文

1.GET请求

 2.POST请求

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <form action="http://127.0.0.1:9000" method="post">
        <input type="text" name="username" id="">
        <input type="text" name="password" id="">
        <input type="submit"  id="" value="提交">
    </form>
    
</body>
</html>

三、获取HTTP请求报文

想要获取请求数据,需要通过 request 对象

含义语法
请求方法request.method
请求版本request.httpVersion
请求路径request.url
URL路径require('url).parse(request.url).pathname
URL查询字符串require('url).parse(request.url, true).query
请求头request.headers
请求体

request.on('data', function(chunk){ })

request.on('end',function(){ })

注意:

  1. request.url只能获取路径和查询字符串,无法获取URL中的域名及协议内容
  2. request.headers 将请求信息转化成一个对象,并将属性都转化成小写
  3. 关于路径:如果访问网站只填写了IP地址或者域名,此时请求路径为 /
  4. favicon.ico :这个是浏览器自动发送的请求,用于获取网页图标

1.获取请求头

const http = require('http');

const server = http.createServer((request,response)=>{
    response.setHeader('content-type','text/html;charset=utf-8');
    //1.request.method
    //console.log(request.method);
    /*运行结果
        GET
        GET(favicon.ico的图标请求)
    */

    //2.request.url  只包含url中的路径与查询字符串  
    //console.log(request.url)
     /*运行结果
       /home/search?name=123&pwd=233
       /favicon.ico
    */

    //3.request.httpVersion 获取http协议的版本号
    //console.log(request.httpVersion)
    /*运行结果
       1.1
       1.1 
    */

    //4.请求头 是一个对象,对象里包括请求头所有内容,每个属性名变成了小写
    //console.log(request.headers);
    console.log(request.headers.host);//127.0.0.1:9000
    response.end('提取http报文')//设置响应体,并结束
});


server.listen(9000,()=>{
    console.log('9000服务已经启动')
})

request.heaaders 请求头内容

{
  host: '127.0.0.1:9000',
  connection: 'keep-alive',
  'cache-control': 'max-age=0',
  'sec-ch-ua': '"Google Chrome";v="111", "Not(A:Brand";v="8", "Chromium";v="111"',
  'sec-ch-ua-mobile': '?0',
  'sec-ch-ua-platform': '"Windows"',
  'upgrade-insecure-requests': '1',
  'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36',
  accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',  
  'sec-fetch-site': 'none',
  'sec-fetch-mode': 'navigate',
  'sec-fetch-user': '?1',
  'sec-fetch-dest': 'document',
  'accept-encoding': 'gzip, deflate, br',
  'accept-language': 'zh-CN,zh;q=0.9'
}
{
  host: '127.0.0.1:9000',
  connection: 'keep-alive',
  'sec-ch-ua': '"Google Chrome";v="111", "Not(A:Brand";v="8", "Chromium";v="111"',
  'sec-ch-ua-mobile': '?0',
  'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36',
  'sec-ch-ua-platform': '"Windows"',
  accept: 'image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8',
  'sec-fetch-site': 'same-origin',
  'sec-fetch-mode': 'no-cors',
  'sec-fetch-dest': 'image',
  referer: 'http://127.0.0.1:9000/home/search?name=123&pwd=233',
  'accept-encoding': 'gzip, deflate, br',
  'accept-language': 'zh-CN,zh;q=0.9'
}

 2.获取请求体

const http = require('http');

const server = http.createServer((request,response)=>{
    response.setHeader('content-type','text/html;charset=utf-8');
    //1.声明一个变量
    let body = '';

    //2.绑定时间 获取可读流绑定时间
    request.on('data',chunk=>{
        //chunk是buffer
        body += chunk.toString();
    })
    //3.绑定end
    request.on('end',()=>{
        console.log(body);//username=123&password=456
        response.end('提取http请求体')//设置响应体,并结束
    })
});


server.listen(9000,()=>{
    console.log('9000服务已经启动')
})

3.获取请求路径和查询字符串

 1. url模块

  • .parse方法来将一个URL字符串转换为URL对象, .format方法允许将一个URL对象转换为URL字符串
  • request.url不包含协议头和域名,但同样可以用.parse方法解析
  • 第二个参数等于true时,该方法返回的URL对象中,query字段不再是一个字符串,而是经过querystring转换后的参数对象。第三个参数等于true,该方法可以正确解析不带协议头的URL,例如//www.example.com/foo/bar
  • .resolve方法可以用于拼接URL
const http = require('http');
//导入url模块
const url = require('url');

const server = http.createServer((request, response) => {
    response.setHeader('content-type', 'text/html;charset=utf-8');
    //解析request.url
    //console.log(request.url)
    let res = url.parse(request.url);
    //console.log(res);
    let res2 = url.parse(request.url, true); //query属性将会变成对象, query: [Object: null prototype] { keyword: '123' },
    //console.log(res2);
    //路径
    let pathname = res.pathname;
    //console.log(pathname);
    /*运行结果
        /search
        /favicon.ico
    */

    //查询字符串
    let keyword = res2.query.keyword;
    console.log(keyword);
    /*运行结果
        123
        undefined
    */
    response.end('提取请求路径和字符') //设置响应体,并结束
});


server.listen(9000, () => {
    console.log('9000服务已经启动')
})

require('url).parse(request.url)内容

Url {
  protocol: null,
  slashes: null,
  auth: null,
  host: null,
  port: null,
  hostname: null,
  hash: null,
  search: null,
  query: null,
  pathname: '/',
  path: '/',
  href: '/'
}
Url {
  protocol: null,
  slashes: null,
  auth: null,
  host: null,
  port: null,
  hostname: null,
  hash: null,
  search: null,
  query: null,
  pathname: '/favicon.ico',
  path: '/favicon.ico',
  href: '/favicon.ico'
}

 2. 实例化URL对象

  •  new URL(input[, base])
const http = require('http');

const server = http.createServer((request, response) => {
    response.setHeader('content-type', 'text/html;charset=utf-8');
    //let url = new URL('/search?code=admin&pwd=123','http://127.0.0.1:9000')
    let url = new URL(request.url, 'http://127.0.0.1:9000');
    //console.log(url);
    console.log(url.pathname);
    //输出查询字符串内容
    //console.log(url.searchParams.code)// 不可行,必须用get()
    console.log(url.searchParams.get('code'));
    /*运行结果
        /search
        admin
        /favicon.ico
        null
    */
    response.end('提取请求路径和字符2') //设置响应体,并结束
});


server.listen(9000, () => {
    console.log('9000服务已经启动')
})

实例化URL对象

URL {
  href: 'http://127.0.0.1:9000/search?code=admin&pwd=123',
  origin: 'http://127.0.0.1:9000',
  protocol: 'http:',
  username: '',
  password: '',
  host: '127.0.0.1:9000',
  hostname: '127.0.0.1',
  port: '9000',
  pathname: '/search',
  search: '?code=admin&pwd=123',
  searchParams: URLSearchParams { 'code' => 'admin', 'pwd' => '123' },
  hash: ''
}
URL {
  href: 'http://127.0.0.1:9000/search?code=admin&pwd=123',
  origin: 'http://127.0.0.1:9000',
  protocol: 'http:',
  username: '',
  password: '',
  host: '127.0.0.1:9000',
  hostname: '127.0.0.1',
  port: '9000',
  pathname: '/search',
  search: '?code=admin&pwd=123',
  searchParams: URLSearchParams { 'code' => 'admin', 'pwd' => '123' },
  hash: ''
}

 4.HTTP请求练习

请求类型请求地址响应体结果
GET/login登录页
GET/reg注册页
const http = require('http')

const server = http.createServer((request, response) => {
    response.setHeader('content-type','text/html;charset=utf-8');
    //获取请求方法
    let {method} = request;
    //获取请求的url路径
    let {pathname} = new URL(request.url,'http://127.0.0.1:500')
    // console.log(method);
    // console.log(pathname);
    if(method === 'GET' && pathname === '/login'){
        response.end('登录页')
    }else if(method === 'GET' && pathname === '/reg'){
        response.end('注册页')
    }else{
        //未改变响应状态码仍然是200
        response.end('404')
    }
})

server.listen(5000, () => {
    console.log('5000')
})

四、设置HTTP响应报文

作用语法
设置响应状态码response.statusCode
设置响应状态信息response.statusMessage
设置响应头信息response.setHeader('头名', '头值')
设置响应体

response.write('xxxxxx')

response.end('xxxxxx')

注意:

  • write可多次调用
  • write,end里都存在内容,内容将会拼接成一个,所有一般情况下write里有内容,end不进行设置
  • 必须有end,有且只要一个 

1.设置http响应报文

const http = require('http')

const server = http.createServer((request, response) => {
    response.setHeader('content-type', 'text/html;charset=utf-8');

    //响应状态码
    response.statusCode = 203;
    //响应状态描述
    response.statusMessage = 'check';
    //响应头
    response.setHeader('content-text', 'text/html;charset=utf-8')
    response.setHeader('server', 'Node')
    response.setHeader('myHeader', 'header')
    //设置多个同名头
    response.setHeader('headers', ['test1', 'test2'])
    //响应体设置 write可多次调用
    response.write('hello!')
    response.write('hello!')
    //必须有end(),有且仅有一个
    response.end('');//如果有write,end里就不要设置了
})

server.listen(5000, () => {
    console.log('5000')
})

 2.HTTP响应练习

 响应一个4行3列的表格,并要求表格有隔色换行的效果,且点击单元格高亮显示

1. 单独的html文件

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        td {
            padding: 10px 20px;
        }

        table,
        td {
            border-collapse: collapse;
        }

        table tr:nth-child(odd) {
            background-color: skyblue;
        }

        table tr:nth-child(even) {
            background-color: pink;
        }
    </style>
</head>

<body>
    <table border="1">
        <tr>
            <td></td>
            <td></td>
            <td></td>
        </tr>
        <tr>
            <td></td>
            <td></td>
            <td></td>
        </tr>
        <tr>
            <td></td>
            <td></td>
            <td></td>
        </tr>
        <tr>
            <td></td>
            <td></td>
            <td></td>
        </tr>
    </table>
    <script>
        let tds = document.querySelectorAll('td');
        tds.forEach(item => {
            item.onclick = function () {
                this.style.background = '#f0f0f0';
            }
        })
    </script>

</body>

</html>
const http = require('http');
const fs = require('fs');

const server = http.createServer((request, response) => {
    response.setHeader('content-type', 'text/html;charset=utf-8');
    let html = fs.readFileSync(__dirname+'/index2.html');
    response.end(html);
    
})

server.listen(5000, () => {
    console.log('5000')
})

2.引入多个文件资源

const http = require('http');
const fs = require('fs');

const server = http.createServer((request, response) => {
    //response.setHeader('content-type', 'text/html;charset=utf-8');
    //let html = fs.readFileSync(__dirname+'/index2.html');
    //response.end(html); 不可行

    //必须根据请求url路径返回对应的结果
    let {pathname} = new URL(request.url, 'http://127.0.0.1');
    if(pathname ==='/'){
        let html = fs.readFileSync(__dirname+'/index2.html');
        response.end(html); 
    }else if(pathname ==='/index.css'){
        let css = fs.readFileSync(__dirname+'/index.css');
        response.end(css); 
    }else if(pathname ==='/node.png'){
        let img = fs.readFileSync(__dirname+'/node.png');
        response.end(img); 
    }else if(pathname ==='/index.js'){
        let js = fs.readFileSync(__dirname+'/index.js');
        response.end(js); 
    }else{
        response.statusCode = 404;
        response.end('<h3>404</h3>')
    }
})

server.listen(3000, () => {
    console.log('3000')
})

 注意:引入多个资源文件时,必须根据需要请求的url路径做判断,响应对应文件

五、网页加载过程中向服务器发送了几个请求?

1.静态资源和动态资源

  • 静态资源是指内容长时间不发生变化的资源,例如:图片、视频、css文件、js文件、html文件、字体文件。
  • 动态资源是指长时间经常更新的资源,例如:百度首页、京东搜索列表页等。

2.搭建静态资源服务

/**创建一个HTTP服务,端口为6000,满足如下服务
 * GET /index2.html          响应 static/index2.html内容
 * GET /css/index.css        响应 static/css/index.css内容
 * GET /img/node.png         响应 static/img/node.png内容
 * GET /js/index.js          响应 static/js/index.js内容
 */

const http = require('http');
const fs = require('fs');
const path = require('path');
//匹配类型
let mines = {
    html :'text/html',
    css :'text/css',
    png :'image/png',
    js:'text/javascript',
    json:'application/json'
}
const server = http.createServer((request, response) => {
    if(request.method !== 'GET'){
        response.setHeader('content-type','text/html;charset=utf-8');
        response.statusCode = 405;
        response.end('方法不被允许');
        return;
    }
    //必须根据请求url路径返回对应的结果
    let {pathname} = new URL(request.url, 'http://127.0.0.1');
    //网站的根目录,可根据需求调整
    //let root = __dirname + '/../';
    let root = __dirname + '/static';
    //拼接文件路径
    let filename = root + pathname;

    //读取文件 
    fs.readFile(filename,(err,data)=>{
        //完善错误处理
        if(err){
            //判断错误代号
            //console.log(err.code);
            //response.setHeader('content-type','text/html;charset=utf-8');
            switch(err.code){
                case 'ENOENT':
                    response.statusCode = 404;
                    response.end('文件不存在');
                    //EPERM (操作不被允许)
                case 'EPERM':
                    response.statusCode = 403;
                    response.end('无权限进行访问');
                default:
                    response.statusCode = 500;
                    response.end('服务器内部错误');
            }
            return;
        }
        //设置响应文件类型,根据文件类型后缀决定
        //1.获取文件后缀名
        let etx = path.extname(filename).slice(1);
        //console.log(etx);
        //获取对应的类型
        let type = mines[etx];
        
        if(type){
            //解决乱码问题
            response.setHeader('content-type',type + ';charset=utf-8');
            //response.setHeader('content-text',`${type};charset=utf-8`);//不生效
            
        }else{
            response.setHeader('content-type','application/octet-stream');
        }
        //响应文件内容
        response.end(data);
    })
    
})

server.listen(5000, () => {
    console.log('5000');
})

注意:

1.HTTP服务在那个文件夹中寻找静态资源,那个人家就是静态资源目录,也称为网站根目录

六、设置资源类型(mime类型)

  • 媒体类型通常被称为一种标准,用来表示文档、文件或字节流的性质和格式。
  • mime类型结构  [type]/[subType],如:text/html     text/css  image/jpeg  application/json
  • HTTP设置Content-type来表明响应体的类型,浏览器会根据该类型决定如何处理资源
  • 对于未知的资源可以application/octet-stream类型,浏览器会在遇到该类型时,会对响应体内容进行独立存储,也就是常见的下载效果

七、GET和POST请求的区别

  1. 作用:GET主要用来获取数据,POST用来提交数据
  2. 参数位置:GET带参数请求是将参数缀到URL中,POST带参数是将参数放到请求体中
  3. 安全性:POST安全性相对较高,因为浏览器中参数会暴露在地址栏中
  4. GET请求大小有限制,一般2K,而POST没有大小限制

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

才不吃胡萝卜嘞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值