HTTP超文本传输协议

let http = require('http');        // 导入http模块

HTTP协议构建就是在请求和响应上,由http.ServerRequest和http.ServerResponse构造出来的

http.createServer(function(req, res){
    if(req.url === '/login'){
        res.writeHead(200, {'Content-Type': 'text/html' });
        res.end('<div>login</div>');
    }
    else if(req.url === 'main' && req.method === 'POST'){
        res.writeHead(200, {'Content-Type': 'text/html' });
        res.end('Hello <b>post</b>');
    }
}).listen(3030)

http.server类

是一个创建服务的类 ServerRequest()

方法:

    1、close([callback]): 停止服务器连接

    2、listen(path, [callback]): 侦听, 与TCP使用方法相同

属性:

    1、listening: 返回是否在监听连接服务器的布尔值

    2、maxHeadersCount: 限制最大的请求头数据,默认2000

    3、keepAliveTimeout

    3、setTimeout(msecs, callback): 为socket设置超时值,如果一个超时发生

事件

    1、connect - 请求时触发


Example:

    const HOST = '127.0.0.1';
    const PORT = 3000;

    // 创建服务器
    let server = http.createServer((req, res) => {
        console.log('请求方式:', request.method);       // 请求方式
        console.log('请求url:', request.url);          // 请求url
        console.log('请求头:', request.headers);       // 请求头

        res.writeHead(200);
        res.end('hello world');    
    })            

    // 侦听3000端口
    server.listen(PORT, HOST, ()=> {
        console.log(`server running at http://${hostname}:${port}`);
    })

Request类

url - 返回url地址

method - 返回请求方法

headers - 请求头

Response类

// 这里res返回的就是ServerResponse类
const server = http.createServer((req, res) => { ..... });   

方法:

1、addTrailers(headers)

2、end([data],[encoding],[callback]) - 告诉服务器所有响应头和主体都已被发送,等同于response.write()

3、finished: 

4、getHeader(name): 

5、headersSent: 返回消息头是否被发送,发送为true否则false

6、removeHeader(name): 移出一个头消息 response.removeHeader('Content-Encoding');

7、sendDate: 如果设置为true消息头存在日期消息头则自动生成并且响应在发送

8、setHeader(name, value): 设置头信息

    response.setHeader('Content-Type', 'text/html');
    response.setHeader('Set-Cookie', ['type=ninja', 'language=javascript']);

9、setTimeout(msecs, callback): 设置 socket 的超时时间

10、statusCode: 设置向客户端响应的状态码  res.statusCode = 200;

11、statusMessage

12、write(chunk[, encoding][, callback])

13、writeContinue()

14、writeHead(statusCode[, statusMessage][, headers]): 发送一个响应头给请求

    writeHead(状态码, [状态消息], {响应头信息})

    Example: res.writeHead(200, { content-Type: 'text/html', Connection: 'keep-alive'})

15、setEncoding(编码): 设置编码格式 res.setEncoding('utf8');


res.connection

事件:

    1、close - 关闭连接,会自动调用response.end();

    2、finish - 当响应已被发送时触发

http.IncomingMessage 类

const server = http.createServer((req, res) => { ..... });  就是req返回的类

1、headers: 客户端的请求头

2、method: 获取请求方式

3、url: 请求url

4、statusCode: 状态码

5、statusMessage: 状态消息

6、socket: 与连接有关的 net.Socket 对象。

7、destroy([error])

8、httpVersion: http的版本

9、rawHeaders

10、rawTrailers

11、setTimeout(msecs, callback)

12、trailers

http.createServer(): 创建server服务

http.get(options, [callback]): 用来模拟客户端向服务器发送请求

Example: 请求nodejs.org的index.json文件,返回json的内容

const http = require('http');

http.get('http://nodejs.org/dist/index.json', (res) => {
    const statusCode = res.statusCode;
    const contentType = res.headers['content-type'];

    let error;
    if (statusCode !== 200) {
        error = new Error(`请求失败。\n` + `状态码: ${statusCode}`);
    } else if (!/^application\/json/.test(contentType)) {
        error = new Error(`无效的 content-type.\n` + `期望 application/json 但获取的是 ${contentType}`);
    }
    if (error) {
        console.log(error.message);
        // 消耗响应数据以释放内存
        res.resume();
        return;
    }

    res.setEncoding('utf8');
    let rawData = '';
    res.on('data', (chunk) => rawData += chunk);
    res.on('end', () => {
        try {
            let parsedData = JSON.parse(rawData);
            console.log(parsedData);
        } catch (e) {
            console.log(e.message);
        }
    });
}).on('error', (e) => {
    console.log(`错误: ${e.message}`);
});

http.request(options, [callback]): 模拟HTTP请求

options:

    protocol <String> 使用的协议。默认为 'http:'。

    host <String> 请求发送至的服务器的域名或 IP 地址。默认为 'localhost'。

    hostname <String> host 的别名。为了支持 url.parse(),hostname 优于 host。

    family <Number> 当解析 host 和 hostname 时使用的 IP 地址族。 有效值是 4 或 6。当未指定时,则同时使用 IP v4 和 v6。

    port <Number> 远程服务器的端口。默认为 80。

    localAddress <String> 要绑定到网络连接的本地接口。

    socketPath <String> Unix 域 Socket(使用 host:port 或 socketPath 的其中之一)。

    method <String> 一个指定 HTTP 请求方法的字符串。默认为 'GET'。

    path <String> 请求的路径。默认为 '/'。 应包括查询字符串(如有的话)。如 '/index.html?page=12'。 
    当请求的路径中包含非法字符时,会抛出异常。 目前只有空字符会被拒绝,但未来可能会变化。

    headers <Object> 一个包含请求头的对象。

    auth <String> 基本身份验证,如 'user:password' 来计算 Authorization 头。

    agent <http.Agent> | <Boolean> 控制 Agent 的行为。 当使用 Agent 是,请求默认为 Connection: keep-alive。 可能的值有:
    undefined (默认): 对该主机和端口使用 http.globalAgent。

    Agent 对象:显式地使用传入的 Agent。

    false: 不对连接池使用 Agent,默认请求 Connection: close。

    createConnection <Function> 当不使用 agent 选项时,产生一个用于请求的 socket/stream 的函数。 这可以用于避免创建一个自定义的 Agent 类,只是为了覆盖默认的 createConnection 函数。详见 agent.createConnection()。

    timeout <Integer>: 一个数值,指定 socket 超时的毫秒数。 它会在 socket 被连接时设置超时。


Example:

    var postData = querystring.stringify({
        'msg' : 'Hello World!'
    });

    var options = {
        hostname: 'www.google.com',
        port: 80,
        path: '/upload',
        method: 'POST',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
            'Content-Length': Buffer.byteLength(postData)
        }
    };

    var req = http.request(options, (res) => {
        console.log(`STATUS: ${res.statusCode}`);
        console.log(`HEADERS: ${JSON.stringify(res.headers)}`);
        res.setEncoding('utf8');
        res.on('data', (chunk) => {
            console.log(`主体: ${chunk}`);
        });
        res.on('end', () => {
            console.log('响应中已无数据。');
        });
    });

    req.on('error', (e) => {
        console.log(`请求遇到问题: ${e.message}`);
    });

    // 写入数据到请求主体
    req.write(postData);
    req.end();

http概念

1、请求方法:

    Get: 请求从服务器获取数据,没有请求体,不会影响服务器数据

    Post: 从服务器获取数据,有请求体,会影响服务器端的数据

    DELETE: 从服务器删除资源

    HEAD: 向服务器获取响应头,不要响应体

    PUT: 要新的服务器一个资源

    OPTIONS: 获取服务器支持的方法


2、文件类型 Content-type

    html: text/html

    ASCII文本: text/plain

    jpeg图片: image/jpeg

    GIF图片: image/gif

    javascript: text/javascript

    css: text/css

    表单: application/x-www-form-urlencoded



# 获取 index.html 文件内容返回给客户端

    var http = require('http');
    var fs = require('fs');

    exports.createServer2 = function(){
        var server = http.createServer(function(request, response){
        var url = request.url;

            // 获取 index.html 文件内容返回给客户端
            fs.readFile('./index.html', 'utf-8', function(err, data){
                console.log(err, data);
                response.write(data);
                response.end();
            })
        });
        server.listen(8081, 'localhost');
    }


# 处理Get请求的参数

    var server = http.createServer(function(request, response){
            var oUrl = url.parse(request.url, true);

            console.log(oUrl.query);        // { username: 'siguang', age: '30' }

            var urlQuery = oUrl.query;
            if(urlQuery){
                    response.write('服务器接收GET请求参数成功\n')
                    response.write('用户名:'+ urlQuery.username +'\n');
                    response.write('年级:'+ urlQuery.age +'\n');
            }
            else{
                    response.write('服务器接收参数失败');
            }
            response.end();
    });

    server.listen(8081, 'localhost');


# 处理POST请求

    if(urlObj.pathname == '/register'){           // 处理 '/clock' 的请求
        var str = '';
        var userList = {};

        // 通过on来侦听 data事件, data事件就是接收客户端传输过来的事件, 用可接收post的数据
        request.on('data', function(data){
            console.log(data.toString());          // 返回的是 Buffer
            str += data.toString();
        })

        // 所有接收完成后处理接收数据
        request.on('end', function(data){
            userList = JSON.parse(str);

            response.writeHead('200', {'Content-Type': 'text/html;charset=utf-8'});
            if(userList.username == 'aaa' && userList.password == 'ssssss'){
                    response.end(JSON.stringify({"res":true,"message":"注册成功"}));        // 这里一定要用JSON.stringify来转成串
            }
            else{
                response.end(JSON.stringify({'res':false,'message':'注册失败'}));
            }
            response.end();
        })
    }

    注意:

    1、客户端发送ajax请求时

        如果data是字符串,接收过来就是 '{'username': 'aaa', 'password': 'ssssss'}' 字符串可以直接转成json,

        如果data传的是一个对象,jquery会转成"{'username'='aaa'&'password'='ssssss'}", 还需要node重组

http概念

1、up 工具 通过nodeAPI来监听文件或目录下所有文件,如果有文件改变不需要重启服务器

    $ sudo npm i up -g   

    运行命令: up -watch -port 8080 server.js