• 技术文章 >web前端 >js教程

    浅析用Node创建一个简单的HTTP服务器

    青灯夜游青灯夜游2022-12-05 18:35:22转载120
    怎么使用NodeJS创建HTTP服务器?下面本篇文章给大家介绍一下使用Node创建一个简单的HTTP服务器的方法,希望对大家有所帮助!

    大前端成长进阶课程:进入学习

    1. 使用Node.js直接运行JavaScript脚本

    node.js基于Chromev8引擎运行js代码,因此我们可以摆脱浏览器环境,直接在控制台中运行js代码,比如下面这个hello world代码

    console.log('hello world');

    控制台中直接使用node即可运行

    1.png


    2. 创建一个简单的HTTP服务器

    node.js的内置模块http提供了基本的http服务的能力,基于CommonJS规范,我们可以使用require导入http模块进行使用http模块中有一个createServer函数能够让我们创建一个http服务器 其接收一个回调函数作为参数,这个回调函数接收两个参数 -- requestresponse。【相关教程推荐:nodejs视频教程

    当我们将响应体处理好了之后,调用response.end()方法就可以将响应体发送给客户端 使用createServer函数只是帮我们创建了一个Server对象,并没有让其开启监听,我们还需要调用server对象的listen方法才可以进行监听,真正作为一个服务器开始运行

    下面是使用http模块创建一个简单服务器的例子

    const { createServer } = require('http');
    const HOST = 'localhost';
    const PORT = '8080';
    
    const server = createServer((req, resp) => {
      // the first param is status code it returns  
      // and the second param is response header info
      resp.writeHead(200, { 'Content-Type': 'text/plain' });  
      
      console.log('server is working...');  
      
      // call end method to tell server that the request has been fulfilled
      resp.end('hello nodejs http server');
    });
    
    server.listen(PORT, HOST, (error) => {  
    if (error) {  
      console.log('Something wrong: ', error);   
       return;
      }  
      console.log(`server is listening on http://${HOST}:${PORT} ...`);
    });

    可以直接尝试用node运行它,创造一个属于你的服务器!服务器运行后,浏览器访问http://localhost:8080即可访问到这个服务器

    2.png

    也可以使用nodemon运行它,这样当我们的代码发生变化的时候就不需要手动终止程序再重新运行了

    npm i -g nodemon

    建议全局安装它,这样就可以直接使用,不需要通过npx nodemon去使用 使用也很简单,直接将node命令改成nodemon命令即可

    nodemon http-server.js

    3.png


    3. 加上类型提示

    前面我们在使用createServer以及resp对象的时候,看不到任何的语法提示,必须随时跟着node官方文档去边用边查,有点不方便 但是没关系,我们可以使用ts.d.ts文件帮助我们提供语法提示功能,注意,我们不是使用ts进行开发,只是使用它的语法提示功能而已

    1. 初始化项目 -- npm init -y
    2. 安装@types/node -- pnpm i @types/node -D
    3. 在项目目录下创建jsconfig.json文件,将node_modules排除在外,没必要对其进行检查
    {  "compilerOptions": {
        "checkJs": true
      },  
      "exclude": ["node_modules", "**/node_modules/*"]
    }

    不知道你是否有发现上面的代码其实是有一处错误的呢?checkJs能够帮助我们检查类型错误问题,可以根据需要选择是否开启 可以看到,开启检查后立马就给我们提示了参数类型不匹配的问题

    4.png

    这时候将鼠标悬浮在listen方法上,就能够看到该方法的签名

    5.png

    可以看到,原来port参数需要是number类型,但是我们定义的时候是string类型,所以没匹配上,将其修改为number8080即可 而且可以直接查看到相关api的文档,不需要打开node官方的文档找半天去查看了


    4. 返回多个字符串的响应体

    前面我们的简单http server中只返回了一句话,那么是否能够返回多句话呢? 这就要用到resp对象的write方法了,end只能够返回一次内容,而是用write方法,我们可以多次写入内容到响应体中,最后只用调用一次end,并且不传递任何参数,只让他完成发送响应体的功能

    const { createServer } = require("http");
    const HOST = "localhost";
    const PORT = 8080;
    
    const server = createServer((req, resp) => {
      resp.writeHead(200, { "Content-Type": "text/plain" });  
      console.log("server is working...");  
      
      // write some lorem sentences
      resp.write("Lorem ipsum dolor sit amet consectetur adipisicing elit.\n");
      resp.write("Omnis eligendi aperiam delectus?\n");
      resp.write("Aut, quam quo!\n");
    
      resp.end();
    });
    
    server.listen(PORT, HOST, (error) => {
      if (error) {    
      console.log("Something wrong: ", error);    
      return;
      }  
      console.log(`server is listening on http://${HOST}:${PORT} ...`);
    });

    这次我们写入了三句话,现在的效果就变成这样啦

    6.png


    5. 返回html

    我们不仅可以返回字符串给浏览器,还可以直接读取html文件的内容并将其作为结果返回给浏览器 这就需要用到另一个Node.js的内置模块 -- fs,该模块提供了文件操作的功能 使用fs.readFile可以异步进行读取文件的操作,但是它不会返回promise对象,因此我们需要传入回调去处理读取到文件后的操作 还可以使用fs.readFileSync进行同步阻塞读取文件,这里我们选择异步读取

    const { createServer } = require("http");
    const fs = require("fs");
    const HOST = "localhost";
    
    const PORT = 8080;const server = createServer((req, resp) => {
      // change the MIME type from text/plain to text/html
      resp.writeHead(200, { "Content-Type": "text/html" });  
      
      // read the html file content
      fs.readFile("index.html", (err, data) => { 
         if (err) {  
          console.error(      
            "an error occurred while reading the html file content: ",
            err
          );      throw err;
        }    
        console.log("operation success!");
    
        resp.write(data);
        resp.end();
      });
    });
    
    server.listen(PORT, HOST, (error) => {
      if (error) {    
      console.log("Something wrong: ", error);    
      return;
      }  
      console.log(`server is listening on http://${HOST}:${PORT} ...`);
    });

    现在的结果就像下面这样:

    7.png

    成功将html返回注意:这里需要将响应头的**Content-Type**改为**text/html**,告知浏览器我们返回的是**html**文件的内容,如果仍然以**text/plain**返回的话,浏览器不会对返回的内容进行解析,即便它是符合**html**语法的也不会解析,就像下面这样:

    8.png


    6. 返回JSON

    当我们需要编写一个后端服务器,只负责返回接口数据的时候,就需要返回json格式的内容了,相信聪明的你也知道该怎么处理了:

    1. MIME类型设置为application/json
    2. resp.write的时候传入的是json字符串,可以使用JSON.stringify处理对象后返回
    const { createServer } = require("http");
    const HOST = "localhost";
    const PORT = 8080;
    
    const server = createServer((req, resp) => { 
     // change the MIME type to application/json
      resp.writeHead(200, { "Content-Type": "application/json" });  
      
      // create a json data by using an object  
      const jsonDataObj = {
          code: 0,    
          message: "success",    
          data: {  
              name: "plasticine",      
              age: 20,      
              hobby: "coding",
        },
      };
    
      resp.write(JSON.stringify(jsonDataObj));
      resp.end();
    });
    
    server.listen(PORT, HOST, (error) => {
      if (error) { 
         console.log("Something wrong: ", error);    
         return;
      }  
      console.log(`server is listening on http://${HOST}:${PORT} ...`);
    });

    结果如下:

    9.png


    7. 返回pdf文件

    和之前返回html文件的思路类似,都是一个设置响应头MIME类型,读取文件,返回文件内容的过程 但是这次我们搞点不一样的 我们的思路是在服务器运行的时候生成一个pdf文件,并将它返回 还需要将MIME的类型改为application/pdf生成pdf文件需要用到一个库 -- pdfkit

    pnpm i pdfkit

    首先我们编写一个创建pdf文件的函数,因为创建pdf文件还需要进行一些写入操作,不确定什么时候会完成,但是我们的请求必须等到pdf文件创建完成后才能得到响应 所以我们需要将它变成异步进行的,返回一个promise

    /**
     * @description 创建 pdf 文件
     */const createPdf = () => {
       return new Promise((resolve, reject) => {
           if (!fs.existsSync("example.pdf")) {      
           // create a PDFDocument object      
           const doc = new PDFDocument();
           
           // create write stream by piping the pdf content.
           doc.pipe(fs.createWriteStream("example.pdf"));   
            
          // add some contents to pdf document
          doc.fontSize(16).text("Hello PDF", 100, 100);   
             
          // complete the operation of generating PDF file.
          doc.end();
        }
    
        resolve("success");
      });
    };

    这里使用到了管道操作,将PDFDocument对象的内容通过管道传到新创建的写入流中,当完成操作后我们就通过resovle告知外界已经创建好pdf文件了 然后在服务端代码中调用

    const server = createServer(async (req, resp) => {
      // change the MIME type to application/pdf
      resp.writeHead(200, { "Content-Type": "application/pdf" });  
      
      // create pdf file  
      await createPdf();  
      
      // read created pdf file
      fs.readFile("example.pdf", (err, data) => {
          if (err) { 
           console.error(        
            "an error occurred while reading the pdf file content: ",
            err
          );      
          throw err;
        }    
        console.log("operation success!");
    
        resp.end(data);
      });
    });
    
    server.listen(PORT, HOST, (error) => {
      if (error) {
          console.log("Something wrong: ", error);    
          return;
      }  
      console.log(`server is listening on http://${HOST}:${PORT} ...`);
    });

    现在浏览器就可以读取到创建的pdf文件了

    10.png


    8. 返回音频文件

    思路依然是一样的,读取一个音频文件,然后通过管道将它送到resp对象中再返回即可

    const { createServer } = require("http");
    const { stat, createReadStream } = require("fs");
    const HOST = "localhost";
    const PORT = 8080;
    
    const server = createServer((req, resp) => {
      // change the MIME type to audio/mpe
      resp.writeHead(200, { "Content-Type": "audio/mp3" });  
      const mp3FileName = "audio.mp3";
    
      stat(mp3FileName, (err, stats) => {
        if (stats.isFile()) {      
          const rs = createReadStream(mp3FileName);      
          
          // pipe the read stream to resp
          rs.pipe(resp);
        } else {
          resp.end("mp3 file not exists");
        }
      });
    });
    
    server.listen(PORT, HOST, (error) => {
      if (error) {    
      console.log("Something wrong: ", error);    
      return;
      }  
      console.log(`server is listening on http://${HOST}:${PORT} ...`);
    });

    效果如下

    11.png

    打开后就是一个播放音频的界面,这是chrome提供的对音频文件的展示,并且打开控制台会发现有返回音频文件

    11-2.png

    注意:将音频文件流通过管道传到**resp**后,不需要调用**resp.end()**方法,因为这会关闭整个响应,导致音频文件无法获取

    12.png

    13.png


    9. 返回视频文件

    视频文件和音频文件的处理是一样的,只是MIME的类型要改成video/mp4,其他都一样

    const { createServer } = require("http");
    const { stat, createReadStream } = require("fs");
    const HOST = "localhost";
    const PORT = 8080;
    const server = createServer((req, resp) => {  
    // change the MIME type to audio/mpe
      resp.writeHead(200, { "Content-Type": "audio/mp4" });  
      const mp4FileName = "video.mp4";
    
      stat(mp4FileName, (err, stats) => { 
         if (stats.isFile()) {      
         const rs = createReadStream(mp4FileName);      
         // pipe the read stream to resp
          rs.pipe(resp);
        } else {
          resp.end("mp4 file not exists");
        }
      });
    });
    
    server.listen(PORT, HOST, (error) => { 
     if (error) {    
     console.log("Something wrong: ", error);    
     return;
      }  
      console.log(`server is listening on http://${HOST}:${PORT} ...`);
    });

    14.png


    总结

    我们学会了:

    虽然内容简单,但还是希望你能跟着动手敲一敲,不要以为简单就看看就算了,看了不代表会了,真正动手实现过后才会找到自己的问题

    更多node相关知识,请访问:nodejs 教程

    以上就是浅析用Node创建一个简单的HTTP服务器的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:掘金社区,如有侵犯,请联系admin@php.cn删除

    Linux系统运维及项目正式上线:点击学习

    专题推荐:Node.js node
    上一篇:手把手带你了解Angular中的依赖注入 下一篇:自己动手写 PHP MVC 框架(40节精讲/巨细/新人进阶必看)

    相关文章推荐

    • ❤️‍🔥共22门课程,总价3725元,会员免费学• ❤️‍🔥接口自动化测试不想写代码?• 聊聊怎么使用Node将Excel转为JSON• 聊聊Node.js中的 GC (垃圾回收)机制• Node学习之聊聊Cookie-Session登录验证的工作原理• Node实战:运用Cookie&Session进行登录验证• 聊聊用pkg将Node.js项目打包为可执行文件的方法
    1/1

    PHP中文网