노드로.js 웹 프레임워크 쓰기 (3)

5079 단어
보충1:1의 디자인은 로그 시스템이 부족한 것이 분명하다. 여기에 간단한 것을 보충하고 나중에 보완한다:logger.js
exports.setDevMode = function(mode){
    devMode = mode;
}

exports.log = function(msg){
    if(devMode){
        console.log(msg);
    }
}

var devMode = true;
보충 2:
Dispatcher의 논리를 보완했습니다.
/aaa/bb'상황, 대응하는 것을 찾지 못하면./modules/aaa/views.js의 bbb() 함수는./views.js의aa() 함수,'bbb'를 첫 번째 매개 변수로 이 함수에 전송합니다.
추가 3: 현재 디렉토리의 구조와 모든 파일에 대해 설명합니다.
/server.js--------------------------- 메인 파일 (사실은 아무것도 없습니다. 서버를 시작하고 Dispatcher를 연결하는 것)/dispatcher입니다.js----------------Dispathcer 논리 부분/logger.로그 섹션/utils.js--------------------------------------------------------------------------------------------------------------------------------------------------------------------------js---------------------------------------------------------------------------------------------------/views.js-----------------------------루트views 파일, 시리즈 2의 소개/modules----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------js-----모듈article의views 파일
실제로 디자인에서 Django의 조직 구조를 참고했습니다.
다음은 본문입니다. 오늘 실현된 것은 정적 파일 시리즈입니다.논리는 복잡하지 않지만 내용은 매우 많다.
정적 파일 요청이 오면 (예를 들어 요청 xxx.js/xx.css/xx.html 또는 xx.mp3 등) 정적 파일 경로에 이 정적 파일이 포함되어 있는지 확인하고 되돌아오면 됩니다.
여기서는 브라우저가 정적 파일을 정확하게 열 수 있도록 되돌릴 때 MIME type 헤더를 써야 하기 때문에 MIME type 테이블이 필요합니다.
var STATIC_TYPES = {
	'css'	: 'text/css',
  	'gif'	: 'image/gif',
  	'html'	: 'text/html',
  	'ico'	: 'image/x-icon',
  	'jpeg'	: 'image/jpeg',
  	'jpg'	: 'image/jpeg',
  	'js'	: 'text/javascript',
  	'json'	: 'application/json',
	'mp3'	: 'audio/mpeg',
  	'pdf'	: 'application/pdf',
  	'png'	: 'image/png',
  	'svg'	: 'image/svg+xml',
  	'swf'	: 'application/x-shockwave-flash',
  	'tiff'	: 'image/tiff',
  	'txt'	: 'text/plain',
  	'wav'	: 'audio/x-wav',
  	'wma'	: 'audio/x-ms-wma',
  	'wmv'	: 'video/x-ms-wmv',
  	'xml'	: 'text/xml'
};
이것은 결코 완전하지 않아서 잠시 쓰기에 부족하다.표준 참조:http://www.iana.org/assignments/media-types/index.html
다음은 리퀘스트에 필요한 파일의 접두사를 검사하는 것입니다. 이것은 간단합니다. 하나의 정규로 해결됩니다.그리고 파일이 존재하는지 확인하고, 존재하면 파일로 돌아가고, 그렇지 않으면 다음 단계를 수행하면 됩니다.코드:
/**
 * Try to response a static file.
 */
function handleStatics(req, res){
	// check whether request has extension.
	var extension = req.url.match(/\.\w+$/);
	if(!extension){
		return false;
	}
	var path = './' + option.staticPath + req.url;
	if(fs.existsSync(path)){
		fs.readFile(path, 'binary', function(err, file){
			if(err){
				throw err;
			}else{
				var contentType = STATIC_TYPES[extension.slice(1)] || 'text/plain';
				res.writeHead(200, {ContentType : contentType});
				res.write(file, 'binary');
				res.end();
			}
		});
		return true;
	}else{
		return false;
	}
}
여기서 파일이 동기화되었는지 검사하고 나중에 상황을 봐서 비동기식으로 바꿔야 할지 고민합니다(이러면 비동기화가 아파요...)
다음은 파일을 써서 시험해 봅시다:/static/test.html
<!Doctype html>
<html>
	<head>
		<meta charset="utf-8">
		<title>test</title>
	</head>
	<body>
		<h1>Hello!</h1>
	</body>
</html>
그리고 서버를 열고 시험해 보세요:localhost:8080/test.html, ok 성공.
여기에 HTTP 프로토콜에 익숙한 사람들은 캐시 파일이 전혀 없기 때문에 나를 뿌릴 것이다.HTTP 상태는 클라이언트에게 이 파일이 바뀌지 않았다는 것을 알려주기 위해 클라이언트 캐시를 사용하면 된다.
HTTP 헤더에 Expires, Cache-Control, Last-Modified 세 가지를 추가하여 캐시 시간을 표시하고 파일이 수정되었는지 확인해야 합니다.
/**
 * Try to response a static file.
 */
function handleStatics(req, res){
	// check whether request has extension.
	var extension = req.url.match(/\.\w+$/);
	if(!extension){
		return false;
	}
	var path = './' + option.staticPath + req.url;
	if(fs.existsSync(path)){
		fs.readFile(path, 'binary', function(err, file){
			if(err){
				throw err;
			}else{
				var lastModified = fs.statSync(path).mtime.toUTCString();
				if(req.headers['If-Modified-Since'] 
				   && lastModified == req.headers['If-Modified-Since']){
					res.writeHead(304, "Not Modified");
					res.end();
				}else{
					var contentType = STATIC_TYPES[extension.slice(1)] || 'text/plain';
					var expires = new Date(new Date().getTime() + option.maxAge).toUTCString();
					var cacheControl = 'max-age=' + option.maxAge / 1000;
					
					res.writeHead(	200, 
									{
										'ContentType' 	: contentType,
										'Expires'		: expires,
										'Cache-Control'	: cacheControl,
										'Last-Modified'	: lastModified
									});
					res.write(file, 'binary');
					res.end();
				}
			}
		});
		return true;
	}else{
		return false;
	}
}
됐어, 큰 공을 세웠어.

좋은 웹페이지 즐겨찾기