Node.js创建第一个应用

Node.js开发的目的就是为了用JavaScript编写Web服务器程序, 在使用Node.js时,不仅仅是在实现一个应用,同时还实现了整个HTTP服务器。在创建Node.js第一个"Hello, World!"应用前,需先了解下Node.js应用是由哪几部分组成的:

  1. 引入require模块: 使用require指令载入Node.js模块
  2. 创建服务器: 服务器可以监听客户端的请求,类似于Apache、Nginx等HTTP服务器
  3. 接收请求与响应请求: 客户端可以使用浏览器或终端发送HTTP请求,服务器接收请求后返回响应数据

HTTP协议

要理解Web服务器程序的工作原理,首先,要对HTTP协议有基本的了解HTTP协议简介

HTTP服务器

开发HTTP服务器程序, 从头处理TCP连接, 解析HTTP是不现实的. 这些工作实际上已经由Node.js自带的http模块帮我们完成了. 应用程序并不直接和HTTP协议打交道, 而是操作http模块提供的requestresponse对象.

request对象封装了HTTP请求,调用request对象的属性和方法就可以得到所有HTTP请求的信息;

response对象封装了HTTP响应,操作response对象的方法,就可以把HTTP响应返回给浏览器;

用Node.js实现一个HTTP服务器程序。首先实现一个最简单的Web程序hello.js,它对于所有请求,都返回Hello world!:

步骤一、引入require模块

const http = require('http');

步骤二、创建服务器

使用http.createServer()方法创建服务器,并使用listen方法绑定8080端口. 函数通过request, response参数来接收和响应数据

const http = require('http');

http.createServer(function (request, response) {

    // 发送 HTTP 头部
// HTTP 状态值: 200 : OK
// 内容类型: text/plain
response.writeHead(200, {'Content-Type': 'text/plain'}); // 发送响应数据 "Hello World"
response.end('Hello World!\n');
}).listen(8080); // 终端打印如下信息
console.log('Server running at http://127.0.0.1:8080/');
'use strict';

// 导入http模块:
const http = require('http'); // 创建http server,并传入回调函数:
const server = http.createServer(function (request, response) {
// 回调函数接收request和response对象,
// 获得HTTP请求的method和url:
console.log(request.method + ': ' + request.url);
// 将HTTP响应200写入response, 同时设置Content-Type: text/html:
response.writeHead(200, {'Content-Type': 'text/html'});
// 将HTTP响应的HTML内容写入response:
response.end('<h1>Hello world!</h1>');
}); // 让服务器监听8080端口:
server.listen(8080); console.log('Server is running at http://127.0.0.1:8080/');
'use strict';

// 导入http模块:
const http = require('http'); // 创建http server,并传入回调函数:
const server = http.createServer((request, response) => {
// 回调函数接收request和response对象,
// 获得HTTP请求的method和url:
console.log(request.method + ': ' + request.url);
// 将HTTP响应200写入response, 同时设置Content-Type: text/html:
response.writeHead(200, {'Content-Type': 'text/html'});
// 将HTTP响应的HTML内容写入response:
response.end('<h1>Hello world!</h1>');
}); // 让服务器监听8080端口:
server.listen(8080); console.log('Server is running at http://127.0.0.1:8080/');

在命令行下运行该文件,可以看到以下输出:

$ node hello.js
Server is running at http://127.0.0.1:8080/

不要关闭命令提示符,直接打开浏览器输入http://localhost:8080,即可看到服务器响应的内容:

同时,在命令提示符窗口,可以看到程序打印的请求消息:

GET: /
GET: /favicon.ico

文件服务器

继续扩展上面的Web程序, 可以设定一个目录,然后让Web程序变成一个文件服务器。要实现这一点,只需解析request.url中的路径,然后在本地找到对应的文件,把文件内容发送出去就可以了。

解析URL需要用到Node.js提供的url模块,它使用起来非常简单,通过parse()将一个字符串解析为一个Url对象:

'use strict';

const url = require('url');

console.log(url.parse('http://user:pass@host.com:8080/path/to/file?query=string#hash'));

结果如下:

Url {
protocol: 'http:',
slashes: true,
auth: 'user:pass',
host: 'host.com:8080',
port: '8080',
hostname: 'host.com',
hash: '#hash',
search: '?query=string',
query: 'query=string',
pathname: '/path/to/file',
path: '/path/to/file?query=string',
href: 'http://user:pass@host.com:8080/path/to/file?query=string#hash'
}

处理本地文件目录需要使用Node.js提供的path模块,它可以方便地构造目录:

'use strict';

const path = require('path');

// 解析当前目录
const workDir = path.resolve('.'); // 组合完整的文件路径:当前目录 + 'static' + 'index.html'
const filePath = path.join(workDir, 'static', 'index.html'); console.log(workDir);
console.log(filePath);
// D:\NodejsApp\middleware\workdir
// D:\NodejsApp\middleware\workdir\static\index.html

使用path模块可以正确处理操作系统相关的文件路径。在Windows系统下,返回的路径类似于C:\Users\Unity\static\index.html,这样,就不必关心怎么拼接路径了。最后,实现文件服务器file_server.js

'use strict';

const fs = require('fs');
const url = require('url');
const path = require('path');
const http = require('http'); // 从命令行参数获取root目录,默认是当前目录
const root = path.resolve(process.argv[2] || '.'); console.log(`Stctic root dir: ${root}`); // 创建服务器
http.createServer((request, response) => {
// 获得URL的path,类似/css/bootstrap.css
const pathname = url.parse(request.url).pathname; // 获得对应的本地文件路径,类似/src/css/bootstrap.css
const filepath = path.join(root, pathname); // 获取文件状态
fs.stat(filepath, (err, stats) => {
if (!err && stats.isFile()) {
// 没有出错并且文件存在
console.log('200' + request.url);
// 发送200响应
response.writeHead(200);
// 将文件流导向response
fs.createReadStream(filepath).pipe(response);
} else {
// 出错或文件不存在
console.log('404' + request.url);
// 发送404
response.writeHead(404);
response.end('404 Not Found');
}
});
}).listen(8080); console.log('Server is running at http://127.0.0.1:8080/');

没有必要手动读取文件内容, 由于response对象本身是一个Writable Stream,直接用pipe()方法就实现了自动读取文件内容并输出到HTTP响应

在命令行运行node file_server.js 然后在浏览器中输入http://localhost:8080/index.html

只要当前目录下存在文件index.html,服务器就可以把文件内容发送给浏览器。观察控制台输出

200 /index.html
200 /css/uikit.min.css
200 /js/jquery.min.js
200 /fonts/fontawesome-webfont.woff2

第一个请求是浏览器请求index.html页面,后续请求是浏览器解析HTML后发送的其它资源请求

练习

在浏览器输入http://localhost:8080/时,会返回404,原因是程序识别出HTTP请求的不是文件,而是目录。请修改file_server.js,如果遇到请求的路径是目录,则自动在目录下依次搜索index.htmldefault.html,如果找到了,就返回HTML文件的内容。

参考源码

http服务器代码(含静态网站)

Create First Application的更多相关文章

  1. kivy Create an application

    http://kivy.org/docs/guide/basic.html#quickstart I followed this tutorial about how to create basic ...

  2. maven command to create your application

    How do I make my first Maven project? We are going to jump headlong into creating your first Maven p ...

  3. Java SE series:1. environment configure and Hello world! [We use compiler and packager to create an application!]

    1. cli (command line interface) and gui (graphic user interface) use javahome path, search classpath ...

  4. [NativeScript] Create new application and run emulator

    Install: npm i -g nativescript Create: tns create <app_name> --ng Run: tns emulate ios List al ...

  5. How do I create an IIS application and application pool using InnoSetup script

    Create an IIS application. Create a new IIS application pool and set it's .NET version to 4. Set the ...

  6. cocos2d-x打飞机实例总结(一):程序入口分析和AppDelegate,Application,ApplicationProtocol三个类的分析

    首先,是个敲代码的,基本上都知道程序的入口是main函数,显然,就算在cocos2d-x框架中也一样 我们看看main函数做了什么 #include "main.h" #inclu ...

  7. 应用程序域(Application Domain)

    应用程序域为隔离正在运行的应用程序提供了一种灵活而安全的方法. 应用程序域通常由运行时宿主创建和操作. 有时,您可能希望应用程序以编程方式与应用程序域交互,例如想在不停止应用程序运行的情况下卸载某个组 ...

  8. 【转】How to view word document in WPF application

    How to view word document in WPF application (CSVSTOViewWordInWPF) Introduction The Sample demonstra ...

  9. Application Pool Identities

    Whether you are running your site on your own server or in the cloud, security must be at the top of ...

随机推荐

  1. 标准库sys

    sys模块的主要函数介绍,结合官方文档说明和实例.This module provides access to some variables used or maintained by the int ...

  2. TCP连接过程及报文解析

    可能大家都听过TCP建立连接时需要经历三次握手和四次挥手的. 那么具体的握手挥手的过程是怎么样的呢? 这篇文章就通过WireShark抓包来了解TCP连接建立和断开的过程. 实验方法: 写一段简单的代 ...

  3. 算法竞赛进阶指南--lowbit运算,找到二进制下所有是1的位

    // lowbit运算,找到二进制下所有是1的位 int H[37]; // 预处理 for (int i = 0; i < 36; i++) H[(1ll << i) % 37] ...

  4. 快速幂 递归&&非递归 模板

    一.递归版快速幂 inline int qpow(int x,int y,int p){ if(y==0) return 1; int z=qpow(x,y>>1,p); z=1ll*z* ...

  5. awk调用date命令

    创建文件date.awk: $ == { cmd = "\"" while (cmd | getline line) { print line } close(cmd) ...

  6. Integer和int及String的总结

    秉承着总结发表是最好的记忆,我把之前遇到的问题在这里总结和大家分享一下,希望大家共同进步: 一.Integer和int首先说下自动拆装箱,基本数据类型转换为包装类型的过程叫装箱,反之则是拆箱,其中最特 ...

  7. Java——集合系列(1)框架概述

    该系列博文会告诉你如何从入门到进阶,一步步地学习Java基础知识,并上手进行实战,接着了解每个Java知识点背后的实现原理,更完整地了解整个Java技术体系,形成自己的知识框架. 集合框架概述 Jav ...

  8. 2019-2020Nowcoder Girl初赛 题解

    题目都不是很难,就是最后一题有点毒瘤 第一题:牛妹爱整除 这个你把一个进制数进行拆分,拆分成若干位,然后在取模,这样会发现如果是x进制的数,那么对x+1这个进制转化即满足条件. 举个例子:一个x进制数 ...

  9. 【FPGA篇章二】FPGA开发流程:详述每一环节的物理含义和实现目标

    欢迎大家关注我的微信公众账号,支持程序媛写出更多优秀的文章 FPGA的开发流程是遵循着ASIC的开发流程发展的,发展到目前为止,FPGA的开发流程总体按照下图进行,有些步骤可能由于其在当前项目中的条件 ...

  10. 深入理解CSS定位—浮动模型

    前面我们讲到了绝对定位,在这篇文章中,我们将讲到3种定位模型中的浮动模型.主要参考 张鑫旭在慕课网的 深入理解float 那些年我们一起清过的浮动---by 一丝丝凉 精通CSS 注意:第二小节基本参 ...