Node-http模块2

560 阅读3分钟

`---

主题列表:juejin, github, smartblue, cyanosis, channing-cyan, fancy, hydrogen, condensed-night-purple, greenwillow, v-green, vue-pro, healer-readable, mk-cute, jzman, geek-black, awesome-green

贡献主题:github.com/xitu/juejin…

theme: juejin highlight:

前面一篇文章大概了解了http模块的基本框架。接下来深入了解:

1. 如何根据不同的url请求不同的文件

这是我们目前的目录结构。在public中的三个文件,需要被请求。而且html引用了css和js。

import * as http from 'http';
import {IncomingMessage, ServerResponse} from 'http';
import * as fs from 'fs';
import * as path from 'path';
import * as url from 'url';

const server=http.createServer()

server.on('request',(request: IncomingMessage,response:ServerResponse)=>{
    const publicDir=path.resolve(__dirname,'public')
    const {url:myUrl}=request
    console.log(myUrl);
    const {pathname}=url.parse(myUrl)

    switch(pathname){
        case '/index.html':
            response.setHeader('Content-Type','text/html;charset=utf-8')
            fs.readFile(path.resolve(publicDir,'index.html'),(err,data)=>{
                if(err) throw err;
                response.end(data.toString())
            })
            break;
        case '/style.css':
            response.setHeader('Content-Type','text/css;charset=utf-8')
            fs.readFile(path.resolve(publicDir,'style.css'),(err,data)=>{
                if(err) throw err;
                response.end(data.toString())
            })
            break;
        case '/main.js':
            response.setHeader('Content-Type','text/javascript;charset=utf-8')
            fs.readFile(path.resolve(publicDir,'main.js'),(err,data)=>{
                if(err) throw err;
                response.end(data.toString())
            })
            break;
        default:
            response.statusCode=404
            response.end('Not Found')
    }
})

server.listen(8888)

当然首先必须监听server的request事件,在回调里,可以通过request对象的url属性,获取请求的路径。比如如果我在浏览器输入http://localhost:8888/index.htmlrequest.url === /index.html 所以通过条件判断request.url 分情况返回不同的文件内容:

  1. 首先文件的类型各有不同,通过response.setHeader 设置文件类型。
  2. 怎么获取文件里的内容并且响应回去呢?首先要读文件内容:这里用到了另一个模块fs 文件模块。fs.readFile的第一个参数是文件路径,第二个参数是回调:接受err和data,这个data是buffer类型的。所以我们拿到了文件内容,使用response.end返回。

fs模块是文件系统,用于与文件系统进行交互。

找路径的时候用到了另一个模块path,用于处理文件和目录的路径。path.resolve()用于将多个路径序列合并成绝对路径,因为我们不确定路径连接用/还是\,所以用resolve连接很方便。

node中的__dirname变量表示当前文件所在的目录的绝对路径

2. 请求url中有查询参数怎么办

如果我在浏览器输入http://localhost:8888/index.htmlrequest.url === /index.html 这没有问题。但是如果我带了查询参数呢?http://localhost:8888/index.html?age=18 发现此时request.url === /index.html?age=18 怎么获取干净纯粹的文件路径呢?

用到了url模块:用于处理与解析 URL

url.parse(myUrl) myUrl就是request.url ,也就是/index.html?age=18这样一段字符串。得到一个对象:可以看到这个对象有个pathname属性,就是我们想要的

3. webstorm中将目录设置为根目录的使用

这是目前的目录结构。写了一个404.html,作为404页面,当用户请求的路径不存在,就显示它。在404.html里,用了一张图片:

<body>
    <h1>你要找的页面不存在</h1>
    <p>
        <img src="./images/404.png" alt="">
    </p>
</body>

使用相对路径设置src属性。

// index.ts
fs.readFile(path.resolve(publicDir,filename),(err,data)=>{
        if(err){
            if(err.errno===-4058){
                response.statusCode=404
                fs.readFile(path.resolve(publicDir,'404.html'),(err,data)=>{
                    response.end(data)
                })
            }else{
                response.statusCode=500
                response.end('服务器繁忙')
            }

        }else{
            response.end(data)
        }
    })

在node运行的文件index.ts里,如果错误码是-4058,就是用户请求的路径不存在,就返回404.html

如果我请求:http://localhost:8888/x.html 明显路径不存在,此时页面会正确显示404及图片。

但是如果请求的路径里又多了一层目录,比如:http://localhost:8888/xxx/x.html

发现图片显示不了!我们打开Network,发现对404.png的请求路径变成了目录xxx里的images/404.png 。但是images/404.png明明是在public目录里啊!

这是因为src写的是相对路径:<img src="./images/404.png" alt=""> 所以当我多加了一层目录xxx ,就会请求xxx/images/404.png

写绝对路径就好了<img src="/images/404.png" alt=""> 然后再把目录public变成/ 也就是当前的根目录:鼠标移到public,右键,Mark Directory as Resource Root

之后不管我请求多少个目录里的不存在路径,404.png的请求src就永远是public里的images/404.png