http
- HTTP协议(HyperText Transfer Protocol,超文本传输协议)是用于从WWW服务器传输超文本到本地浏览器的传输协议。它可以使浏览器更加高效,使网络传输减少。它不仅保证计算机正确快速地传输超文本文档,还确定传输文档中的哪一部分,以及哪部分内容首先显示(如文本先于图形)等。
http请求头
- 四中协议基础:
通用头域、请求消息、响应消息、实体信息;
就是访问每个网页的时候,资源和数据请求的这些各种’头’
请求头包含基本内容
Accept
:浏览器可接受的MIME类型(文字、声音、图像等)。Accept-Charset
:浏览器可接受的字符集(utf-8,ASCII,GB2312等)。Accept-Encoding
:浏览器能够进行解码的数据编码方式,比如gzip。Servlet+ `能够向支持gzip的浏览器返回经gzip编码的HTML页面。许多情形下这可以减少5到10倍的下载时间。Accept-Language
:浏览器所希望的语言种类,当服务器能够提供一种以上的语言版本时要用到。Authorization
:授权信息,通常出现在对服务器发送的WWW-Authenticate头的应答中。Connection
:表示是否需要持久连接。如果Servlet看到这里的值为“Keep-Alive”,或者看到请求使用的是HTTP 1.1(HTTP 1.1默认进行持久连接),它就可以利用持久连接的优点,当页面包含多个元素时(例如Applet,图片),显著地减少下载所需要的时间。要实现这一点,Servlet需要在应答中发送一个Content-Length头,最简单的实现方法是:先把内容写入ByteArrayOutputStream,然后在正式写出内容之前计算它的大小。Content-Length
:表示请求消息正文的长度。Cookie
:这是最重要的请求头信息之一From
:请求发送者的email地址,由一些特殊的Web客户程序使用,浏览器不会用到它。Host
:初始URL中的主机和端口。If-Modified-Since
:只有当所请求的内容在指定的日期之后又经过修改才返回它,否则返回304“Not Modified”应答。Pragma
:指定“no-cache”值表示服务器必须返回一个刷新后的文档,即使它是代理服务器而且已经有了页面的本地拷贝。Referer
:包含一个URL,用户从该URL代表的页面出发访问当前请求的页面。User-Agent
:浏览器类型,如果Servlet返回的内容与浏览器类型有关则该值非常有用。UA-Pixels,UA-Color,UA-OS,UA-CPU
:由某些版本的IE浏览器所发送的非标准的请求头,表示屏幕大小、颜色深度、操作系统和CPU类型。
http状态码
详细请看百度百科
nodejs创建服务
创建监听
const http = require("http");
const server = http.createServer((req,res) => {
res.write("向客户端返回数据")
res.end()//主动终端会话,不然浏览器会一直加载,圈圈一直转
})//require reponse
server.listen(3001)//监听端口
由于没有写请求头,得到的数据是乱码:
请求头
const http = require("http");
const server = http.createServer((req,res) => {
res.writeHead(200,{
"Content-Type":"text/plain;charset=utf-8"
})//设置成功状态码,设置请求头传递的数据编码
res.write("向客户端返回数据")
res.end()//end为可选参数,传递buffer对象或者字符串,会作为结束标志拼接在write的最后,而且end代表上下文结束,后面的代码将没有意义。
})//require reponse
server.listen(3001)
console.log('开启了服务');
至关重要的请求消息
- 我们先看一下一次请求向后台发送了写什么消息:
这一长串滚动条都是请求发送给后台的消息。
- 我们将最重要的一部分打印出来看看:
const http = require("http");
const server = http.createServer((req,res) => {
res.writeHead(200,{
"Content-Type":"text/plain;charset=utf-8"
})
for (const index in req.headers) {
res.write("\n")
res.write(index+":"+req.headers[index])
}
res.end()
})//require reponse
server.listen(3001)
console.log('开启了服务');
拿到路由信息
const http = require("http");
const server =http.createServer((req,res) => {
res.writeHead(200,{
"Content-Type":"text/plain;charset=utf-8"
})
res.end(req.url)
})//require reponse
server.listen(3001)
console.log('开启了服务');
如果我们再通过逻辑代码,通过不同的路由返回不同的信息!是不是突然有种通透的感觉,一个网站不就是这样吗?不然你的fs是学来干嘛的嘛,读取文件嘛,返回utf8字符串嘛,所以说,nodejs的后台非常的轻、简单!
不过这里要注意的是,在设置请求头的时候,如果Content-Type如果依然设置为text/plain,那么返回的字符只会被当做普通txt文本解析,如果改成html就会被解析成html代码了!
const http = require("http");
const server =http.createServer((req,res) => {
res.writeHead(200,{
"Content-Type":"text/html;charset=utf-8"
})
res.end("<h1>hello word</h1>")
})//require reponse
server.listen(3001)
console.log('开启了服务');
如果是ajax请求呢?
- 我们先随便写个html代码:
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<meta http-equiv='X-UA-Compatible' content='IE = edge'>
<title>Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- <link rel="stylesheet" type="text/css" media="screen" href="css/style.css" /> -->
</head>
<body>
<h1 id="app">Hello word</h1>
</body>
<script src="ajax.js"></script>
<script type="text/javascript">
app.onclick = ()=>{
ajax({
url:"http://localhost:3001",
method:"get",
data:{
name:"Lucy",
age:"19"
},
sucess:function(result) {
console.log(result);
}
})
}
</script>
</html>
- 我这里是自己以前封装的ajax,用jQuery的也是一样的,如果你想用我的:
/*
ajax 方法
options 配置信息
*/
function ajax(options) {
options.type = /post/i.test(options.type) ? 'POST' : 'GET';
//console.log( options.type);
//异步或者同步
options.async = options.async === false ? false : true;
/*console.log(options.async)*/
var xhr = new XMLHttpRequest();
var data = ''; //user=韩梅梅&age=18
for (var k in options.data) {
data += k + '=' + encodeURIComponent(options.data[k]) + '&';
}
//是get还是post
if (options.type === 'GET') {
if (!/\?/.test(options.url)) {
options.url += '?';
} else {
if (!/(&\s*)$/.test(options.url)) {
options.url += '&';
}
}
options.url += data + '_=' + new Date().getTime();
data = null;
}
xhr.open(options.type, options.url, options.async);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=UTF-8');
xhr.onreadystatechange = function () {
if (this.readyState === 4) { //0 1 2 3 4
if (this.status > 199 && this.status < 300 || this.status === 304) {
options.success && options.success.call(this, strJsonCode(this.response));
} else {
options.error && options.error.call(this, this.status);
}
}
};
xhr.send(data);
}
//将字符串打包成json数据,打包失败,默认返回原字符串
function strJsonCode(str) {
try {
return JSON.parse(str);
} catch (e) {
return str;
}
}
//时间打包函数
function formatterDateTime() {
var date = new Date()
var month = date.getMonth() + 1
var datetime = date.getFullYear() +
"" // "年"
+
(month >= 10 ? month : "0" + month) +
"" // "月"
+
(date.getDate() < 10 ? "0" + date.getDate() : date
.getDate()) +
"" +
(date.getHours() < 10 ? "0" + date.getHours() : date
.getHours()) +
"" +
(date.getMinutes() < 10 ? "0" + date.getMinutes() : date
.getMinutes()) +
"" +
(date.getSeconds() < 10 ? "0" + date.getSeconds() : date
.getSeconds());
return datetime;
}
- 当前服务端代码;
const http = require("http");
const server =http.createServer((req,res) => {
res.writeHead(200,{
"Content-Type":"text/html;charset=utf-8"
})
const obj = {
name:"Bob",
age:"18"
}
console.log(1);
res.end()
})//require reponse
server.listen(3001)
console.log('开启了服务');
本地打开页面,触发ajax,这里出现了跨域问题
这里的1打印出来了,说明服务端准确地接收到了请求并执行了里面的代码,只是有跨域无法获取到服务器的返回数据:
跨域并不是因为服务器或者代码的问题,它是因为浏览器在中间作祟,浏览器"不同意这门婚事"!
但是,出于安全的考虑,浏览器是默认将没有设置请求头被返回消息的对象时,默认保护服务方。
- 设置请求头的跨域信息:
res.writeHead(200,{
"Content-Type":"text/html;charset=utf-8",
"Access-Control-Allow-Origin": "*"
})
我点击后不再出现跨域问题,而且后台也显示了我触发的次数:
//没错,返回数据就是靠write
res.write(JSON.stringify(obj))
请求代理
- 因为后台没有设置跨域问题,那么默认情况下,或者允许情况下,我可以让远在上海的服务器访问北京的服务器,上海服务器是个代理,上海服务器被黑了,但是因为北京服务器本身地址和端口以及跨域问题,用户没有办法直接获取到,所以北京服务器是安全的!
- 增加一个server.js作为远在上海的服务器:
我把原来的3001端口的服务修改一下:
const http = require("http");
const server =http.createServer((req,res) => {
const obj = {
name:"Bob",
age:"18"
}
console.log(1);
res.write(JSON.stringify(obj))
res.end()
})//require reponse
server.listen(3001)
console.log('开启了服务');
const http = require("http");
const option = {
host: "localhost",
port: 3001,
method: "get",
path: "/"
}
let httpServer = (response)=>{
//request 是作为nodejs后台用于请求的方法
const myreq = http.request(option, res => {
let obj = ""; //外部用于保存从3002端口请求的数据
res.setEncoding("utf8");
res.on("data", chunk => {
console.log(chunk);
obj = chunk
})
res.on("end", () => {
response.end(JSON.stringify(obj)) //将请求的消息发送到传递进来的外部请求对象
})
})
myreq.on("error", err => {
console.log(err);
})
myreq.write("")
myreq.end()
}
const server = http.createServer((req, res) => {
res.writeHead(200, {
"Content-Type": "text/html;charset=utf-8",
"Access-Control-Allow-Origin": "*"
})
httpServer(res);//调用请求函数,将本次外部请求的对象传递过去
}) //require reponse
server.listen(3002) //创建新的服务3002端口
console.log('开启了服务');
一个窗口只能开一个服务:
完美实现服务器代理,保护了源服务器!