Koa.js-퀵 가이드

웹 애플리케이션 프레임 워크는 웹 사이트, 웹 앱 및 백엔드를 구축하기위한 간단한 API를 제공합니다. 낮은 수준의 프로토콜, 프로세스 등에 대해 걱정할 필요가 없습니다.

Koa는 무엇입니까?

Koa는 애플리케이션을 빌드하기위한 최소한의 인터페이스를 제공합니다. 앱을 빌드하는 데 필요한 도구를 제공하는 매우 작은 프레임 워크 (600 LoC)이며 매우 유연합니다. npm에는 Koa 용으로 직접 연결할 수있는 다양한 모듈이 있습니다. Koa는 모든 종소리가없는 express.js의 핵심으로 생각할 수 있습니다.

왜 Koa?

Koa는 풋 프린트 (600 LoC)가 작으며 서버 측 앱을 생성하기 위해 노드에 대한 매우 얇은 추상화 계층입니다. 완전히 플러그 가능하며 거대한 커뮤니티가 있습니다. 이를 통해 Koa를 쉽게 확장하고 필요에 따라 사용할 수 있습니다. Express와 같은 이전 프레임 워크보다 우위를 차지하는 최첨단 기술 (ES6)을 사용하여 구축되었습니다.

이긴 흙

Pug (이전의 Jade로 알려짐)는 HTML 템플릿 작성을위한 간결한 언어입니다.

  • HTML 생성
  • 동적 코드 지원
  • 재사용 성 (DRY) 지원

Koa에서 가장 많이 사용되는 템플릿 언어 중 하나입니다.

MongoDB 및 Mongoose

MongoDB는 손쉬운 개발 및 확장을 위해 설계된 오픈 소스 문서 데이터베이스입니다. 이 데이터베이스를 사용하여 데이터를 저장합니다.

Mongoose는 Node.js 용 클라이언트 API로 Koa 애플리케이션에서 데이터베이스에 쉽게 액세스 할 수 있습니다.

Koa 프레임 워크를 사용하여 개발을 시작하려면 Node 및 npm (노드 패키지 관리자)이 설치되어 있어야합니다. 아직 설치하지 않은 경우 노드 설정 으로 이동하여 로컬 시스템에 노드를 설치하십시오. 터미널에서 다음 명령을 실행하여 노드 및 npm이 설치되었는지 확인합니다.

$ node --version
$ npm --version

다음과 유사한 출력을 받아야합니다.

v5.0.0
3.5.2

노드 버전이 6.5.0 이상인지 확인하십시오. 이제 Node와 npm이 설정되었으므로 npm이 무엇이며 어떻게 사용하는지 이해하겠습니다.

노드 패키지 관리자 (npm)

npm은 노드의 패키지 관리자입니다. npm 레지스트리는 Node.js, 프런트 엔드 웹 앱, 모바일 앱, 로봇, 라우터 및 JavaScript 커뮤니티의 수많은 기타 요구 사항을위한 오픈 소스 코드 패키지의 공개 모음입니다. npm을 사용하면 이러한 모든 패키지에 액세스하여 로컬로 설치할 수 있습니다. npmJS 에서 npm에서 사용 가능한 패키지 목록을 찾아 볼 수 있습니다 .

npm을 사용하는 방법?

npm을 사용하여 패키지를 설치하는 방법에는 전역 및 로컬의 두 가지가 있습니다.

Globally−이 방법은 일반적으로 개발 도구 및 CLI 기반 패키지를 설치하는 데 사용됩니다. 패키지를 전역으로 설치하려면 다음 명령을 사용하십시오.

$ npm install -g <package-name>

Locally−이 방법은 일반적으로 프레임 워크 및 라이브러리를 설치하는 데 사용됩니다. 로컬로 설치된 패키지는 설치된 디렉토리 내에서만 사용할 수 있습니다. 패키지를 로컬로 설치하려면 위와 동일한 명령을 사용하십시오.g 깃발.

$ npm install <package-name>

npm을 사용하여 프로젝트를 만들 때마다 프로젝트에 대한 모든 세부 정보가 포함 된 package.json 파일을 제공해야합니다. npm을 사용하면이 파일을 쉽게 설정할 수 있습니다. 개발 프로젝트를 설정하겠습니다.

Step 1 − 터미널 / cmd를 실행하고 hello-world라는 이름의 새 폴더를 생성 한 다음 cd −

Step 2 − 이제 npm을 사용하여 package.json 파일을 생성하려면 다음을 사용하십시오.

npm init

다음 정보를 요청합니다.

Enter를 계속 누르고 "저자 이름"필드에 이름을 입력하십시오.

Step 3− 이제 package.json 파일이 설정되었으므로 Koa를 설치합니다. Koa를 설치하고 package.json 파일에 추가하려면 다음 명령을 사용하십시오.

$ npm install --save koa

Koa가 올바르게 설치되었는지 확인하려면 다음 명령을 실행하십시오.

$ ls node_modules #(dir node_modules for windows)

Tip--save 플래그는 다음으로 대체 될 수 있습니다. -S깃발. 이 플래그는 Koa가 package.json 파일에 대한 종속성으로 추가되도록합니다. 이것은 이점이 있습니다. 다음에 프로젝트의 모든 종속성을 설치해야 할 때 npm install 명령을 실행하면이 파일에서 종속성을 찾아서 설치합니다.

Koa 프레임 워크를 사용하여 개발을 시작하는 데 필요한 전부입니다. 개발 프로세스를 훨씬 더 쉽게 만들기 위해 npm, nodemon에서 도구를 설치합니다. 이 도구는 파일을 변경하자마자 서버를 다시 시작합니다. 그렇지 않으면 파일을 수정할 때마다 서버를 수동으로 다시 시작해야합니다. nodemon을 설치하려면 다음 명령을 사용하십시오.

$ npm install -g nodemon

이제 우리는 모두 Koa에 뛰어들 준비가되었습니다!

개발을 설정했으면 Koa를 사용하여 첫 번째 앱 개발을 시작할 때입니다. 라는 새 파일을 만듭니다.app.js 다음을 입력하십시오.

var koa = require('koa');
var app = new koa();

app.use(function* (){
   this.body = 'Hello world!';
});

app.listen(3000, function(){
   console.log('Server running on https://localhost:3000')
});

파일을 저장하고 터미널로 이동하여 입력하십시오.

$ nodemon app.js

그러면 서버가 시작됩니다. 이 앱을 테스트하려면 브라우저를 열고https://localhost:3000 다음 메시지를 받아야합니다.

이 앱은 어떻게 작동합니까?

첫 번째 줄은 파일에서 Koa를 가져옵니다. Koa 변수를 통해 API에 액세스 할 수 있습니다. 우리는 그것을 사용하여 응용 프로그램을 만들고 var app에 할당합니다.

app.use(function)−이 함수는 미들웨어로 서버가 요청을받을 때마다 호출됩니다. 다음 장에서 미들웨어에 대해 자세히 알아볼 것입니다. 콜백 함수는 생성기이며 다음 장에서 살펴 보겠습니다. 이 생성기의 컨텍스트를 Koa에서는 컨텍스트라고합니다. 이 컨텍스트는 요청 및 응답 개체에 액세스하고 수정하는 데 사용됩니다. 우리는이 응답의 본문을Hello world!.

app.listen(port, function)−이 기능은 지정된 포트에서 연결을 바인딩하고 수신합니다. 여기서 포트는 유일한 필수 매개 변수입니다. 앱이 성공적으로 실행되면 콜백 함수가 실행됩니다.

JavaScript ES6의 가장 흥미로운 새 기능 중 하나는 생성기라고하는 새로운 유형의 함수입니다. 생성기 이전에는 전체 스크립트가 일반적으로 코드 실행을 중지하고 나중에 동일한 스택으로 다시 시작할 수있는 쉬운 방법없이 위에서 아래로 순서대로 실행하는 데 사용되었습니다. 생성기는 종료하고 나중에 다시 입력 할 수있는 기능입니다. 해당 컨텍스트 (변수 바인딩)는 재진입시 저장됩니다.

생성기를 사용하면 그 사이에 코드 실행을 중지 할 수 있습니다. 따라서 간단한 생성기를 살펴 보겠습니다.

var generator_func = function* (){
   yield 1;
   yield 2;
};

var itr = generator_func();
console.log(itr.next());
console.log(itr.next());
console.log(itr.next());

위의 코드를 실행하면 다음과 같은 결과가 나옵니다.

{ value: 1, done: false }
{ value: 2, done: false }
{ value: undefined, done: true }

위의 코드를 살펴 보겠습니다. 먼저 다음과 같은 생성기를 만듭니다.generator_func(). 우리는이 이상해 보이는 함수의 인스턴스를 생성하고itr. 그런 다음 우리는 전화를 시작했습니다next() 이 itr 변수에.

next ()를 호출하면 생성기가 시작되고 수익률에 도달 할 때까지 실행됩니다. 그런 다음 값과 완료가있는 객체를 반환합니다. 여기서 값에는 표현식 값이 있습니다. 이 표현은 무엇이든 될 수 있습니다. 이 시점에서 실행을 일시 중지합니다. 다시이 함수 (next)를 호출하면 생성기는 마지막 항복 지점에서 다음 항복 지점까지 일시 중지시 동일한 함수 상태로 실행을 다시 시작합니다. 이것은 코드에 더 이상 항복점이 없을 때까지 수행됩니다.

Koa의 발전기

이 튜토리얼에서 생성기에 대해 논의하는 이유는 무엇입니까? Hello World 프로그램에서 기억 하시겠지만,function* ()app.use ()에 콜백을 전달하는 표기법입니다. Koa는 미들웨어 생성기 함수의 배열을 포함하는 객체이며 각 요청에 따라 스택과 같은 방식으로 구성되고 실행됩니다. Koa는 또한 제어 흐름의 업스트림에 이어 다운 스트림을 구현합니다.

이를 더 잘 이해하려면 다음 예제를 살펴보십시오.

var koa = require('koa');
var app = koa();
 
app.use(function* (next) {
   //do something before yielding to next generator function 
   
   //in line which will be 1st event in downstream
   console.log("1");
   yield next;
 
   //do something when the execution returns upstream, 
   //this will be last event in upstream
   console.log("2");
});
app.use(function* (next) {
   // This shall be 2nd event downstream
   console.log("3");
   yield next;
 
   // This would be 2nd event upstream
   console.log("4");
});
app.use(function* () { 
   // Here it would be last function downstream
   console.log("5");
   
   // Set response body
   this.body = "Hello Generators";

   // First event of upstream (from the last to first)
   console.log("6");
});

app.listen(3000);

위의 코드를 실행하고 탐색 할 때 https://localhost:3000/ 콘솔에 다음 출력이 표시됩니다.

1
3
5
6
4
2

이것은 본질적으로 Koa가 생성기를 사용하는 방법입니다. 이 속성을 사용하여 컴팩트 한 미들웨어를 만들고 업스트림 및 다운 스트림 기능 모두에 대한 코드를 작성할 수 있으므로 콜백으로부터 우리를 절약 할 수 있습니다.

웹 프레임 워크는 다양한 경로에서 HTML 페이지, 스크립트, 이미지 등과 같은 리소스를 제공합니다. Koa는 코어 모듈에서 경로를 지원하지 않습니다. Koa에서 경로를 쉽게 생성하려면 Koa-router 모듈을 사용해야합니다. 다음 명령을 사용하여이 모듈을 설치합니다.

npm install --save koa-router

이제 Koa-router가 설치되었으므로 간단한 GET 경로 예제를 살펴 보겠습니다.

var koa = require('koa');
var router = require('koa-router');
var app = koa();

var _ = router();              //Instantiate the router
_.get('/hello', getMessage);   // Define routes

function *getMessage() {
   this.body = "Hello world!";
};

app.use(_.routes());           //Use the routes defined using the router
app.listen(3000);

애플리케이션을 실행하고 localhost : 3000 / hello로 이동하면 서버는 "/ hello"경로에서 get 요청을받습니다. Koa 앱은이 경로에 연결된 콜백 함수를 실행하고 "Hello World!"를 보냅니다. 응답으로.

동일한 경로에서 여러 가지 다른 방법을 사용할 수도 있습니다. 예를 들면

var koa = require('koa');
var router = require('koa-router');
var app = koa();

var _ = router(); //Instantiate the router

_.get('/hello', getMessage);
_.post('/hello', postMessage);

function *getMessage() {
	this.body = "Hello world!";
};
function *postMessage() {
   this.body = "You just called the post method at '/hello'!\n";
};
app.use(_.routes()); //Use the routes defined using the router
app.listen(3000);

이 요청을 테스트하려면 터미널을 열고 cURL을 사용하여 다음 요청을 실행하십시오.

curl -X POST "https://localhost:3000/hello"

특별한 방법, all, 동일한 기능을 사용하여 특정 경로에서 모든 유형의 http 메소드를 처리하기 위해 express에서 제공합니다. 이 방법을 사용하려면 다음을 시도하십시오.

_.all('/test', allMessage);

function *allMessage(){
   this.body = "All HTTP calls regardless of the verb will get this response";
};

이제 경로를 정의 할 수 있습니다. 정적이거나 고정되어 있습니다. 동적 경로를 사용하려면 다양한 유형의 경로를 제공해야합니다. 동적 경로를 사용하면 매개 변수를 전달하고이를 기반으로 처리 할 수 ​​있습니다. 다음은 동적 경로의 예입니다.

var koa = require('koa');
var router = require('koa-router');
var app = koa();

var _ = router();

_.get('/:id', sendID);

function *sendID() {
   this.body = 'The id you specified is ' + this.params.id;
}

app.use(_.routes());
app.listen(3000);

이것을 테스트하려면 https://localhost:3000/123. 다음과 같은 응답을 받게됩니다.

URL의 '123'을 다른 것으로 바꿀 수 있으며 응답에 반영됩니다. 다음은 위의 복잡한 예입니다.

var koa = require('koa');
var router = require('koa-router');
var app = koa();

var _ = router();

_.get('/things/:name/:id', sendIdAndName);

function *sendIdAndName(){
   this.body = 'id: ' + this.params.id + ' and name: ' + this.params.name;
};

app.use(_.routes());

app.listen(3000);

이것을 테스트하려면 https://localhost:3000/things/tutorialspoint/12345.

당신은 사용할 수 있습니다 this.paramsURL에서 전달하는 모든 매개 변수에 액세스 할 수 있습니다. 위의 두 가지 경로는 서로 다릅니다. 그들은 결코 겹치지 않을 것입니다. 또한 '/ things'를받을 때 코드를 실행하려면 별도로 정의해야합니다.

패턴 일치 경로

정규식을 사용하여 URL 매개 변수 일치를 제한 할 수도 있습니다. ID가 5 자리 숫자 여야한다고 가정 해 보겠습니다. 다음 경로 정의를 사용할 수 있습니다.

var koa = require('koa');
var router = require('koa-router');
var app = koa();

var _ = router();

_.get('/things/:id([0-9]{5})', sendID);

function *sendID(){
   this.body = 'id: ' + this.params.id;
}

app.use(_.routes());
app.listen(3000);

이것은 only5 자리의 긴 ID가있는 요청과 일치합니다. 더 복잡한 정규식을 사용하여 경로를 일치 / 검증 할 수 있습니다. 요청과 일치하는 경로가 없으면 응답으로 찾을 수 없음 메시지가 표시됩니다.

예를 들어, 위와 동일한 경로를 정의하면 유효한 URL로 요청하면 다음과 같이됩니다.

HTTP 메서드는 요청에 제공되며 클라이언트가 요청한 작업을 지정합니다. 다음 표에는 일반적으로 사용되는 HTTP 메서드가 요약되어 있습니다.

Sr. 아니. 방법 및 설명
1

GET

GET 메서드는 지정된 리소스의 표현을 요청합니다. GET을 사용하는 요청은 데이터 만 검색해야하며 다른 효과는 없어야합니다.

2

POST

POST 메소드는 서버가 요청에 포함 된 데이터를 URI로 식별되는 리소스의 새 개체 / 엔티티로 수락하도록 요청합니다.

PUT

PUT 메서드는 URI로 식별되는 기존 개체에 대한 수정으로 요청에 포함 된 데이터를 서버에 수락하도록 요청합니다. 존재하지 않는 경우 PUT 메소드가 생성해야합니다.

4

DELETE

DELETE 메서드는 서버가 지정된 리소스를 삭제하도록 요청합니다.

이것은 가장 일반적인 HTTP 메소드입니다. 그들에 대해 자세히 알아 보려면https://www.tutorialspoint.com/http/http_methods.htm.

Koa Request 객체는 노드의 바닐라 요청 객체 위에 추상화되어 일상적인 HTTP 서버 개발에 유용한 추가 기능을 제공합니다. Koa 요청 객체는 컨텍스트 객체에 포함되어 있습니다.this. 요청을받을 때마다 요청 객체에서 로그 아웃합시다.

var koa = require('koa');
var router = require('koa-router');
var app = koa();

var _ = router();

_.get('/hello', getMessage);

function *getMessage(){
   console.log(this.request);
   this.body = 'Your request has been logged.';
}
app.use(_.routes());
app.listen(3000);

이 코드를 실행하고 다음으로 이동하면 https://localhost:3000/hello, 그러면 다음 응답을 받게됩니다.

콘솔에서 요청 개체가 로그 아웃됩니다.

{ 
   method: 'GET',
   url: '/hello/',
   header: 
   { 
      host: 'localhost:3000',
      connection: 'keep-alive',
      'upgrade-insecure-requests': '1',
      'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) 
         AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36',
      accept: 'text/html,application/xhtml+xml,
         application/xml;q = 0.9,image/webp,*/*;q = 0.8',
      dnt: '1',
      'accept-encoding': 'gzip, deflate, sdch',
      'accept-language': 'en-US,en;q = 0.8' 
   }
}

이 객체를 사용하여 요청의 많은 유용한 속성에 액세스 할 수 있습니다. 몇 가지 예를 살펴 보겠습니다.

request.header

모든 요청 헤더를 제공합니다.

request.method

요청 방법 (GET, POST 등) 제공

request.href

전체 요청 URL을 제공합니다.

request.path

요청 경로를 제공합니다. 쿼리 문자열 및 기본 URL이 없습니다.

request.query

구문 분석 된 쿼리 문자열을 제공합니다. 예를 들어, 다음과 같은 요청에이를 기록하면https://localhost:3000/hello/?name=Ayush&age=20&country=India, 그러면 다음 객체를 얻을 수 있습니다.

{
   name: 'Ayush',
   age: '20',
   country: 'India'
}

request.accepts (유형)

이 함수는 요청 된 리소스가 주어진 요청 유형을 수락하는지 여부에 따라 true 또는 false를 반환합니다.

Request 의 문서에서 요청 객체에 대한 자세한 내용을 읽을 수 있습니다 .

Koa Response 객체는 노드의 바닐라 응답 객체 위에 추상화되어 일상적인 HTTP 서버 개발에 유용한 추가 기능을 제공합니다. Koa 응답 객체는 컨텍스트 객체에 포함되어 있습니다.this. 요청을받을 때마다 응답 객체를 로그 아웃합시다.

var koa = require('koa');
var router = require('koa-router');
var app = koa();

var _ = router();

_.get('/hello', getMessage);

function *getMessage(){
   this.body = 'Your request has been logged.';
   console.log(this.response);
}

app.use(_.routes());
app.listen(3000);

이 코드를 실행하고 다음으로 이동하면 https://localhost:3000/hello 그러면 다음과 같은 응답을 받게됩니다.

콘솔에서 요청 개체가 로그 아웃됩니다.

{ 
   status: 200,
   message: 'OK',
   header: 
   {
      'content-type': 'text/plain; charset=utf-8',
      'content-length': '12' 
   },
   body: 'Your request has been logged.' 
}

상태와 메시지는 Koa에 의해 자동으로 설정되지만 당사에서 수정할 수 있습니다. 응답 본문을 설정하지 않으면 상태 코드는 404로 설정됩니다. 응답 본문을 설정하면 상태는 기본적으로 200으로 설정됩니다. 이 동작을 명시 적으로 재정의 할 수 있습니다.

이 객체를 사용하여 응답의 많은 유용한 속성에 액세스 할 수 있습니다. 몇 가지 예를 살펴 보겠습니다.

response.header

모든 응답 헤더를 제공합니다.

response.status

응답 상태 (200, 404, 500 등)를 제공합니다. 이 속성은 응답 상태를 설정하는데도 사용됩니다.

response.message

응답 메시지를 제공합니다. 이 속성은 응답이있는 사용자 지정 메시지를 설정하는데도 사용됩니다. response.status와 연관됩니다.

response.body

응답 본문을 가져 오거나 설정합니다. 일반적으로 컨텍스트 개체를 사용하여 액세스합니다. 이것은 액세스하는 또 다른 방법입니다. 본문은 String, Buffer, Stream, Object 또는 Null 유형일 수 있습니다.

response.type

현재 응답의 콘텐츠 유형을 가져 오거나 설정합니다.

response.get (필드)

이 함수는 대소 문자를 구분하지 않는 값 필드가있는 헤더의 값을 가져 오는 데 사용됩니다.

response.set (필드, 값)

이 함수는 필드와 값 쌍을 사용하여 응답에 헤더를 설정하는 데 사용됩니다.

response.remove (필드)

이 함수는 필드 이름을 사용하여 응답에서 헤더를 설정 해제하는 데 사용됩니다.

Response 의 문서에서 응답 객체에 대해 자세히 읽을 수 있습니다 .

리디렉션은 웹 사이트를 만들 때 매우 중요합니다. 잘못된 URL이 요청되거나 서버에 오류가있는 경우 해당 오류 페이지로 리디렉션해야합니다. 리디렉션을 사용하여 웹 사이트의 제한된 영역에서 사람들을 보호 할 수도 있습니다.

누군가가 잘못된 URL을 요청할 때마다 오류 페이지를 만들고 해당 페이지로 리디렉션하겠습니다.

var koa = require('koa');
var router = require('koa-router');
var app = koa();
var _ = router();

_.get('/not_found', printErrorMessage);
_.get('/hello', printHelloMessage);

app.use(_.routes());
app.use(handle404Errors);

function *printErrorMessage() {
   this.status = 404;
   this.body = "Sorry we do not have this resource.";
}
function *printHelloMessage() {
   this.status = 200;
   this.body = "Hey there!";
}
function *handle404Errors(next) {
   if (404 != this.status) return;
   this.redirect('/not_found');
}
app.listen(3000);

이 코드를 실행하고 / hello 이외의 경로로 이동하면 / not_found로 리디렉션됩니다. 우리는 마지막에 미들웨어를 배치했습니다 (이 미들웨어에 대한 app.use 함수 호출). 이를 통해 우리는 마침내 미들웨어에 도달하고 해당 응답을 보냅니다. 다음은 위 코드를 실행할 때 표시되는 결과입니다.

우리가 탐색 할 때 https://localhost:3000/hello, 우리는-

다른 경로로 이동하면-

오류 처리는 웹 애플리케이션을 구축하는 데 중요한 역할을합니다. Koa는 이러한 목적으로도 미들웨어를 사용합니다.

Koa에서는 다음과 같은 미들웨어를 추가합니다. try { yield next }최초의 미들웨어 중 하나로. 다운 스트림에서 오류가 발생하면 관련 catch 절로 돌아가 여기에서 오류를 처리합니다. 예를 들면-

var koa = require('koa');
var app = koa();

//Error handling middleware
app.use(function *(next) {
   try {
      yield next;
   } catch (err) {
      this.status = err.status || 500;
      this.body = err.message;
      this.app.emit('error', err, this);
   }
});

//Create an error in the next middleware
//Set the error message and status code and throw it using context object

app.use(function *(next) {
   //This will set status and message
   this.throw('Error Message', 500);
});

app.listen(3000);

위 코드에서 의도적으로 오류를 생성했으며 첫 번째 미들웨어의 catch 블록에서 오류를 처리하고 있습니다. 그런 다음 콘솔로 내보내고 클라이언트에 대한 응답으로 보냅니다. 다음은이 오류를 트리거 할 때 표시되는 오류 메시지입니다.

InternalServerError: Error Message
   at Object.module.exports.throw 
      (/home/ayushgp/learning/koa.js/node_modules/koa/lib/context.js:91:23)
   at Object.<anonymous> (/home/ayushgp/learning/koa.js/error.js:18:13)
   at next (native)
   at onFulfilled (/home/ayushgp/learning/koa.js/node_modules/co/index.js:65:19)
   at /home/ayushgp/learning/koa.js/node_modules/co/index.js:54:5
   at Object.co (/home/ayushgp/learning/koa.js/node_modules/co/index.js:50:10)
   at Object.toPromise (/home/ayushgp/learning/koa.js/node_modules/co/index.js:118:63)
   at next (/home/ayushgp/learning/koa.js/node_modules/co/index.js:99:29)
   at onFulfilled (/home/ayushgp/learning/koa.js/node_modules/co/index.js:69:7)
   at /home/ayushgp/learning/koa.js/node_modules/co/index.js:54:5

현재 서버에 요청을 보내면이 오류가 발생합니다.

미들웨어 기능은 context object애플리케이션의 요청-응답주기에서 다음 미들웨어 기능. 이러한 함수는 요청 본문 구문 분석, 응답 헤더 추가 등과 같은 작업에 대한 요청 및 응답 개체를 수정하는 데 사용됩니다. Koa는'downstream', 그런 다음 컨트롤을 다시 전달 'upstream'. 이 효과는cascading.

다음은 작동중인 미들웨어 기능의 간단한 예입니다.

var koa = require('koa');
var app = koa();
var _ = router();

//Simple request time logger
app.use(function* (next) {
   console.log("A new request received at " + Date.now());
   
   //This function call is very important. It tells that more processing is 
   //required for the current request and is in the next middleware function/route handler.
   yield next;
});

app.listen(3000);

위의 미들웨어는 서버의 모든 요청에 ​​대해 호출됩니다. 따라서 모든 요청 후 콘솔에 다음 메시지가 표시됩니다.

A new request received at 1467267512545

특정 경로 (및 모든 하위 경로)로 제한하려면 라우팅에서했던 것처럼 경로를 생성하면됩니다. 실제로 이러한 미들웨어는 우리의 요청을 처리합니다.

예를 들면

var koa = require('koa');
var router = require('koa-router');
var app = koa();

var _ = router();

//Simple request time logger
_.get('/request/*', function* (next) {
   console.log("A new request received at " + Date.now());
   yield next;
});

app.use(_.routes());
app.listen(3000);

이제 '/ request'의 하위 경로를 요청할 때마다 시간을 기록합니다.

미들웨어 호출 순서

Koa에서 미들웨어에 대한 가장 중요한 것 중 하나는 파일에 작성 / 포함되는 순서가 다운 스트림에서 실행되는 순서라는 것입니다. 미들웨어에서 yield 문에 도달하자마자 마지막에 도달 할 때까지 다음 미들웨어로 전환됩니다. 그런 다음 다시 돌아가서 yield 문에서 함수를 다시 시작합니다.

예를 들어, 다음 코드 스 니펫에서 첫 번째 함수는 먼저 yield까지 실행하고 두 번째 미들웨어는 yield까지 실행 한 다음 세 번째 함수를 실행합니다. 여기에 미들웨어가 더 이상 없기 때문에 뒤로 이동하기 시작하여 역순, 즉 세 번째, 두 번째, 첫 번째로 실행합니다. 이 예제는 Koa 방식으로 미들웨어를 사용하는 방법을 요약합니다.

var koa = require('koa');
var app = koa();

//Order of middlewares
app.use(first);
app.use(second);
app.use(third);

function *first(next) {
   console.log("I'll be logged first. ");
   
   //Now we yield to the next middleware
   yield next;
   
   //We'll come back here at the end after all other middlewares have ended
   console.log("I'll be logged last. ");
};

function *second(next) {
   console.log("I'll be logged second. ");
   yield next;
   console.log("I'll be logged fifth. ");
};

function *third(next) {
   console.log("I'll be logged third. ");
   yield next;
   console.log("I'll be logged fourth. ");
};

app.listen(3000);

이 코드를 실행 한 후 '/'를 방문하면 콘솔에서 다음을 얻을 수 있습니다.

I'll be logged first. 
I'll be logged second. 
I'll be logged third. 
I'll be logged fourth. 
I'll be logged fifth. 
I'll be logged last.

다음 다이어그램은 위의 예에서 실제로 일어나는 일을 요약합니다.

이제 자체 미들웨어를 만드는 방법을 알았으므로 가장 일반적으로 사용되는 커뮤니티 생성 미들웨어에 대해 논의하겠습니다.

타사 미들웨어

Express 용 타사 미들웨어 목록은 여기에서 확인할 수 있습니다. 다음은 가장 일반적으로 사용되는 미들웨어입니다.

  • koa-bodyparser
  • koa-router
  • koa-static
  • koa-compress

다음 장에서 여러 미들웨어에 대해 논의 할 것입니다.

Pug는 템플릿 엔진입니다. 템플릿 엔진은 기존 HTML 템플릿에 문자열을 강력하게 연결하여 HTML로 서버 코드의 복잡함을 제거하는 데 사용됩니다. Pug는 다음과 같은 다양한 기능을 가진 매우 강력한 템플릿 엔진입니다.filters, includes, inheritance, interpolation, 등등. 이것에 대해 다룰 근거가 많이 있습니다.

Koa와 함께 Pug를 사용하려면 다음 명령을 사용하여 설치해야합니다.

$ npm install --save pug koa-pug

pug가 설치되면 앱의 템플릿 엔진으로 설정합니다. app.js 파일에 다음 코드를 추가합니다.

var koa = require('koa');
var router = require('koa-router');
var app = koa();

var Pug = require('koa-pug');
var pug = new Pug({
   viewPath: './views',
   basedir: './views',
   app: app //Equivalent to app.use(pug)
});

var _ = router(); //Instantiate the router

app.use(_.routes()); //Use the routes defined using the router
app.listen(3000);

이제보기라는 새 디렉터리를 만듭니다. 디렉터리 내에 first_view.pug라는 파일을 만들고 다음 데이터를 입력합니다.

doctype html
html
   head
      title = "Hello Pug"
   body
      p.greetings#people Hello Views!

이 페이지를 실행하려면 앱에 다음 경로를 추가하십시오.

_.get('/hello', getMessage); // Define routes

function *getMessage(){
   this.render('first_view');
};

다음과 같이 출력을 받게됩니다.

Pug가하는 일은 매우 간단한 마크 업을 html로 변환하는 것입니다. 태그를 닫는 것을 추적 할 필요가 없으며 class 및 id 키워드를 사용할 필요가 없으며 '.'를 사용합니다. 및 '#'을 사용하여 정의합니다. 위의 코드는 먼저 다음으로 변환됩니다.

<!DOCTYPE html>
<html>
   <head>
      <title>Hello Pug</title>
   </head>
    
   <body>
      <p class = "greetings" id = "people">Hello Views!</p>
   </body>
</html>

Pug는 HTML 마크 업을 단순화하는 것 이상을 수행 할 수 있습니다. Pug의 이러한 기능 중 일부를 살펴 보겠습니다.

간단한 태그

태그는 들여 쓰기에 따라 중첩됩니다. 위의 예 에서처럼<title> 안으로 들여 쓰기되었습니다 <head>태그, 내부에있었습니다. 그러나, 그<body> 태그가 같은 들여 쓰기에 있었으므로 <head> 꼬리표.

태그를 닫을 필요가 없습니다. Pug는 동일하거나 외부 들여 쓰기 수준에서 다음 태그를 만나는 즉시 태그를 닫습니다.

태그 안에 텍스트를 넣는 세 가지 방법이 있습니다.

  • 분리 된 공간-
h1 Welcome to Pug
  • 파이프 텍스트 −
div
   | To insert multiline text, 
   | You can use the pipe operator.
  • 텍스트 블록-
div.
   But that gets tedious if you have a lot of text. 
   You can use "." at the end of tag to denote block of text. 
   To put tags inside this block, simply enter tag in a new line and 
   indent it accordingly.

코멘트

Pug는 주석 작성에 JavaScript (//)와 동일한 구문을 사용합니다. 이러한 주석은 html 주석 (<!-comment->)으로 변환됩니다. 예를 들면

//This is a Pug comment

이 주석은-

<!--This is a Pug comment-->

속성

속성을 정의하기 위해 괄호 안에 쉼표로 구분 된 속성 목록을 사용합니다. 클래스 및 ID 속성에는 특별한 표현이 있습니다. 다음 코드 줄은 주어진 html 태그에 대한 속성, 클래스 및 ID 정의를 다룹니다.

div.container.column.main#division(width = "100",height = "100")

이 코드 줄은 다음과 같이 변환됩니다.

<div class = "container column main" id = "division" width = "100" height = "100"></div>

템플릿에 값 전달

Pug 템플릿을 렌더링 할 때 실제로 경로 핸들러에서 값을 전달하여 템플릿에서 사용할 수 있습니다. 다음 코드를 사용하여 새 경로 처리기를 만듭니다.

var koa = require('koa');
var router = require('koa-router');
var app = koa();

var Pug = require('koa-pug');
var pug = new Pug({
   viewPath: './views',
   basedir: './views',
   app: app // equals to pug.use(app) and app.use(pug.middleware)
});

var _ = router(); //Instantiate the router

_.get('//dynamic_view', dynamicMessage); // Define routes

function *dynamicMessage(){
   this.render('dynamic', {
      name: "TutorialsPoint", 
      url:"https://www.tutorialspoint.com"
   });
};

app.use(_.routes()); //Use the routes defined using the router
app.listen(3000);

그런 다음 다음 코드를 사용하여보기 디렉터리에 dynamic.pug라는 새보기 파일을 만듭니다.

html
   head
      title = name
   body
      h1 = name
      a(href = url) URL

열다 localhost:3000/dynamic브라우저에서 다음이 출력되어야합니다. −

텍스트 내에서 이러한 전달 된 변수를 사용할 수도 있습니다. 태그의 텍스트 사이에 전달 된 변수를 삽입하려면 # {variableName} 구문을 사용합니다. 예를 들어 위의 예에서 TutorialsPoint에서 Greetings를 삽입하려면 다음 코드를 사용해야합니다.

html
   head
      title = name
   body
      h1 Greetings from #{name}
      a(href = url) URL

이 값을 사용하는 방법을 보간이라고합니다.

조건부

조건문과 반복 구조도 사용할 수 있습니다. 이 실용적인 예를 고려해보십시오. 사용자가 로그인하면 "Hi, User"를 표시하고 그렇지 않은 경우 "Login / Sign Up"링크를 표시하려고합니다. 이를 위해 다음과 같은 간단한 템플릿을 정의 할 수 있습니다.

html
   head
      title Simple template
   body
      if(user)
         h1 Hi, #{user.name}
      else
         a(href = "/sign_up") Sign Up

경로를 사용하여 이것을 렌더링하고 다음과 같은 객체를 전달하면-

this.render('/dynamic',{user: 
   {name: "Ayush", age: "20"}
});

Hi, Ayush를 표시하는 메시지가 표시됩니다. 그러나 객체를 전달하지 않거나 사용자 키없이 객체를 전달하면 등록 링크를 받게됩니다.

포함 및 구성 요소

Pug는 웹 페이지의 구성 요소를 만드는 매우 직관적 인 방법을 제공합니다. 예를 들어 뉴스 웹 사이트를 보면 로고와 카테고리가있는 헤더는 항상 고정됩니다. 모든 뷰에 복사하는 대신 include를 사용할 수 있습니다. 다음 예는 include를 사용하는 방법을 보여줍니다.

다음 코드로 세 개의 뷰를 만듭니다.

header.pug

div.header.
   I'm the header for this website.

content.pug

html
   head
      title Simple template
   body
      include ./header.pug
      h3 I'm the main content
      include ./footer.pug

footer.pug

div.footer.
   I'm the footer for this website.

이에 대한 경로를 다음과 같이 만듭니다.

var koa = require('koa');
var router = require('koa-router');
var app = koa();

var Pug = require('koa-pug');
var pug = new Pug({
   viewPath: './views',
   basedir: './views',
   app: app //Equivalent to app.use(pug)
});

var _ = router(); //Instantiate the router

_.get('/components', getComponents);

function *getComponents(){
   this.render('content.pug');
}

app.use(_.routes()); //Use the routes defined using the router
app.listen(3000);

이동 localhost:3000/components, 다음과 같은 출력이 표시됩니다.

include 일반 텍스트, CSS 및 JavaScript를 포함하는데도 사용할 수 있습니다.

Pug의 다른 많은 기능이 있습니다. 그러나 이는이 튜토리얼의 범위를 벗어납니다. Pug에서 Pug를 더 탐험 할 수 있습니다 .

양식은 웹의 필수적인 부분입니다. 우리가 방문하는 거의 모든 웹 사이트는 우리를 위해 몇 가지 정보를 제출하거나 가져 오는 양식을 제공합니다. 양식을 시작하려면 먼저 koa-body를 설치합니다. 이것을 설치하려면 터미널로 이동하여 다음을 사용하십시오.

$ npm install --save koa-body

app.js 파일 내용을 다음 코드로 바꿉니다.

var koa = require('koa');
var router = require('koa-router');
var bodyParser = require('koa-body');
var app = koa();

//Set up Pug
var Pug = require('koa-pug');
var pug = new Pug({
   viewPath: './views',
   basedir: './views',
   app: app //Equivalent to app.use(pug)
});

//Set up body parsing middleware
app.use(bodyParser({
   formidable:{uploadDir: './uploads'},
   multipart: true,
   urlencoded: true
}));

_.get('/', renderForm);
_.post('/', handleForm);

function * renderForm(){
   this.render('form');
}
function *handleForm(){
   console.log(this.request.body);
   console.log(this.req.body);
   this.body = this.request.body; //This is where the parsed request is stored
}

app.use(_.routes()); 
app.listen(3000);

여기서 우리가하는 새로운 일은 body parser와 multer를 가져 오는 것입니다. 우리는 json 및 x-www-form-urlencoded 헤더 요청을 구문 분석하기 위해 본문 구문 분석기를 사용하고 있으며 multipart / form-data 구문 분석을 위해 multer를 사용합니다.

이를 테스트하기 위해 html 양식을 만들어 보겠습니다! 다음 코드를 사용하여 form.pug라는 새보기를 만듭니다.

html
   head
      title Form Tester
   body
      form(action = "/", method = "POST")
         div
            label(for = "say") Say: 
            input(name = "say" value = "Hi")
         br
         div
            label(for = "to") To: 
            input(name = "to" value = "Koa form")
         br
         button(type = "submit") Send my greetings

다음을 사용하여 서버를 실행하십시오-

nodemon index.js

이제 localhost : 3000 /로 이동하여 원하는대로 양식을 작성하고 제출하십시오. 다음과 같이 응답을 받게됩니다.

콘솔을 살펴보면 요청 본문이 JavaScript 개체로 표시됩니다. 예를 들면-

그만큼 this.request.body객체에는 파싱 된 요청 본문이 포함됩니다. 해당 객체의 필드를 사용하려면 일반 JS 객체로 사용하면됩니다.

이것은 요청을 보내는 한 가지 방법 일뿐입니다. 다른 많은 방법이 있지만 Koa 앱이 모든 요청을 동일한 방식으로 처리하기 때문에 여기에서 다루지 않아도됩니다. 다양한 요청 방법에 대해 자세히 알아 보려면 이 페이지를 참조하십시오.

웹 애플리케이션은 파일 업로드를 허용하는 기능을 제공해야합니다. 클라이언트로부터 파일을 받아 서버에 저장하는 방법을 살펴 보겠습니다.

요청 구문 분석을 위해 이미 koa-body 미들웨어를 사용했습니다. 이 미들웨어는 파일 업로드 처리에도 사용됩니다. 파일을 업로드하고 Koa를 사용하여 이러한 파일을 저장할 수있는 양식을 만들어 보겠습니다. 먼저 다음과 같은 템플릿을 만듭니다.file_upload.pug 다음 내용으로.

html
   head
      title File uploads
   body
      form(action = "/upload" method = "POST" enctype = "multipart/form-data")
         div
            input(type = "text" name = "name" placeholder = "Name")
         
         div
            input(type = "file" name = "image")
         
         div
            input(type = "submit")

양식에 위와 동일한 인코딩 유형을 제공해야합니다. 이제 서버에서이 데이터를 처리하겠습니다.

var koa = require('koa');
var router = require('koa-router');
var bodyParser = require('koa-body');
var app = koa();

//Set up Pug
var Pug = require('koa-pug');
var pug = new Pug({
   viewPath: './views',
   basedir: './views',
   app: app 
});

//Set up body parsing middleware
app.use(bodyParser({
   formidable:{uploadDir: './uploads'},    //This is where the files would come
   multipart: true,
   urlencoded: true
}));

var _ = router(); //Instantiate the router

_.get('/files', renderForm);
_.post('/upload', handleForm);

function * renderForm(){
   this.render('file_upload');
}

function *handleForm(){
   console.log("Files: ", this.request.body.files);
   console.log("Fields: ", this.request.body.fields);
   this.body = "Received your data!"; //This is where the parsed request is stored
}

app.use(_.routes()); 
app.listen(3000);

이것을 실행하면 다음과 같은 양식이 표시됩니다.

이것을 제출하면 콘솔이 다음 출력을 생성합니다.

업로드 된 파일은 위 출력의 경로에 저장됩니다. 다음을 사용하여 요청의 파일에 액세스 할 수 있습니다.this.request.body.files 및 해당 요청의 필드 this.request.body.fields.

정적 파일은 클라이언트가 서버에서 그대로 다운로드하는 파일입니다. 새 디렉토리를 만듭니다.public. Express는 기본적으로 정적 파일 제공을 허용하지 않습니다.

이 목적을 위해 미들웨어가 필요합니다. 계속해서 설치하십시오koa-serve

$ npm install --save koa-static

이제 우리는 use이 미들웨어. 그 전에 public이라는 디렉토리를 만드십시오. 여기에 모든 정적 파일을 저장합니다. 이렇게하면이 공용 폴더 위의 어떤 것도 클라이언트에 액세스 할 수 없으므로 서버 코드를 안전하게 유지할 수 있습니다. 공용 디렉터리를 만든 후 다음과 같은 파일을 만듭니다.hello.txt당신이 좋아하는 모든 콘텐츠와 함께. 이제 app.js에 다음을 추가하십시오.

var serve = require('koa-static');
var koa = require('koa');
var app = koa();

app.use(serve('./public'));

app.listen(3000);

Note− Koa는 정적 디렉토리에 상대적인 파일을 조회하므로 정적 디렉토리의 이름은 URL의 일부가 아닙니다. 이제 루트 경로가 공용 디렉토리로 설정되었으므로로드하는 모든 정적 파일은 공용을 루트로 간주합니다. 이것이 제대로 작동하는지 테스트하려면 앱을 실행하고https://localhost:3000/hello.txt

다음과 같은 출력을 얻어야합니다. 이것은 HTML 문서 또는 Pug보기가 아니라 단순한 txt 파일입니다.

여러 정적 Dirs

다음을 사용하여 여러 정적 자산 디렉토리를 설정할 수도 있습니다.

var serve = require('koa-static');
var koa = require('koa');
var app = koa();

app.use(serve('./public'));
app.use(serve('./images'));

app.listen(3000);

이제 파일을 요청할 때 Koa는 이러한 디렉토리를 검색하여 일치하는 파일을 보냅니다.

쿠키는 서버 요청과 함께 클라이언트로 전송되고 클라이언트 측에 저장되는 간단하고 작은 파일 / 데이터입니다. 사용자가 웹 사이트를 다시로드 할 때마다이 쿠키가 요청과 함께 전송됩니다. 이렇게하면 사용자 작업을 추적하는 데 도움이됩니다. HTTP 쿠키에는 수많은 용도가 있습니다.

  • 세션 관리
  • 개인화 (추천 시스템)
  • 사용자 추적

Koa에서 쿠키를 사용하기 위해 다음과 같은 기능이 있습니다. ctx.cookies.set()ctx.cookies.get(). 새 쿠키를 설정하기 위해 Koa 앱에서 새 경로를 정의하겠습니다.

var koa = require('koa');
var router = require('koa-router');
var app = koa();

_.get('/', setACookie);

function *setACookie() {
   this.cookies.set('foo', 'bar', {httpOnly: false});
}

var _ = router();

app.use(_.routes());
app.listen(3000);

쿠키가 설정되어 있는지 확인하려면 브라우저로 이동하여 콘솔을 실행하고 다음을 입력하십시오.

console.log(document.cookie);

그러면 다음과 같은 출력이 생성됩니다 (브라우저의 확장으로 인해 더 많은 쿠키가 설정 될 수 있음).

"foo = bar"

다음은 위의 예입니다.

브라우저는 또한 서버에 쿼리 할 때마다 쿠키를 다시 보냅니다. 서버의 쿠키를 보려면 경로의 서버 콘솔에서 해당 경로에 다음 코드를 추가하십시오.

console.log('Cookies: foo = ', this.cookies.get('foo'));

다음에이 경로에 요청을 보내면 다음 출력이 표시됩니다.

Cookies: foo = bar

만료 시간이있는 쿠키 추가

만료되는 쿠키를 추가 할 수 있습니다. 만료되는 쿠키를 추가하려면 'expires'속성이 만료되기를 원하는 시간으로 설정된 객체를 전달하면됩니다. 예를 들면

var koa = require('koa');
var router = require('koa-router');
var app = koa();

_.get('/', setACookie);

function *setACookie(){
   //Expires after 360000 ms from the time it is set.
	this.cookies.set('name', 'value', { 
      httpOnly: false, expires: 360000 + Date.now() });
}

var _ = router();

app.use(_.routes());
app.listen(3000);

기존 쿠키 삭제

쿠키 설정을 해제하려면 쿠키를 빈 문자열로 설정하면됩니다. 예를 들어 다음과 같은 쿠키를 삭제해야하는 경우foo, 다음 코드를 사용하십시오.

var koa = require('koa');
var router = require('koa-router');
var app = koa();

_.get('/', setACookie);

function *setACookie(){
   //Expires after 360000 ms from the time it is set.
   this.cookies.set('name', '');
}

var _ = router();

app.use(_.routes());
app.listen(3000);

이렇게하면 해당 쿠키가 설정 해제됩니다. 당신은 떠나야합니다HttpOnly 클라이언트 측 코드에서 쿠키를 사용하지 않을 때 옵션을 true로 설정합니다.

HTTP는 상태 비 저장이므로 요청을 다른 요청에 연결하려면 HTTP 요청간에 사용자 데이터를 저장하는 방법이 필요합니다. 쿠키와 URL 매개 변수는 모두 클라이언트와 서버간에 데이터를 전송하는 데 적합한 방법입니다. 그러나 둘 다 클라이언트 측에서 읽을 수 있습니다. 세션은이 문제를 정확히 해결합니다. 클라이언트에 ID를 할당하고 해당 ID를 사용하여 모든 추가 요청을 수행합니다. 클라이언트와 관련된 정보는이 ID에 연결된 서버에 저장됩니다.

koa-session이 필요하므로 다음을 사용하여 설치하십시오.

npm install --save koa-session

우리는 koa-session미들웨어. 이 예에서는 RAM을 사용하여 세션을 저장합니다. 프로덕션 환경에서는 사용하지 마십시오. 세션 미들웨어는 모든 것을 처리합니다. 즉, 세션 생성, 세션 쿠키 설정, 컨텍스트 객체에 세션 객체 생성 등이 있습니다.

동일한 클라이언트에서 다시 요청을 할 때마다 세션 정보가 저장됩니다 (서버가 다시 시작되지 않은 경우). 이 세션 개체에 더 많은 속성을 추가 할 수 있습니다. 다음 예에서는 클라이언트에 대한 뷰 카운터를 만듭니다.

var session = require('koa-session');
var koa = require('koa');
var app = koa();

app.keys = ['Shh, its a secret!'];
app.use(session(app));  // Include the session middleware

app.use(function *(){
   var n = this.session.views || 0;
   this.session.views = ++n;
   
   if(n === 1)
      this.body = 'Welcome here for the first time!';
   else
      this.body = "You've visited this page " + n + " times!";
})

app.listen(3000);

위 코드가하는 일은 사용자가 사이트를 방문 할 때 사용자를위한 새 세션을 만들고 쿠키를 할당하는 것입니다. 다음에 사용자가 방문하면 쿠키가 확인되고 이에 따라 page_view 세션 변수가 업데이트됩니다.

이제 앱을 실행하고 localhost:3000, 다음과 같은 응답을 받게됩니다.

페이지를 다시 방문하면 페이지 카운터가 증가합니다. 이 경우 페이지는 12 번 새로 고쳐졌습니다.

인증은 제공된 자격 증명을 로컬 운영 체제 또는 인증 서버 내에서 권한이 부여 된 사용자 정보 데이터베이스의 파일에있는 것과 비교하는 프로세스입니다. 자격 증명이 일치하면 프로세스가 완료되고 사용자에게 액세스 권한이 부여됩니다.

우리는 사용할 매우 기본적인 인증 시스템을 만들 것입니다. Basic HTTP Authentication. 이것은 쿠키, 세션 또는 다른 것이 필요하지 않기 때문에 액세스 제어를 시행하는 가장 간단한 방법입니다. 이를 사용하려면 클라이언트는 모든 요청과 함께 Authorization 헤더를 보내야합니다. 사용자 이름과 비밀번호는 암호화되지 않지만 다음과 같이 단일 문자열로 연결됩니다.

username:password

이 문자열은 Base64로 인코딩되며 Basic이라는 단어가이 값 앞에 놓입니다. 예를 들어 사용자 이름이 Ayush이고 비밀번호 India 인 경우 문자열"Ayush:India" 인증 헤더에 인코딩 된대로 전송됩니다.

Authorization: Basic QXl1c2g6SW5kaWE=

koa 앱에서이를 구현하려면 koa-basic-auth 미들웨어가 필요합니다. 사용하여 설치-

$ npm install --save koa-basic-auth

이제 app.js 파일을 열고 다음 코드를 입력하십시오.

//This is what the authentication would be checked against
var credentials = { name: 'Ayush', pass: 'India' }

var koa = require('koa');
var auth = require('koa-basic-auth');
var _ = require('koa-router')();

var app = koa();

//Error handling middleware
app.use(function *(next){
   try {
      yield next;
   } catch (err) {
      if (401 == err.status) {
         this.status = 401;
         this.set('WWW-Authenticate', 'Basic');
         this.body = 'You have no access here';
      } else {
         throw err;
      }
   }
});

// Set up authentication here as first middleware. 
// This returns an error if user is not authenticated.
_.get('/protected', auth(credentials), function *(){
   this.body = 'You have access to the protected area.';
   yield next;
});

// No authentication middleware present here.
_.get('/unprotected', function*(next){
   this.body = "Anyone can access this area";
   yield next;
});

app.use(_.routes());
app.listen(3000);

모든 인증 관련 오류를 처리하기 위해 오류 처리 미들웨어를 만들었습니다. 그런 다음 2 개의 경로를 만들었습니다.

  • /protected−이 경로는 사용자가 올바른 인증 헤더를 전송 한 경우에만 액세스 할 수 있습니다. 다른 모든 경우에는 오류가 발생합니다.

  • /unprotected −이 경로는 인증 여부에 관계없이 누구나 액세스 할 수 있습니다.

이제 인증 헤더없이 또는 잘못된 자격 증명을 사용하여 / protected에 요청을 보내면 오류가 발생합니다. 예를 들면

$ curl https://localhost:3000/protected

다음과 같이 응답을 받게됩니다.

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic
Content-Type: text/plain; charset=utf-8
Content-Length: 28
Date: Sat, 17 Sep 2016 19:05:56 GMT
Connection: keep-alive

Please authenticate yourself

그러나 올바른 자격 증명을 사용하면 예상되는 응답을 얻을 수 있습니다. 예를 들면

$ curl -H "Authorization: basic QXl1c2g6SW5kaWE=" https://localhost:3000/protected -i

당신은 다음과 같은 응답을 받게 될 것입니다.

HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Content-Length: 38
Date: Sat, 17 Sep 2016 19:07:33 GMT
Connection: keep-alive

You have access to the protected area.

/ unprotected 경로는 여전히 모든 사람이 액세스 할 수 있습니다.

압축은 대역폭을 절약하고 사이트 속도를 높일 수있는 간단하고 효과적인 방법입니다. 최신 브라우저와 만 호환되며 사용자가 레거시 브라우저도 사용하는 경우주의해서 사용해야합니다.

서버에서 응답을 보낼 때 압축을 사용하면로드 시간을 크게 향상시킬 수 있습니다. 우리는라는 미들웨어를 사용할 것입니다.koa-compress 파일의 압축을 처리하고 적절한 헤더를 설정합니다.

계속해서 사용하여 미들웨어를 설치하십시오-

$ npm install --save koa-compress

이제 app.js 파일에 다음 코드를 추가하십시오.

var koa = require('koa');
var router = require('koa-router');
var app = koa();

var Pug = require('koa-pug');
var pug = new Pug({
   viewPath: './views',
   basedir: './views',
   app: app //Equivalent to app.use(pug)
});

app.use(compress({
   filter: function (content_type) {
      return /text/i.test(content_type)
   },
   threshold: 2048,
   flush: require('zlib').Z_SYNC_FLUSH
}));

var _ = router(); //Instantiate the router

_.get('/', getRoot);

function *getRoot(next){
   this.render('index');
}

app.use(_.routes()); //Use the routes defined using the router
app.listen(3000);

이것은 우리의 압축 미들웨어를 제자리에 놓습니다. 필터 옵션은 응답 내용 유형을 확인하여 압축 여부를 결정하는 기능입니다. 임계 값 옵션은 압축 할 최소 응답 크기 (바이트)입니다. 이렇게하면 모든 작은 응답을 압축하지 않습니다.

다음은 압축하지 않은 응답입니다.

다음은 압축과 유사한 응답입니다.

하단의 크기 탭을 보면 둘의 차이를 잘 알 수 있습니다. 파일을 압축하면 150 % 이상 향상됩니다.

캐싱은 후속 요청을 더 빠르게 만들기 위해 재사용 가능한 응답을 저장하는 용어입니다. 모든 브라우저는 HTTP 캐시 구현과 함께 제공됩니다. 우리가해야 할 일은 각 서버 응답이 브라우저가 응답을 캐시 할 수있는시기와 기간에 대해 브라우저에 지시하는 올바른 HTTP 헤더 지시문을 제공하는지 확인하는 것입니다.

다음은 웹 앱에 캐싱을 포함하는 몇 가지 이점입니다.

  • 네트워크 비용이 감소합니다. 콘텐츠가 캐시 된 경우 이후의 모든 요청에 ​​대해 더 적은 양을 보내야합니다.

  • 웹 사이트의 속도와 성능이 향상됩니다.

  • 클라이언트가 오프라인 상태 인 경우에도 콘텐츠를 사용할 수 있습니다.

koa-static-cache 미들웨어를 사용하여 앱에서 캐싱을 구현할 것입니다. 다음을 사용하여 이러한 미들웨어를 설치하십시오-

$ npm install --save koa-static-cache

app.js 파일로 이동하여 다음 코드를 추가하십시오.

var koa = require('koa');
var app = koa();

var path = require('path');
var staticCache = require('koa-static-cache');

app.use(staticCache(path.join(__dirname, 'public'), {
   maxAge: 365 * 24 * 60 * 60  //Add these files to caches for a year
}))

app.listen(3000);

그만큼 koa-static-cache미들웨어는 클라이언트 측에서 서버 응답을 캐시하는 데 사용됩니다. 그만큼cache-control헤더는 캐시 개체를 초기화하는 동안 제공하는 옵션에 따라 설정됩니다. 이 캐시 된 응답의 만료 시간을 1 년으로 설정했습니다. 다음은 파일을 캐시하기 전과 후에 보낸 요청을 비교 한 것입니다.

이 파일이 캐시되기 전에 반환 된 상태 코드는 200으로 정상입니다. 응답 헤더에는 캐시 할 콘텐츠에 대한 여러 정보가 있으며ETag 내용.

다음에 요청이 전송 될 때 ETtag와 함께 전송되었습니다. 우리의 콘텐츠가 서버에서 변경되지 않았기 때문에 해당 ETag도 동일하게 유지되었으며 클라이언트는 로컬에있는 사본이 서버가 제공하는 최신 정보이며 요청하는 대신 로컬을 사용해야한다고 들었습니다. 다시.

Note− 캐시 된 파일을 무효화하려면 파일 이름을 변경하고 참조를 업데이트하기 만하면됩니다. 이렇게하면 클라이언트에 보낼 새 파일이 있고 클라이언트는 캐시에서 파일을 다시로드 할 수 없습니다.

요청을 받고 있지만 어디에도 저장하지 않습니다. 데이터를 저장할 데이터베이스가 필요합니다. 우리는 유명한 NoSQL 데이터베이스를 사용할 것입니다.MongoDB. Mongo를 설치하고 읽으려면 이 링크로 이동하십시오.

Koa와 함께 Mongo를 사용하려면 노드에 대한 클라이언트 API가 필요합니다. 우리에게는 여러 가지 옵션이 있지만이 튜토리얼에서는 mongoose를 고수 할 것 입니다. 몽구스는document modelingMongoDB 용 Node. 문서 모델링이란Model (매우 class 문서 지향 프로그래밍에서), 그리고 우리는 documents 이 모델을 사용하여 documents of a classOOP에서). 모든 처리는 이러한 "문서"에서 수행되고 마지막으로 데이터베이스에 이러한 문서를 작성합니다.

몽구스 설정

이제 Mongo가 설치되었으므로 다른 노드 패키지를 설치하는 것과 같은 방법으로 mongoose를 설치하겠습니다.

$ npm install --save mongoose

mongoose를 사용하기 전에 Mongo 셸을 사용하여 데이터베이스를 만들어야합니다. 새 데이터베이스를 생성하려면 터미널을 열고 "mongo"를 입력하십시오. Mongo 셸이 시작되면 다음을 입력합니다.

use my_db

새 데이터베이스가 생성됩니다. Mongo 셸을 열 때마다 기본적으로 "test"db가 사용되며 위와 동일한 명령을 사용하여 데이터베이스로 변경해야합니다.

mongoose를 사용하려면 app.js 파일에서 필요로 한 다음 mongodb : // localhost에서 실행되는 mongod 서비스에 연결합니다.

var koa = require('koa');
var _ = require('koa-router')();
var app = koa();

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/my_db');

app.use(_.routes());
app.listen(3000);

이제 앱이 데이터베이스에 연결되었으므로 새 모델을 만들어 보겠습니다. 이 모델은 데이터베이스에서 컬렉션 역할을합니다. 새 모델을 생성하려면 경로를 정의하기 전에 다음 코드를 사용하십시오.

var koa = require('koa');
var _ = require('koa-router')();
var app = koa();

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/my_db');

var personSchema = mongoose.Schema({
   name: String,
   age: Number,
   nationality: String
});

var Person = mongoose.model("Person", personSchema);

app.use(_.routes());
app.listen(3000);

위의 코드는 사람의 스키마를 정의하고 몽구스 모델을 만드는 데 사용됩니다. Person.

문서 저장

이제 우리는 사람의 세부 사항을 가져 와서 데이터베이스에 저장할 새로운 html 양식을 만들 것입니다. 양식을 작성하려면 다음 컨텐츠가있는보기 디렉토리에 person.pug라는 새보기 파일을 작성하십시오.

html
   head
      title Person
   body
      form(action = "/person", method = "POST")
         div
            label(for = "name") Name: 
            input(name = "name")
         br
         div
            label(for = "age") Age: 
            input(name = "age")
         br
         div
            label(for = "nationality") Nationality: 
            input(name = "nationality")
         br
         button(type = "submit") Create new person

또한이 문서를 렌더링하기 위해 index.js에 새로운 get 경로를 추가합니다.

var koa = require('koa');
var _ = require('koa-router')();
var app = koa();

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/my_db');

var personSchema = mongoose.Schema({
   name: String,
   age: Number,
   nationality: String
});

var Person = mongoose.model("Person", personSchema);

_.get('/person', getPerson);

function *getPerson(next){
   this.render('person');
   yield next;
}

app.use(_.routes());
app.listen(3000);

localhost : 3000 / person으로 이동하여 양식이 올바르게 표시되는지 확인하십시오. 이것은 단지 UI 일뿐 아직 작동하지 않습니다. 이것이 우리 양식의 모습입니다.

이제이 요청을 처리 할 '/ person'에 포스트 라우트 핸들러를 정의합니다.

var koa = require('koa');
var _ = require('koa-router')();
var app = koa();

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/my_db');

var personSchema = mongoose.Schema({
   name: String,
   age: Number,
   nationality: String
});

var Person = mongoose.model("Person", personSchema);

_.post('/person', createPerson);

function *createPerson(next){
   var self = this;
   var personInfo = self.request.body; //Get the parsed information
   
   if(!personInfo.name || !personInfo.age || !personInfo.nationality){
      self.render(
         'show_message', {message: "Sorry, you provided wrong info", type: "error"});
   } else {
      var newPerson = new Person({
         name: personInfo.name,
         age: personInfo.age,
         nationality: personInfo.nationality
      });
      yield newPerson.save(function(err, res) {
         if(err)
            self.render('show_message', 
               {message: "Database error", type: "error"});
         else
            self.render('show_message', 
               {message: "New person added", type: "success", person: personInfo});
      });
   }
}

app.use(_.routes());
app.listen(3000);

위 코드에서 빈 필드가 수신되거나 필드가 수신되지 않으면 오류 응답을 보냅니다. 그러나 올바른 형식의 문서를 받으면 Person 모델에서 newPerson 문서를 만들고 다음을 사용하여 DB에 저장합니다.newPerson.save()함수. 이것은 mongoose에서 정의되며 콜백을 인수로받습니다. 이 콜백에는 두 개의 인수가 있습니다.errorresponse. 그러면 show_message 뷰가 렌더링되므로이 뷰도 만들어야합니다.

이 경로의 응답을 표시하려면 show_message전망. 다음 코드로 새보기를 만듭니다.

html
   head
      title Person
   body
      if(type = "error")
         h3(style = "color:red") #{message}
      else
         h3 New person, name: 
            #{person.name}, age: 
            #{person.age} and nationality: 
            #{person.nationality} added!

다음은 성공적으로 양식 (show_message.pug)을 제출했을 때받는 응답입니다.

이제 사람을 만드는 인터페이스가 생겼습니다!

문서 검색

Mongoose는 문서 검색을위한 많은 기능을 제공하며 그중 세 가지에 초점을 맞출 것입니다. 이러한 모든 함수는 콜백을 마지막 매개 변수로 사용하며 저장 함수와 마찬가지로 해당 인수는 오류 및 응답입니다.

세 가지 기능은-

Model.find (조건, 콜백)

이 함수는 조건 개체의 필드와 일치하는 모든 문서를 찾습니다. Mongo에서 사용되는 동일한 연산자는 mongoose에서도 작동합니다. 예를 들어, 이것은 개인 컬렉션에서 모든 문서를 가져옵니다.

Person.find(function(err, response){
   console.log(response);
});

필드 이름이 "Ayush"이고 나이가 20 인 모든 문서를 가져옵니다.

Person.find({name: "Ayush", age: 20}, 
   function(err, response){
      console.log(response);
   });

우리는 또한 우리가 필요로하는 프로젝션, 즉 우리가 필요로하는 필드를 제공 할 수 있습니다. 예를 들어,names 그 사람들의 nationality이다 "인도" 우리는 사용 -

Person.find({nationality: "Indian"}, 
   "name", function(err, response) {
      console.log(response);
   });

Model.findOne (조건, 콜백)

이 함수는 항상 가장 관련성이 높은 단일 문서를 가져옵니다. Model.find ()와 동일한 인수를가집니다.

Model.findById (id, callback)

이 함수는 _id(mongo에 의해 정의 됨) 첫 번째 인수, 선택적 프로젝션 문자열 및 응답을 처리하기위한 콜백. 예를 들면

Person.findById("507f1f77bcf86cd799439011", 
   function(err, response){
      console.log(response);
   });

모든 사람 기록을 볼 수있는 경로를 만들어 보겠습니다.

var koa = require('koa');
var _ = require('koa-router')();
var app = koa();

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/my_db');

var personSchema = mongoose.Schema({
   name: String,
   age: Number,
   nationality: String
});

var Person = mongoose.model("Person", personSchema);

_.get('/people', getPeople);
function *getPeople(next){
   var self = this;
   
   yield Person.find(function(err, response){
      self.body = response;
   });
}
app.use(_.routes());
app.listen(3000);

문서 업데이트

Mongoose는 문서를 업데이트하는 세 가지 기능을 제공합니다.

Model.update (조건, 업데이트, 콜백)

이 함수는 조건을 취하고 개체를 입력으로 업데이트하고 컬렉션의 조건과 일치하는 모든 문서에 변경 사항을 적용합니다. 예를 들어, 다음 코드는 모든 Person 문서를 "American"국적을 갖도록 업데이트합니다.

Person.update({age: 25},
   {nationality: "American"}, 
   function(err, response){
      console.log(response);
   });

Model.findOneAndUpdate (조건, 업데이트, 콜백)

그것은 정확히 말하는 것을 수행합니다. 쿼리를 기반으로 한 문서를 찾고 두 번째 인수에 따라 업데이트합니다. 또한 마지막 인수로 콜백을받습니다. 예를 들면

Person.findOneAndUpdate({name: "Ayush"}, 
   {age: 40}, 
   function(err, response){
      console.log(response);
   });

Model.findByIdAndUpdate (id, 업데이트, 콜백)

이 함수는 ID로 식별되는 단일 문서를 업데이트합니다. 예를 들면

Person.findByIdAndUpdate("507f1f77bcf86cd799439011", 
   {name: "James"}, 
   function(err, response){
      console.log(response);
   });

사람들을 업데이트하는 경로를 만들어 보겠습니다. 이것은 매개 변수로 id와 페이로드의 세부 사항이있는 PUT 경로입니다.

var koa = require('koa');
var _ = require('koa-router')();
var app = koa();
var mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/my_db');

var personSchema = mongoose.Schema({
   name: String,
   age: Number,
   nationality: String
});

var Person = mongoose.model("Person", personSchema);

_.put('/people/:id', updatePerson);

function *updatePerson() {
   var self = this;
   yield Person.findByIdAndUpdate(self.params.id, 
      {$set: {self.request.body}}, function(err, response){
      
      if(err) {
         self.body = {
            message: "Error in updating person with id " + self.params.id};
      } else {
         self.body = response;
      }
   });
}

app.use(_.routes());
app.listen(3000);

이 경로를 테스트하려면 터미널에 다음을 입력하십시오 (ID를 생성 된 사람의 ID로 대체).

curl -X PUT --data "name = James&age = 20&nationality = American" https://localhost:3000/people/507f1f77bcf86cd799439011

위의 세부 정보로 경로에 제공된 ID와 관련된 문서가 업데이트됩니다.

문서 삭제

우리는 Create, Read 및 Update, 이제 mongoose를 사용하여 문서를 삭제하는 방법을 살펴 보겠습니다. 여기에는 업데이트와 똑같은 세 가지 기능이 있습니다.

Model.remove (조건, [콜백])

이 함수는 조건 개체를 입력으로 사용하고 조건과 일치하는 모든 문서를 제거합니다. 예를 들어 20 세의 모든 사람을 제거해야하는 경우

Person.remove({age:20});

Model.findOneAndRemove (조건, [콜백])

이 기능은 single, 조건 개체에 따라 가장 관련성이 높은 문서. 예를 들면

Person.findOneAndRemove({name: "Ayush"});

Model.findByIdAndRemove (id, [콜백])

이 함수는 ID로 식별되는 단일 문서를 제거합니다. 예를 들면

Person.findByIdAndRemove("507f1f77bcf86cd799439011");

이제 데이터베이스에서 사람을 삭제하는 경로를 만들어 보겠습니다.

var koa = require('koa');
var _ = require('koa-router')();
var app = koa();

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/my_db');

var personSchema = mongoose.Schema({
   name: String,
   age: Number,
   nationality: String
});

var Person = mongoose.model("Person", personSchema);

_.delete('/people/:id', deletePerson);
function *deletePerson(next){
   var self = this;
   yield Person.findByIdAndRemove(self.params.id, function(err, response){
      if(err) {
         self.body = {message: "Error in deleting record id " + self.params.id};
      } else {
         self.body = {message: "Person with id " + self.params.id + " removed."};
      }
   });
}

app.use(_.routes());
app.listen(3000);

이를 테스트하려면 다음 curl 명령을 사용하십시오.

curl -X DELETE https://localhost:3000/people/507f1f77bcf86cd799439011

이렇게하면 다음 메시지를 생성하는 주어진 ID를 가진 사람이 제거됩니다. −

{message: "Person with id 507f1f77bcf86cd799439011 removed."}

이것은 MongoDB, mongoose 및 Koa를 사용하여 간단한 CRUD 애플리케이션을 만드는 방법을 요약합니다. 몽구스를 더 자세히 알아 보려면 API 문서를 읽어 보세요.

모바일 애플리케이션, 단일 페이지 애플리케이션을 만들고 AJAX 호출을 사용하고 클라이언트에 데이터를 제공하려면 API가 필요합니다. 이러한 API와 엔드 포인트를 구조화하고 이름을 지정하는 방법에 대한 인기있는 아키텍처 스타일을REST(Representational Transfer State). HTTP 1.1은 REST 원칙을 염두에두고 설계되었습니다. REST는Roy Fielding 2000 년 그의 논문 Fielding Dissertations에서.

RESTful URI와 메서드는 요청을 처리하는 데 필요한 거의 모든 정보를 제공합니다. 다음 표에는 다양한 동사를 사용하는 방법과 URI의 이름을 지정하는 방법이 요약되어 있습니다. 마지막으로 영화 API를 만들 예정이므로 어떻게 구성할지 논의 해 보겠습니다.

방법 URI 세부 함수
가져 오기 /영화 산업 안전하고 캐서 블 모든 영화 목록과 세부 정보를 가져옵니다.
가져 오기 / movies / 1234 안전하고 캐서 블 영화 ID 1234의 세부 사항을 가져옵니다.
우편 /영화 산업 N / A 제공된 세부 정보를 사용하여 새 영화를 만듭니다. 응답에는 새로 생성 된 리소스의 URI가 포함됩니다.
놓다 / movies / 1234 멱 등성 영화 ID 1234를 수정합니다 (아직 존재하지 않는 경우 생성). 응답에는 새로 생성 된 리소스의 URI가 포함됩니다.
지우다 / movies / 1234 멱 등성 영화 ID 1234가있는 경우 삭제해야합니다. 응답에는 요청 상태가 포함되어야합니다.
DELETE 또는 PUT /영화 산업 유효하지 않음 유효하지 않아야합니다. DELETE 및 PUT는 작업중인 리소스를 지정해야합니다.

이제 Koa에서이 API를 만들어 보겠습니다. JavaScript에서 작업하기 쉽고 다른 많은 이점이 있으므로 JSON을 전송 데이터 형식으로 사용할 것입니다. index.js 파일을 다음으로 바꿉니다.

INDEX.JS

var koa = require('koa');
var router = require('koa-router');
var bodyParser = require('koa-body');

var app = koa();

//Set up body parsing middleware
app.use(bodyParser({
   formidable:{uploadDir: './uploads'},
   multipart: true,
   urlencoded: true
}));

//Require the Router we defined in movies.js
var movies = require('./movies.js');

//Use the Router on the sub route /movies
app.use(movies.routes());

app.listen(3000);

이제 애플리케이션을 설정 했으므로 API 생성에 집중하겠습니다. 먼저 movies.js 파일을 설정하십시오. 우리는 영화를 저장하는 데 데이터베이스를 사용하지 않고 메모리에 저장하고 있으므로 서버가 다시 시작할 때마다 추가 한 영화가 사라집니다. 이것은 데이터베이스 또는 파일 (node ​​fs 모듈 사용)을 사용하여 쉽게 모방 할 수 있습니다.

koa-router를 가져오고 라우터를 만들고 module.exports를 사용하여 내 보냅니다.

var Router = require('koa-router');
var router = Router({
  prefix: '/movies'
});  //Prefixed all routes with /movies

var movies = [
   {id: 101, name: "Fight Club", year: 1999, rating: 8.1},
   {id: 102, name: "Inception", year: 2010, rating: 8.7},
   {id: 103, name: "The Dark Knight", year: 2008, rating: 9},
   {id: 104, name: "12 Angry Men", year: 1957, rating: 8.9}
];

//Routes will go here

module.exports = router;

GET 경로

모든 영화를 가져 오기위한 GET 경로를 정의하십시오.

router.get('/', sendMovies);
function *sendMovies(next){
   this.body = movies;
   yield next;
}

그게 다야. 이것이 잘 작동하는지 테스트하려면 앱을 실행 한 다음 터미널을 열고 다음을 입력하십시오.

curl -i -H "Accept: application/json" -H "Content-Type: application/json" -X GET localhost:3000/movies

다음과 같은 응답을 받게됩니다.

[{"id":101,"name":"Fight 
Club","year":1999,"rating":8.1},{"id":102,"name":"Inception","year":2010,"rating":8.7},
{"id":103,"name":"The Dark Knight","year":2008,"rating":9},{"id":104,"name":"12 Angry 
Men","year":1957,"rating":8.9}]

모든 영화를 볼 수있는 방법이 있습니다. 이제 ID로 특정 영화를 가져 오는 경로를 만들어 보겠습니다.

router.get('/:id([0-9]{3,})', sendMovieWithId);

function *sendMovieWithId(next){
   var ctx = this;
   var currMovie = movies.filter(function(movie){
      if(movie.id == ctx.params.id){
         return true;
      }
   });
   if(currMovie.length == 1){
      this.body = currMovie[0];
   } else {
      this.response.status = 404;//Set status to 404 as movie was not found
      this.body = {message: "Not Found"};
   }
   yield next;
}

이것은 우리가 제공하는 id에 따라 우리에게 영화를 얻을 것입니다. 이를 테스트하려면 터미널에서 다음 명령을 사용하십시오.

curl -i -H "Accept: application/json" -H "Content-Type: application/json" -X GET localhost:3000/movies/101

당신은 다음과 같은 응답을 받게 될 것입니다.

{"id":101,"name":"Fight Club","year":1999,"rating":8.1}

잘못된 경로를 방문하면 GET 할 수 없음 오류가 발생하고, 존재하지 않는 ID로 유효한 경로를 방문하면 404 오류가 발생합니다.

우리는 GET 경로로 끝났습니다. 이제 POST 경로로 이동하겠습니다.

POST 경로

POST 된 데이터를 처리하려면 다음 경로를 사용하십시오.

router.post('/', addNewMovie);

function *addNewMovie(next){
   //Check if all fields are provided and are valid:
   if(!this.request.body.name || 
      !this.request.body.year.toString().match(/^[0-9]{4}$/g) || 
      !this.request.body.rating.toString().match(/^[0-9]\.[0-9]$/g)){
      
      this.response.status = 400;
      this.body = {message: "Bad Request"};
   } else {
      var newId = movies[movies.length-1].id+1;
      
      movies.push({
         id: newId,
         name: this.request.body.name,
         year: this.request.body.year,
         rating: this.request.body.rating
      });
      this.body = {message: "New movie created.", location: "/movies/" + newId};
   }
   yield next;
}

그러면 새 영화가 만들어져 movies 변수에 저장됩니다. 이 경로를 테스트하려면 터미널에 다음을 입력하십시오.

curl -X POST --data "name = Toy%20story&year = 1995&rating = 8.5" 
https://localhost:3000/movies

다음과 같은 응답을 받게됩니다.

{"message":"New movie created.","location":"/movies/105"}

이것이 movies 객체에 추가되었는지 테스트하려면 / movies / 105에 대한 get 요청을 다시 실행하십시오. 다음과 같은 응답을 받게됩니다.

{"id":105,"name":"Toy story","year":"1995","rating":"8.5"}

PUT 및 DELETE 경로를 생성 해 보겠습니다.

PUT 경로

PUT 경로는 POST 경로와 거의 동일합니다. 업데이트 / 생성 할 개체의 ID를 지정합니다. 다음과 같은 방법으로 경로를 만듭니다-

router.put('/:id', updateMovieWithId);

function *updateMovieWithId(next){
   //Check if all fields are provided and are valid:
   if(!this.request.body.name || 
      !this.request.body.year.toString().match(/^[0-9]{4}$/g) || 
      !this.request.body.rating.toString().match(/^[0-9]\.[0-9]$/g) ||
      !this.params.id.toString().match(/^[0-9]{3,}$/g)){
      
      this.response.status = 400;
      this.body = {message: "Bad Request"};
   } else {
      //Gets us the index of movie with given id.
      var updateIndex = movies.map(function(movie){
         return movie.id;
      }).indexOf(parseInt(this.params.id));
      
      if(updateIndex === -1){
         //Movie not found, create new movies.push({
            id: this.params.id,
            name: this.request.body.name,
            year: this.request.body.year,
            rating: this.request.body.rating
         });
         this.body = {message: "New movie created.", location: "/movies/" + this.params.id};    
      } else {
         //Update existing movie
         movies[updateIndex] = {
            id: this.params.id,
            name: this.request.body.name,
            year: this.request.body.year,
            rating: this.request.body.rating
         };
         this.body = {message: "Movie id " + this.params.id + " updated.", location: "/movies/" + this.params.id};
      }
   }
}

이 경로는 위 표에서 지정한 기능을 수행합니다. 존재하는 경우 새로운 세부 정보로 개체를 업데이트합니다. 존재하지 않는 경우 새 개체를 만듭니다. 이 경로를 테스트하려면 다음 curl 명령을 사용하십시오. 기존 영화를 업데이트합니다. 새 영화를 만들려면 ID를 존재하지 않는 ID로 변경하면됩니다.

curl -X PUT --data "name = Toy%20story&year = 1995&rating = 8.5" 
https://localhost:3000/movies/101

응답

{"message":"Movie id 101 updated.","location":"/movies/101"}

경로 삭제

다음 코드를 사용하여 삭제 경로를 만듭니다.

router.delete('/:id', deleteMovieWithId);

function *deleteMovieWithId(next){
   var removeIndex = movies.map(function(movie){
      return movie.id;
   }).indexOf(this.params.id); //Gets us the index of movie with given id.
   
   if(removeIndex === -1){
      this.body = {message: "Not found"};
   } else {
      movies.splice(removeIndex, 1);
      this.body = {message: "Movie id " + this.params.id + " removed."};
   }
}

다른 사람들에게했던 것과 같은 방식으로 경로를 테스트합니다. 성공적으로 삭제되면 (예 : ID 105) 다음과 같이 표시됩니다.

{message: "Movie id 105 removed."}

마지막으로 movies.js 파일은 다음과 같습니다.

var Router = require('koa-router');
var router = Router({
   prefix: '/movies'
});  //Prefixed all routes with /movies
var movies = [
   {id: 101, name: "Fight Club", year: 1999, rating: 8.1},
   {id: 102, name: "Inception", year: 2010, rating: 8.7},
   {id: 103, name: "The Dark Knight", year: 2008, rating: 9},
   {id: 104, name: "12 Angry Men", year: 1957, rating: 8.9}
];

//Routes will go here
router.get('/', sendMovies);
router.get('/:id([0-9]{3,})', sendMovieWithId);
router.post('/', addNewMovie);
router.put('/:id', updateMovieWithId);
router.delete('/:id', deleteMovieWithId);

function *deleteMovieWithId(next){
   var removeIndex = movies.map(function(movie){
      return movie.id;
   }).indexOf(this.params.id); //Gets us the index of movie with given id.
   
   if(removeIndex === -1){
      this.body = {message: "Not found"};
   } else {
      movies.splice(removeIndex, 1);
      this.body = {message: "Movie id " + this.params.id + " removed."};
   }
}

function *updateMovieWithId(next) {
   //Check if all fields are provided and are valid:
   if(!this.request.body.name ||
      !this.request.body.year.toString().match(/^[0-9]{4}$/g) ||
      !this.request.body.rating.toString().match(/^[0-9]\.[0-9]$/g) ||
      !this.params.id.toString().match(/^[0-9]{3,}$/g)){
      
      this.response.status = 400;
      this.body = {message: "Bad Request"};
   } else {
      //Gets us the index of movie with given id.
      var updateIndex = movies.map(function(movie){
         return movie.id;
      }).indexOf(parseInt(this.params.id));
      
      if(updateIndex === -1){
         //Movie not found, create new
         movies.push({
            id: this.params.id,
            name: this.request.body.name,
            year: this.request.body.year,
            rating: this.request.body.rating
         });
         this.body = {message: "New movie created.", location: "/movies/" + this.params.id};
      } else {
         //Update existing movie
            movies[updateIndex] = {
            id: this.params.id,
            name: this.request.body.name,
            year: this.request.body.year,
            rating: this.request.body.rating
         };
         this.body = {message: "Movie id " + this.params.id + " updated.", 
            location: "/movies/" + this.params.id};
      }
   }
}

function *addNewMovie(next){
   //Check if all fields are provided and are valid:
   if(!this.request.body.name ||
      !this.request.body.year.toString().match(/^[0-9]{4}$/g) ||
      !this.request.body.rating.toString().match(/^[0-9]\.[0-9]$/g)){
      
      this.response.status = 400;
      this.body = {message: "Bad Request"};
   } else {
      var newId = movies[movies.length-1].id+1;
      
      movies.push({
         id: newId,
         name: this.request.body.name,
         year: this.request.body.year,
         rating: this.request.body.rating
      });
      this.body = {message: "New movie created.", location: "/movies/" + newId};
   }
   yield next;
}
function *sendMovies(next){
   this.body = movies;
   yield next;
}
function *sendMovieWithId(next){
   var ctx = this
   
   var currMovie = movies.filter(function(movie){
      if(movie.id == ctx.params.id){
         return true;
      }
   });
   if(currMovie.length == 1){
      this.body = currMovie[0];
   } else {
      this.response.status = 404;//Set status to 404 as movie was not found
      this.body = {message: "Not Found"};
   }
   yield next;
}
module.exports = router;

이것으로 REST API가 완성됩니다. 이제이 단순한 아키텍처 스타일과 Koa를 사용하여 훨씬 더 복잡한 애플리케이션을 만들 수 있습니다.

로깅은 웹 애플리케이션을 만들 때 정확히 어디에서 잘못되었는지 알려주기 때문에 매우 유용합니다. 우리는 또한 잘못된 일에 대한 컨텍스트를 얻고 동일한 해결책을 찾을 수 있습니다.

Koa에서 로그인을 활성화하려면 미들웨어가 필요합니다. koa-logger. 다음 명령을 사용하여 설치하십시오.

$ npm install --save-dev koa-logger

이제 애플리케이션에서 다음 코드를 추가하여 로깅을 활성화합니다.

var logger = require('koa-logger')
var koa = require('koa')

var app = koa()
app.use(logger())

app.use(function*(){
   this.body = "Hello Logger";
})

app.listen(3000)

이 서버를 실행하고 서버의 경로를 방문하십시오. 다음과 같은 로그가 표시되어야합니다.

이제 특정 경로 또는 요청에서 오류가 발생하는 경우 이러한 로그는 각 경로에서 무엇이 잘못되었는지 파악하는 데 도움이됩니다.

비계를 사용하면 쉽게 만들 수 있습니다. skeleton for a web application. 우리는 수동으로 공개 디렉토리를 생성하고, 미들웨어를 추가하고, 별도의 라우트 파일을 생성했습니다. 스캐 폴딩 도구가 이러한 모든 것을 설정하여 애플리케이션 빌드를 직접 시작할 수 있습니다.

우리가 사용할 스캐 폴더는 Yeoman. Node.js 용으로 빌드 된 스캐 폴딩 도구이지만 여러 다른 프레임 워크 (예 : 플라스크, 레일, 장고 등)를위한 생성기도 있습니다. yeoman을 설치하려면 터미널에 다음 명령을 입력하십시오.

$ npm install -g yeoman

Yeoman은 발전기를 사용하여 응용 프로그램을 비계합니다. npm에서 yeoman과 함께 사용할 수있는 발전기를 확인하려면 여기로 이동하십시오 . 이 자습서에서는 'generator-koa'를 사용합니다. 이 생성기를 설치하려면 터미널에 다음 명령을 입력하십시오.

$ npm install -g generator-koa

이 생성기를 사용하려면 다음을 입력하십시오.

yo koa

그런 다음 디렉터리 구조를 생성하고 다음 파일을 생성합니다. 또한 필요한 npm 모듈과 bower 구성 요소를 설치합니다.

create package.json
create test/routeSpec.js
create views/layout.html
create views/list.html
create public/styles/main.css
create public/scripts/.gitkeep
create controllers/messages.js
create app.js
create .editorconfig
create .jshintrc

I'm all done. Running npm install & bower install for you to install 
the required dependencies. 
If this fails, try running the command yourself.

이 생성기는 우리에게 매우 간단한 구조를 만듭니다.

.
├── controllers
│   └── messages.js
├── public
|   ├── scripts
|   └── styles
|       └── main.css    
├── test
|   └── routeSpec.js
├── views
|   ├── layout.html
|   └── list.html
├── .editorconfig
├── .jshintrc
├── app.js
└── package.json

Koa에 사용할 수있는 많은 생성기를 탐색하고 적합한 생성기를 선택하십시오. 모든 생성기를 사용하는 단계는 동일합니다. 생성기를 설치하고 yeoman을 사용하여 실행해야하며 몇 가지 질문을 한 다음 답변을 기반으로 응용 프로그램의 스켈레톤을 생성해야합니다.

다음은이 튜토리얼을 개발하는 동안 사용한 리소스 목록입니다.

  • Koajs.com

  • Koajs- 예제 커뮤니티에서 만든 예제 목록

  • 공식 3 목록 번째 파티 미들웨어.

  • koa.js를 사용하는 CRUD API - Koa.js 에서 CRUD API를 만드는 과정을 보여주는 짧은 스크린 캐스트

  • Koa.js 빠른 시작 스크린 캐스트

  • Koa.js 및 생성기 소개