NestJSをAPI Gateway + AWS Lambdaで構成する（その４）- ControllersコントローラーでDTO (Data Transfer Object)

#
- [その１ NestJSやLambdaでのnode.jsの話し](https://qiita.com/ssugimoto/items/988320d34022555401fb)
- [その２ NestJSのサンプルを動かす、Hello World.](https://qiita.com/ssugimoto/items/557e7a7cce5111bf5de7)
- [その３ コントローラーを追加する](https://qiita.com/ssugimoto/items/fcfbc9a176bcf41d7b45)
- その４ DTOを使う
- [その５ CRUD generatorを使い modules,controller, service, dto を生成する](https://qiita.com/ssugimoto/items/64a9c3cd5cb33e06f4c9)
- [その６ インターセプター](https://qiita.com/ssugimoto/items/dce542a78fdfbaf1e434)
- [その７ ORMでRDBデータベースを扱う](https://qiita.com/ssugimoto/items/45e23d1b2879b083267c)
- [その８ NestJSをAPI Gateway＋AWS Lambdaとしてデプロイ](https://qiita.com/ssugimoto/items/74c26a8219a944d4acc4)

# Controllers（コントローラー）のRequest payloads
## 公式 
https://docs.nestjs.com/controllers

ドキュメント原文
```
But first (if you use TypeScript), we need to determine the DTO (Data Transfer Object) schema. A DTO is an object that defines how the data will be sent over the network. We could determine the DTO schema by using TypeScript interfaces, or by simple classes. 

Interestingly, we recommend using classes here. Why?
Classes are part of the JavaScript ES6 standard, and therefore they are preserved as real entities in the compiled JavaScript. 
On the other hand, since TypeScript interfaces are removed during the transpilation, Nest can't refer to them at runtime. 
This is important because features such as Pipes enable additional possibilities when they have access to the metatype of the variable at runtime.
```

DeepLより
```
DTOスキーマを決定するには、TypeScriptのインターフェイスを使うか、単純なクラスを使う方法がある。興味深いことに、ここではクラスを使うことを推奨する。
なぜか？クラスはJavaScript ES6標準の一部であるため、コンパイルされたJavaScriptの中で実際のエンティティとして保存される。
一方、TypeScriptのインターフェイスはトランスパイル時に削除されるため、Nestは実行時にインターフェイスを参照できない。Pipesのような機能は、実行時に変数のメタタイプにアクセスすることで、さらなる可能性を可能にするため、これは重要である。
```

## DTOを作成する

- DTOはクライアントからのリクエストを受ける箱のようなもの、リクエストされた内容とクラスのフィールドを結びつけるのはWebフレームワーク側でやってくれる
- aws-node-typescript-nest/src/cats/create-cat.dto.ts
```create-cat.dto.ts
export class CreateCatDto {
  name: string;
  age: number;
  breed: string;
}
```

## create用のREST APIを追加する

- aws-node-typescript-nest/src/cats/cats.controller.ts
```cats.controller.ts
  @Post()
  create(@Req() request: Request, @Body() createCatDto: CreateCatDto) {

    console.log({ createCatDto });
    console.log(createCatDto.name + "," + createCatDto.age);
    return 'This action adds a new cat';
  }
```

### リクエストを送る

- Windowsのコマンドプロンプトの場合、postでデータを送る
```
curl -X POST --data-urlencode "name=太郎" -d "age=30" http://localhost:3000/dev/cats/

```

- API側のログ
```
ANY /dev/cats (λ: main)
{ createCatDto: { name: '太郎', age: '30' } }
太郎,30
(λ: main) RequestId: 55b8c4eb-8a99-42eb-9219-f393bd95ce4a  Duration: 4.82 ms  Billed Duration: 5 ms

```

- パターン１）windowsコマンドプロンプトでは json と その bodyで送るとエラーになる
```
curl -X POST -H "Content-Type: application/json" -d  "{ "name" : "佐藤" , "age" : "11"}" http://localhost:3000/dev/cats/
```

- パターン１）エラー
```
curl -X POST -H "Content-Type: application/json" -d  "{ "name" : "佐藤" , "age" : "11"}" http://localhost:3000/dev/cats/
{"statusCode":400,"error":"Bad Request","message":"Unexpected token n in JSON at position 2"}

```

- パターン２）
```
curl -X POST -H "Content-Type: application/json" -d  '{ "name" : "佐藤" , "age" : "11"}' http://localhost:3000/dev/cats/
```

- パターン２）エラー
```
C:\Users\shigeo.sugimoto>curl -X POST -H "Content-Type: application/json" -d  '{ "name" : "佐藤" , "age" : "11"}' http://localhost:3000/dev/cats/
curl: (6) Could not resolve host: name
curl: (3) URL using bad/illegal format or missing URL
curl: (6) Could not resolve host: xn--qqq934k
curl: (3) URL using bad/illegal format or missing URL
curl: (6) Could not resolve host: age
curl: (3) URL using bad/illegal format or missing URL
curl: (3) unmatched close brace/bracket in URL position 3:
11}'
  ^
```

- postmanからは json bodyで送って成功する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1482752/ac938677-afe2-7eea-1d1d-df904318051a.png)

```
{
    "name":"名前",
    "age":"10"
}
```

- postman実行
- API側のログ
```
ANY /dev/cats (λ: main)
{ createCatDto: { name: '名前', age: '10' } }
名前,10
(λ: main) RequestId: 33f7d2b6-e418-46e8-a0c6-1a3a90c89e2e  Duration: 6.16 ms  Billed Duration: 7 ms
```


- Windowsコマンドプロンプトでは json と その bodyで送るときにバックスラッシュ「\」でエスケープする
    - 'を"へ
    - "の前にエスケープのバックスラッシュ\を記述
```
curl -X POST -H "Content-Type: application/json" -d  "{\"name\" : \"佐藤\" , \"age\" : \"11\"}" http://localhost:3000/dev/cats/
```

- API側のログ
```
{ createCatDto: { name: '佐藤', age: '11' } }
佐藤,11
(λ: main) RequestId: a606e154-8436-4033-8478-543f8af31ce2  Duration: 275.65 ms  Billed Duration: 276 ms
```

## Route parameters, URIでパラメータ

- `http://localhost:3000/dev/cats/1` のように 1が意味のあるID等になる場合

```
Routes with parameters should be declared after any static paths. This prevents the parameterized paths from intercepting traffic destined for the static paths.
```
- aws-node-typescript-nest/src/cats/cats.controller.ts
```cats.controller.ts
  @Get(':id')
  findOne(@Param() params: any): string {
    console.log(params.id);
    return `This action returns a #${params.id} cat`;
  }
```

さらに単純に

```cats.controller.ts
  @Get(':id')
  findOne(@Param('id') id: string): string {
    console.log({ id });
    return `This action returns a #${id} cat`;
  }
```