고정 Content Server, NodeJ 프레임 없음


Nodejs가 있는 정적 서버
이 자습서는 NodeJ만 사용하여 정적 콘텐츠에 대한 간단한 http 서버를 설정하는 몇 가지 절차를 소개합니다.파일이나 메모리(캐시)에서 요청한 자원을 제공하고 사용할 수 있는 자원이 없을 때 오류 메시지로 응답하는 등 기본 기능을 추가할 것입니다.
실제로, 당신은 이러한 방식으로 http 서버를 거의 영원히 실행하지 않지만, Expressjs와 같은 프레임워크가 백엔드에서 무엇을 하는지 이해하는 것이 매우 도움이 될 것입니다.그것은 또한 매우 간단한 테스트 도구로 로컬 환경에서 사용할 수 있습니다.
업데이트된 버전(12+)을 사용하려면 시스템에 nodejs을 설치해야 합니다.권장되는 환경은 클래스 Unix 시스템이지만 필수는 아닙니다.대상 시청자는 자바스크립트 초보자나 UI 개발자입니다. http 서버가 nodejs에서 어떻게 작동하는지 알고 싶습니다.
다음과 같은 작업을 수행합니다.
  • 설정 http 서버, 정적 서버
  • 요청 읽는 방법 추가 규칙
  • 리소스 및 캐시 찾기

  • 가장 쉬운 문제부터 시작해보도록 하겠습니다.
    Http 서버는 네트워크 트래픽을 수신하는 네트워크 응용 프로그램입니다.이것은 일부 시스템 자원을 획득함으로써 실현된 것이다.구체적으로 말하면, 이것은 메모리에 프로세스를 만들고, 전용 포트에서 네트워크를 통해 전송되는 데이터를 감청한다.http 서버와 통신하기 위해서, 우리는 컴퓨터의 물리적 주소와 응용 프로그램이 가져온 포트가 필요하다.Nodejs는 필요한 모든 기능을 제공합니다.nodesj가 어떻게 이 점을 해냈는지 봅시다.
    nodejs를 사용하여 가장 기본적인 http 서버를 시작하고 실행하는 가장 간단한 방법은 다음과 같습니다.
    node -e "require('http').createServer((req, res) => {res.end('hello world')}).listen(3000)"
    
    노드가 설치된 Linux 시스템에서 이 코드를 실행하면 서버가 시작됩니다.
    브라우저 URL 표시줄에 http://localhost:3000을 입력하여 확인할 수 있습니다.
    또는 새 터미널 창에 다음을 입력합니다.
    > curl http://localhost:3000
    // expected response is
    hello world
    
    이 기본적인 예에서 우리는 건축의 돌을 쉽게 볼 수 있다.대상을 만들고 listen을 호출합니다. 지정한 포트의 연결을 효과적으로 열고 HTTP 프로토콜에 맞는 전송 요청을 기다립니다.
    HTTP GET 요청 헤더에 맞는 텍스트를 netcat으로 보내서 테스트할 수 있습니다.
    printf "GET / HTTP/1.1\r\n\r\n" | nc 127.0.0.1 3000
    // The expected response is again
    HTTP/1.1 200 OK
    Date: Tue, 21 Sep 2021 09:59:13 GMT
    Connection: keep-alive
    Keep-Alive: timeout=5
    Content-Length: 11
    
    hello world%
    
    넷캣은 응답 헤더를 포함한 거의 모든 내용을 출력하기 때문에 더 풍부하다.curl도 할 수 있다.-i 로고를 계속 사용해 보십시오.createServer()listen()을 제외한 또 다른 주요 구성 요소는 createServer으로 전송되는 리셋이다.그것은 requestresponse의 대상에 대한 인용을 포함한다.이 두 대상을 사용하면 우리는 http 서버와 상호작용을 할 수 있다.
    그러나 본고는 네트워크와 프로토콜에 관한 것이 아니라 nodejs만 사용하여 간단한 정적 내용 서버를 구축하는 방법에 대한 강좌입니다. 이것은 우리로 하여금 너무 멀리 가지 못하게 합니다. 왜냐하면 모든 요청에 응답하기 때문입니다.더 잘할 수 있는지 봅시다.

    파일에서 응답
    새로운 http 서버의 기능에 대해 좀 더 진일보합시다.우리의 목표는 정적 내용을 제공할 수 있는 서버다.여기의static라는 단어는 자바스크립트의'static'키워드와 유사하다.그것은 사용자가 요청하기 전에 이미 알고 정의한 것이다.웹 서버에서 우리는 보통 정적 내용을 이미지, 아이콘, CSS 파일 등 파일이라고 부른다.따라서 하드코딩이 아닌 서버 사용자에게 파일 내용을 보냅니다.
    module.exports = function staticServer() {
      const path = './static_content';
      const port = 3000;
    
        // create server object as in previous example
        var server = http.createServer(function(req, res){
        const filePath = path + 'index.html';
        fs.readFile(absPath, function(err, data) {
          res.end(data);
        });
        });
    
      server.listen(port, function() {
        console.log("server listening on port: " + port));
      });
      return server;
    };
    
    또한 컨텐츠가 포함된 디렉토리 및 파일 ./static_content/index.html을 만듭니다.
    <html>
      <body>
        <h1>
          Hello, this is very simple
        </h1>
      </body>
    </html>
    
    위 코드에서 정적 내용이 있는 경로를 정의했습니다. 이 예에서는 색인입니다.html 파일은 저희가 파일을 읽고 데이터를 사용자에게 보내서 고객의 요구에 대한 응답으로 합니다.response.end() executes the above with some [default headers]()
    검색 및 서비스 요청 리소스
    사용자 요청에 따라 내용을 제공하는 작업 중 다음 단계는 사용자가 요청한 요청 자원을 찾는 것입니다.서버에서 이 파일을 찾습니다. 이 파일이 존재하면 클라이언트에게 이 파일의 내용을 제공합니다.
    module.exports = function staticServer() {
      const path = './static_content';
      const port = 3000;
    
        // create server object as in previous example
        var server = http.createServer(function(req, res){
        // get the resource from request
        const filePath = path + req.url;
        fs.readFile(absPath, function(err, data) {
          res.end(fileContents);
        });
        });
    
      server.listen(port, function() {
        console.log("server listening on port: " + port));
      });
      return server;
    };
    
    const filePath = path + req.url은 요청한 자원과 실제 자원 사이의 매핑이 어떻게 작동하는지 보여 준다.Path은 우리의 nodejs 응용 프로그램이 실행되는 위치의 상대적인 경로이고 req.url은 사용자가 원하는 자원을 표시하는 URI의 마지막이다.
    http://www.example.com/**resource**

    캐시
    우리 작은 덧셈을 하나 합시다.캐시디스크에서 파일을 보낼 때, 이것은 결코 큰 문제가 되지 않는다. 왜냐하면 매우 빠르기 때문이다. 그러나 만약 파일이 시간이 더 비싼 자원에서 온다면, 우리는 파일의 내용을 보존하여 이후의 요구에 대비하기를 바란다.다음은 매우 간단한 예로서 이를 어떻게 실현하는지 설명한다.
    module.exports = function staticServer() {
      const path = './static_content';
      const port = 3000;
    
      const cache = {}
    
        // create server object as in previous example
        var server = http.createServer(function(req, res){
        // get the resource from request
        const filePath = path + req.url;
        if (cache[filePath]) {
          sendFile(res, filePath, cache[filePath]);
        } else {
          fs.readFile(filePath, function(err, data) {
            res.end(fileContents);
          });
        }
        });
    
      server.listen(port, function() {
        console.log("server listening on port: " + port));
      });
      return server;
    };
    

    기본 오류 처리 및 요약
    마지막 절에서 우리는 간단한 오류 처리를 추가했다.정적 내용의 주어진 위치에서 찾을 수 없는 자원을 지정하거나 읽을 수 없는 자원을 지정하면 오류를 알려야 합니다.이 동작을 실행하는 표준 방법은 응답 헤더에서 404의 응답을 되돌려 주는 것입니다.우리는 또 내용에 약간의 해석을 추가할 수 있다.
    let 
        fs = require('fs'),
        path = require('path'),
        http = require('http');
    
    const cache = {};
    
    /**
     * lookup content type
     * infer from the extension
     * no extension would resolve in "text/plain"
     */
    function lookupContentType(fileName) {
      const ext = fileName.toLowerCase().split('.').slice(1).pop();
      switch (ext) {
        case 'txt':
          return 'text/plain';
        case 'js':
          return 'text/javascript'
        case 'css':
          return 'text/css'
        case 'pdf':
          return 'application/pdf';
        case 'jpg':
        case 'jpeg':
          return 'image/jpeg';
        case 'mp4':
          return 'video/mp4';
        default:
          return ''
      }
    }
    
    
    /**
     * plain 404 response
     */
    function send404(res){
        res.writeHead(404, {'Content-Type':'text/plain'});
        res.write('Error 404: resource not found.');
        res.end();
    }
    
    /**
     * sending file response
     */
    function sendFile(res, filePath, fileContents){
        res.writeHead(200, {"Content-Type": lookupContentType(path.basename(filePath))});
        res.end(fileContents);
    }
    
    /**
     * serve static content
     * using cache if possible
     */
    function serveStatic(res, cache, absPath) {
      // use cache if there is any
        if (cache[absPath]) {
            sendFile(res, absPath, cache[absPath]);
        } else {
            fs.exists(absPath, function(fileExists) {
          // attempt to read the resource only if it exist
                if (fileExists) {
                    fs.readFile(absPath, function(err, data){
              // not able to read the resource
                        if(err) {
                            send404(res);
                        } else {
                            cache[absPath] = data;
                            sendFile(res, absPath, data);
                        }
                    });
                } else {
            // resource does not exist
                    send404(res);
                }
            });
        }
    }
    
    module.exports = function startServer(spec){
      let { path, port } = spec;
    
        // create server object
        var server = http.createServer(function(req, res){
        // if no resource is specified use index.html
            if(req.url === '/') {
                const filePath = path + 'index.html';
          serveStatic(res, cache, filePath);
            } else {
          const filePath = path + req.url;
          serveStatic(res, cache, filePath);
            }
        });
    
      server.listen(port, function(){
        console.log("server listening on port: "+port);
      });
      return server;
    };
    
    
    이제 이를 실행할 수 있습니다.
    const startServer = require('./startServer.js')
    
    startServer({ path: './static_content', port: 3000 });
    
    위의 예시에서 나는 매우 기본적인 오류 처리를 추가했다.정적 내용 디렉터리에서 사용자가 지정한 자원을 찾을 수 없거나 읽을 수 없으면 서버 응답은 code 404의 제목과 오류 원인을 설명하는 다른 내용을 표시합니다.
    브라우저가 우리가 처리하고 있는 내용 유형을 더욱 잘 이해하도록 하기 위해서, 자원 content type에 대한 지시를 포함하는 것이 가장 좋다.lookupContentType에서는 파일 확장자 유형에 따라서만 이 작업을 수행할 수 있습니다.
    현재, 만약 우리가 pdf을 시도한다면, 브라우저는 pdf 파일을 다운로드하지 않고 열 수 있습니다.

    결론
    이것은 결코 건장한 제품이 아니다. 단지 매우 간단한 예로 expressjs과 같은 구조에서 막후의 작업 원리를 설명한다.우리는 라이브러리 http에 내장된 NodeJ를 이용하여 간단한 http 서버를 실행합니다.
    우리는 주어진 위치에서 정적 내용을 찾기 위해 간단한 경로를 실현했다.우리는 또한 간단한 메모리 캐시, 내용 유형 분석, 자원을 찾지 못하거나 접근할 수 없을 때의 기본적인 오류 처리를 실현했다.

    한층 더 읽다
    정적 내용을 제공하기 위해 서버를 구축하고 싶은 사람이 있다면 기존 프레임워크를 사용하는 것을 권장합니다.또한 다음 항목을 검토하는 것이 좋습니다.
  • 세션 및 트랜잭션 관리
  • 캐시
  • 보안, 인증 및 인증

  • 출처
  • nodejs/http
  • netcat
  • http
  • status codes
  • Common MIME types
  • 좋은 웹페이지 즐겨찾기