node.js——http和服务、服务代理、后台跨域

本文介绍了HTTP协议的基本概念,包括请求头和状态码,并详细讲解了如何使用Node.js创建HTTP服务,监听请求,处理路由信息。特别讨论了在处理AJAX请求时可能出现的跨域问题及解决方案,通过设置请求头解决跨域限制。同时阐述了请求代理的概念,展示如何设置一个代理服务器来保护源服务器。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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('开启了服务');

在这里插入图片描述

一个窗口只能开一个服务:
在这里插入图片描述

完美实现服务器代理,保护了源服务器!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

奔跑的飞牛

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

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

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

打赏作者

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

抵扣说明:

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

余额充值