// 1.导入http模块
const http = require('http');
// 2.创建服务对象
const server = http.createServer((request,response) => {
response.end('Hello HTTP Server');// 设置响应体
}
// 3.监听端口,启动服务
server.listen(9000,() => {
console.log('服务已经启动...')
})

通过上面图片显示的访问方法加上fiddler 的使用就可以得到相应的请求报文和响应报文。

停止HTTP 服务
在哪个命令行启动的HTTP 服务就在那个命令行停止HTTP 服务
更新代码必须重新启动HTTP 服务
响应体为汉字会出现乱码
// 2.创建服务对象
const server = http.createserver((request,response) => {
// response.end('Hello HTTP');// 设置响应体
response.setHeader('content-type','text/html;charset=utf-8');// 设置响应头
response.end('你好');// 设置响应体
);
如果端口被其他程序占用,可以使用
资源监视器找到占用端口的程序,然后使用任务管理器关闭对应的程序
注:资源监视器在utools 中可以搜索到,在侦听端口找到相应端口正在运行的程序的PID ,再在vscode 中右键打开任务管理器通过PID 关闭相应程序。

查看请求头:标头 --> 请求标头(里面全部内容均为请求头)
查看请求头:请求表头右侧查看源代码可以查看请求行和请求头
查看请求体:
get 请求的请求体一般都是为空的,所以我们可以改为post 请求

表单的提交时发出的请求就是post 请求。

载荷除了能够查询请求体内容之外,还可以快速查询URL 中查询字符串的内容!

获取请求报文是为了能够返回正确的响应结果。
// 2.创建服务对象
const server = http.createserver((request,response) => {
// 获取请求的方法
console.log(request.method);
// 获取请求的url
console.log(request.url);// 只包含url中的路径与查询字符串
// 获取HTTP协议的版本号
console.log(request.httpVersion);
// 获取HTTP的请求头
console.log(request.headers);// 返回一个对象
console.log(request.headers.host);// 获取请求头的某个解析值
response.end('http');// 设置响应体
});
(这种方法了解即可,之后会再进行学习)
// 2.创建服务对象
const server = http.createServer((request,response) => {
// 1.声明一个变量
let body = '';
// 2.绑定data事件
request.on('data',chunk => {
body += chunk;
// body += chunk.toString();
})
// 3.绑定end事件
request.on('end',() => {
console.log(body);
// 响应
response.end('Hello HTTP');
})
})
// 导入http模块
const http = require('http');
// 1.导入ur1模块
const url = require('ur1');// Node.js 内置模块 可以对URL 进行解析
// 2.创建服务对象
const server = http.createServer((request,response) => {
// 2.解析request.url
// console.log(request.url);// 字符串形式(路径+查询字符串)
let res = url.parse(request.url,true);// query 转化为了对象形式
// 路径
let pathname = res.pathname;
// 查询字符串
let keyword = res.query.keyword;
console.log(keyword);
response.end('url');
)
// 3.监听端口,启动服务
server.listen(9000,() => {
console.log('服务已经启动...')
})
// 导入http模块
const http require('http');
// 不需要导入URL 模块
// 创建服务对象
const server = http.createserver((request,response) => {
// 实例化URL的对象
// let url = new URL('http://127.0.0.1:9000/search?a= 100&b=2081');
// let url = new URL('/search?a= 100&b=2081', 'http://127.0.0.1:9000');
let url = new URL(request.url, 'http://127.0.0.1');// 端口号无所谓
// 路径
console.log(url.pathname);
// 输出keyword查询字符串
console.log(url.searchParams.get('keyword')) // url.searchParams 是对象形式
response.end('url new');
)}
// 监听端口,启动服务
server.listen(9000,() => {
console.log('服务已经启动...')
});
练习要求:
当请求类型为get 且请求路径为/login 就显示登录页面;当请求类型为get 且请求路径为/reg 就显示注册页面。

const http = require('http')
const server = http.createServer((request, response) => {
let { method } = request;
let { pathname } = new URL(request.url, 'http://127.0.0.1');
response.setHeader('content-type','text/html;charset=utf-8')
if (method === 'GET' && pathname === '/login') {
response.end('登录页面')
} else if (method === 'GET' && pathname === '/reg') {
response.end('注册页面')
} else {
// 如果某个请求一直没有响应,持续占用资源只会一直浪费,所以需要对这种情况进行响应
response.end('Not Found')
}
})
server.listen(9000, () => {
console.log('go');
})

const http = require('http')
const server = http.createServer((request, response) => {
// 1.设置响应状态码
response.statusCode = 203;
response.statusCode = 404;// 后者会覆盖前者
// 2.响应状态的描述
response.statusMessage = 'iloveyou'// 几乎不使用 因为一般响应状态码有对应的响应状态描述
// 3.响应头
// response.setHeader('content-type','text/html;charset=utf-8');
// response.setHeader('Server','Node.js');
// response.setHeader('myHeader','test test test');// 设置自定义响应头
response.setHeader('test',['a','b','c']);// 设置多级同名响应头
})
// 4.响应体的设置
response.write('love');
response.write('love');// write() 是可以多次调用的 但是end() 不可以
// response.end();// 设置响应体 一般来说我们使用了write() 设置响应体就不会再去使用end()
server.listen(9000, () => {
console.log('go');
})

搭建HTTP 服务,响应一个4行3列的表格,并且要求表格有隔行换色效果,且点击单元格能高亮显示
const http = require('http')
const fs = require('fs')
const server = http.createServer((request, response) => {
let table = fs.readFileSync(__dirname + '/12-table.html')
response.end(table) // end() 中既能传入字符串也能传入Buffer
})
server.listen(9000,() => {
console.log('go');
})
请求一般都是并行的,不需要等到服务器响应上一个请求就可以进行下一个请求的发送。
比如说下面一个页面:

这部分内容可以让上面4.2 练习更完善一点。
对于上面4.2 练习的内容我们如果将html 文件中css 部分和js 部分使用外联式引入,那么只靠我们写出的那部分代码是无法成功显示处我们想要的页面的,我们需要对每个请求都作出相应的响应。
let { pathname } = new URL(request.url, 'http://127.0.0.1');
if (pathname === '/') {
let table = fs.readFileSync(__dirname + '/12-table.html')
response.end(table)
}
else if (pathname === '/12-table.css') {
let css = fs.readFileSync(__dirname + '/12-table.css')
response.end(css)
}
else if (pathname === '/12-table.js') {
let js = fs.readFileSync(__dirname + '/12-table.js')
response.end(js)
} else {
response.statusCode = 404;
response.end('404 Not Found
')
}
现在看来如果一个html 文件引入多个css 文件或者js 文件,那么就需要写多个else if ,这是很麻烦的,但是我们后面会改进这种写法。
静态资源是指
内容长时间不发生改变的资源,例如图片、视频、css文件 、js文件、HTML文件、字体文件等;
动态资源是指内容经常更新的资源,例如百度首页、网易首页、京东搜索列表等
这些资源都是相对于项目上线之后来说的。
创建一个HTTP服务,端口为900,满足如下需求
GET /index.html 响应 page/index.html的文件内容
GET /css/app.css 响应 page/css/app,css的文件内容
GET /images/logo.png 响应page/images/logo.png的文件内容

如果我们按照上面这种方式边写代码是很麻烦的,但是我们发现pathname 问年路径与我们读取的文件的路径有相似之处,我们可以利用这点对我们的代码进行简化。
const http = require('http')
const fs = require('fs')
const server = http.createServer((request, response) => {
let { pathname } = new URL(request.url, 'http://127.0.0.1')
let filePath = __dirname + pathname
// 这个地方我们先使用异步读取文件
// 因为我们还没有学习同步读取文件的错误处理方式
fs.readFile(filePath, (err, data) => {
response.setHeader('content-type','text/html;charset=utf-8');
if (err) {
response.statusCode = 500
response.end(err.toString())
return;
}
response.end(data)
})
})
server.listen(9000, () => {
console.log('go');
})
静态资源目录和网站根目录其实所指的是同一个东西,只是不同的叫法而已。
HTTP 服务在哪个文件夹中寻找静态资源,那个文件夹就是静态资源目录,也称之为网站根目录。
// 之前的写法
let { pathname } = new URL(request.url, 'http://127.0.0.1')
let filePath = __dirname + pathname
// 使用网站根目录 之后也方便根据需求修改
let { pathname } = new URL(request.url, 'http://127.0.0.1')
let root = __dirname +'/网站根目录/'
let filePath = root + pathname
思考:
vxcode 中使用Live Server 访问html 时,它启动的服务网站根目录是谁?
就是以所打开的文件夹作为网站根目录
网页URL 主要分为绝对路径和相对路径。

其中我们使用第一种形式比较多。


相对路径在平常用的多,但是在项目运行阶段时用的很少;
因为相对路径不可靠,当页面URL 不正常的时候我们再去使用相对路径去获取资源就会出现异常。
包括但不限于如下场景:
媒体类型(通常称为Multipurpose Internet Mail Extensions或MlME类型)是一种标准,用来表示文档、文件或字节流的性质和格式。
HTTP 服务可以设置响应头Content-Type 来表明响应体的MIME 类型,浏览器会根据该类型决定如何处理资源;
下面是常见文件对应的mime类型:
对于未知的资源类型,可以选择application./octet-stream类型,浏览器在遇到该类型的响应时,会对响应体内容进行独立存储,也就是我们常见的下载效果.
const path = require('path')
if (err) {
response.statusCode = 500;
// response.setHeader('content-type','text/html;charset=utf-8');
response.end(err.toString())
return;
}
// 获取文件的后缀名
let ext = path.extname(filePath)
// 获取对应的类型
let type = mimes[ext]
if (type) {
// 匹配到了
response.setHeader('content-type',type)
} else {
// 没有匹配到
response.setHeader('content-type','application/octet-stream')
}
// 响应文件内容
response.end(data)
一般来说,我们只需要给html 文件设置字符集,因为相应的css / js 文件会根据html 文件的字符集进行解析。
if(type){
if(html){
response.setHeader('content-type',type+';charset=utf-8')
}else{
response.setHeader('content-type',type)
}
// 判断错误的代号
switch(err.code){
case 'ENOENT':
response.statusCode = 404;
response.end('404 Not Found
');
case 'EPERM':
response.statusCode = 403;
response.end('403 Forbidden
');
// 其他错误
defalt:
response.statusCode = 500;
response.end('Interval Server Error
');
}
if(request.method !=='GET'){
response.statusCode = 405;
response.end('405 Method Not Allowed
');
return;
}
GET请求的情况:
POST请求的情况:
GET和POST是HTTP协议请求的两种方式,主要有如下几个区别:
相对GET安全一些,因为在浏览器中参数会暴露在地址栏