从零开始创建一个静态服务器

120 阅读3分钟
  • 工具 ts-node-dev 可以用typescript开发node.js程序,会自动重启 tsnd

基本 Api 以及初始化步骤

  1. 新建文件夹
  2. yarn init -y 初始化
  3. 创建 index.js 文件
  4. yarn add --dev @types/node 安装 node 声明文件(typescript)
  5. 引入http模块
  6. 监听 server 的 request 事件
  7. server.listen (8888) 开始监听8888端口
//引入http模块 
import * as http from 'http';
import {IncomingMessage,ServerResponse} from 'http'

cosnt server=http.createServer()
//监听 server 的 request 事件,有人发请求就会触发这个事件
server.on('request',(resquest:IncomingMessage,response:ServerResponse)=>{
		const array=[];
  	//将请求的数据保存在数组中
		request.on('data',(chunk)=>{
  			array.push(chunk:Buffer);
  	])
  	// 请求结束后,将数据打印出来 并且可以设置响应体的各部分
		request.on('end',()=>{
    		const body=Buffer.concat(array).toString();
    		console.log(body);
     
    		response.setHeader('xxx');  // 设置响应头
    		resposne.statusCode=404 ;   // 设置响应的状态码 默认200
    		response.write('');  // 设置响应体内容,这个api可以多次调用
    		response.end('hi');  //响应体内容
  	})
});
//server.listen (8888) 开始监听8888端口
server.listen(8888);
  • sever 是 http.createServer的返回值的实例,它继承自net.server类,常用的有 error事件错误信息,address()事件返回服务器地址
  • request.url 可以得到请求的路径(含查询参数)
  • request.headers 获取请求头
  • request.methods 请求方法,比如get
  • request.on("data") 事件,请求体上传过程中会一直触发data 事件
  • request.on('end') 事件,请求体上传结束后,触发end事件,可以在回调函数中设置响应体的各部分
  • 关于node.js 的 typescript的类型声明并不智能,可以通过 response.constructor来读取类型

目标: 根据url返回不同的文件

服务器端 只解析用户请求中的数据,比如路径,请求体等,并回复响应的response,前端负责发送请求和接收响应

  • public文件夹中一般是需要渲染到客户端的静态页面
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';

cosnt server = http.createServer();
//__driname可以获取当前文件的绝对路径,resolve计算路径
const publicDir = path.resolve('__dirname,'public');   


server.on('request',(resquest:IncomingMessage,response:ServerResponse)=>{
	const {method,url:path,herders} = request;
    const {pathname,search}=url.pasrse(path);

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

server.listen(8888);

目标:处理路径中的查询参数

利用node.js内置的 URL模块

url.parse(路径) 解析路径 可以获得pathname路径 search 等属性

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';

cosnt server = http.createServer();
//__driname可以获取当前文件的绝对路径,resolve计算路径
const publicDir = path.resolve('__dirname,'public');   


server.on('request',(resquest:IncomingMessage,response:ServerResponse)=>{
	const {method,url:path,herders} = request;
    const {pathname,search}=url.pasrse(path);

    if(method!=='GET'){
        response.statusCode=200;
        response.end('这是一个假的响应')
        return;
    }
    
	let filename = pathname.substr(1);
    if (filename===''){
        filename='index.html';
    }
    
    switch(pathname){
        case '/index.html' :
            response.setHeader('Content-Type','text/html; charser=utf-8')
            fs.readFild(path.resolve(publicDir,filename),(error,data)=>{
                if(error.errno===-4058){
                    response.statusCode=404;
                    fs.readFile(path.resolve(publicDir,'404.html'),(error,data)={
                        responsr.end(data);
                    });
                }else if (error.errno === -4068){
                    response.statusCode=403;
                    response.end('服务器繁忙,请稍后再试')
                }
                if(error) {
                    response.statusCode=5000;
                    response.end('服务器繁忙,请稍后再试');
                }else{
                    // 设置缓存
                    response.setHeader('Cache-Control','public,max-aeg-31536000') 
                    response.end(data.toString());
                }
            })
        	break;
    }
});

server.listen(8888);

目标:处理非get 请求