NodeJS의 기본 정적 파일 서버 “js”: “text/javascript”,

완벽한 서버보다는 노드를 이해하기위한 연습으로 nodejs에서 정적 파일 서버를 만들려고합니다. 저는 Connect 및 node-static과 같은 프로젝트에 대해 잘 알고 있으며 더 많은 프로덕션 준비 코드에 해당 라이브러리를 완전히 사용할 계획이지만 작업중인 작업의 기본 사항도 이해하고 싶습니다. 이를 염두에두고 작은 server.js를 코딩했습니다.

var http = require('http'),
    url = require('url'),
    path = require('path'),
    fs = require('fs');
var mimeTypes = {
    "html": "text/html",
    "jpeg": "image/jpeg",
    "jpg": "image/jpeg",
    "png": "image/png",
    "js": "text/javascript",
    "css": "text/css"};

http.createServer(function(req, res) {
    var uri = url.parse(req.url).pathname;
    var filename = path.join(process.cwd(), uri);
    path.exists(filename, function(exists) {
        if(!exists) {
            console.log("not exists: " + filename);
            res.writeHead(200, {'Content-Type': 'text/plain'});
            res.write('404 Not Found\n');
            res.end();
        }
        var mimeType = mimeTypes[path.extname(filename).split(".")[1]];
        res.writeHead(200, mimeType);

        var fileStream = fs.createReadStream(filename);
        fileStream.pipe(res);

    }); //end path.exists
}).listen(1337);

내 질문은 두 가지입니다

  1. 이것이 노드에서 기본 html 등을 만들고 스트리밍하는 “올바른”방법입니까? 아니면 더 나은 / 더 우아하고 / 더 강력한 방법이 있습니까?

  2. 노드의 .pipe ()는 기본적으로 다음을 수행합니까?

.

var fileStream = fs.createReadStream(filename);
fileStream.on('data', function (data) {
    res.write(data);
});
fileStream.on('end', function() {
    res.end();
});

모두 감사합니다!



답변

  • 다음을 제외하고 기본 서버는 괜찮아 보입니다.

    return없는 문.

    res.write('404 Not Found\n');
    res.end();
    return; // <- Don't forget to return here !!
    

    과:

    res.writeHead(200, mimeType);

    해야한다:

    res.writeHead(200, {'Content-Type':mimeType});

  • pipe() , 기본적으로 소스 스트림을 일시 중지 / 재개합니다 (수신기가 더 느린 경우). pipe()함수 의 소스 코드는 다음과 같습니다 . https://github.com/joyent/node/blob/master/lib/stream.js


답변

적을수록 더

프로젝트에서 먼저 명령 프롬프트로 이동하여

$ npm install express

그런 다음 다음과 같이 app.js 코드를 작성합니다.

var express = require('express'),
app = express(),
port = process.env.PORT || 4000;

app.use(express.static(__dirname + '/public'));
app.listen(port);

그런 다음 파일을 저장하는 “공용”폴더를 만듭니다. 먼저 더 어려운 방법으로 시도했지만 시간이 많이 걸리는 항목을 매핑하고 응답 유형 등에 대해 걱정해야하는 MIME 유형에 대해 걱정해야합니다. 감사합니다.


답변

나는 내부에서 무슨 일이 일어나고 있는지 이해하는 것도 좋아합니다.

코드에서 정리하고 싶은 몇 가지 사항을 발견했습니다.

  • 파일 이름이 디렉토리를 가리킬 때 충돌이 발생합니다. 존재가 참이고 파일 스트림을 읽으려고하기 때문입니다. fs.lstatSync를 사용하여 디렉터리 존재를 확인했습니다.

  • HTTP 응답 코드를 올바르게 사용하지 않습니다 (200, 404 등).

  • MimeType이 (파일 확장자에서) 결정되는 동안 res.writeHead에서 올바르게 설정되지 않습니다 (스튜가 지적한대로)

  • 특수 문자를 처리하려면 uri를 이스케이프 해제해야합니다.

  • 맹목적으로 심볼릭 링크를 따릅니다 (보안 문제가 될 수 있음)

이를 감안할 때 일부 아파치 옵션 (FollowSymLinks, ShowIndexes 등)이 더 이해하기 시작합니다. 다음과 같이 간단한 파일 서버의 코드를 업데이트했습니다.

var http = require('http'),
    url = require('url'),
    path = require('path'),
    fs = require('fs');
var mimeTypes = {
    "html": "text/html",
    "jpeg": "image/jpeg",
    "jpg": "image/jpeg",
    "png": "image/png",
    "js": "text/javascript",
    "css": "text/css"};

http.createServer(function(req, res) {
  var uri = url.parse(req.url).pathname;
  var filename = path.join(process.cwd(), unescape(uri));
  var stats;

  try {
    stats = fs.lstatSync(filename); // throws if path doesn't exist
  } catch (e) {
    res.writeHead(404, {'Content-Type': 'text/plain'});
    res.write('404 Not Found\n');
    res.end();
    return;
  }


  if (stats.isFile()) {
    // path exists, is a file
    var mimeType = mimeTypes[path.extname(filename).split(".").reverse()[0]];
    res.writeHead(200, {'Content-Type': mimeType} );

    var fileStream = fs.createReadStream(filename);
    fileStream.pipe(res);
  } else if (stats.isDirectory()) {
    // path exists, is a directory
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.write('Index of '+uri+'\n');
    res.write('TODO, show index?\n');
    res.end();
  } else {
    // Symbolic link, other?
    // TODO: follow symlinks?  security?
    res.writeHead(500, {'Content-Type': 'text/plain'});
    res.write('500 Internal server error\n');
    res.end();
  }

}).listen(1337);

답변

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

var server = http.createServer(function (req, res) {
  res.writeHead(200, { 'content-type': 'text/plain' })

  fs.createReadStream(process.argv[3]).pipe(res)
})

server.listen(Number(process.argv[2]))

답변

파일이 존재하는지 별도로 확인하지 않는이 패턴은 어떻습니까?

        var fileStream = fs.createReadStream(filename);
        fileStream.on('error', function (error) {
            response.writeHead(404, { "Content-Type": "text/plain"});
            response.end("file not found");
        });
        fileStream.on('open', function() {
            var mimeType = mimeTypes[path.extname(filename).split(".")[1]];
            response.writeHead(200, {'Content-Type': mimeType});
        });
        fileStream.on('end', function() {
            console.log('sent file ' + filename);
        });
        fileStream.pipe(response);

답변

@Jeff Ward 답변을 기반으로 일반적인 사용을 위해 추가 기능이있는 httpServer 기능을 만들었습니다.

  1. custtom dir
  2. index.html은 req === dir 인 경우 반환합니다.

용법:

httpServer(dir).listen(port);

https://github.com/kenokabe/ConciseStaticHttpServer

감사.


답변

번째 모듈은 쉽게 정적 파일을 제공합니다. 다음은 README.md에서 발췌 한 것입니다.

var mount = st({ path: __dirname + '/static', url: '/static' })
http.createServer(function(req, res) {
  var stHandled = mount(req, res);
  if (stHandled)
    return
  else
    res.end('this is not a static file')
}).listen(1338)