FullStackOpen Part3-a Node.js and Express メモ
Nodeを使ってバックエンドを作成
npm initコマンドを適切なフォルダで実行しプロジェクトを作成
startで実行するコードを指定すればnpm startでそのまま実行できる
{
"name": "backend",
"version": "0.0.1",
"description": "",
"main": "index.js",
"scripts": {
"start": "node index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "Part3_backend"
},
"author": "Masa",
"license": "MIT"
}
Simple Web Server
関数定義の見方
引数: データ型 : 引数は必須で、指定されたデータ型である必要がある
引数?: データ型 | 別のデータ型 | ... : ?記号が付いている引数はオプショナル(任意)で、この引数を省略することも可能
(method) ServerResponse<IncomingMessage>.writeHead(
statusCode: number,
headers?: http.OutgoingHttpHeaders | http.OutgoingHttpHeader[] | undefined): http.ServerResponse<http.IncomingMessage> & {
...;
}
つまり
(method) オブジェクト<ジェネリクス>.関数名(必須引数: データ型, オプション引数?: データ型1 | データ型2 | undefined): 返り値
サーバーオブジェクトの作成は以下の通り
const http = require('http')
let notes =[{...}]
const app = http.createServer((request, response) => {
response.writeHead(200, {'Content-Type': 'application/json'})
response.end(JSON.stringify(notes))
})
const PORT =3001
app.listen(PORT)
console.log(`Server running on port ${PORT}`)
Express
Nodeの開発を楽にするライブラリ
npm install expressでインストール
以下のような感じで使う
const express = require('express')
const app = express()で定義して、app.listen(PORT, () => {})でリッスン
エンドポイントの定義はapp.getとかでやる
レスポンスはresponse.send(テキストまたはHTML)かresponse.json(オブジェクト)
自動でJSONstringifyしてくれる
const express = require('express')
const app = express()
let notes = [
...
]
app.get('/', (request, response) => {
response.send('<h1>Hello World!</h1>')
})
app.get('/api/notes', (request, response) => {
response.json(notes)
})
const PORT = 3001
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`)
})
Nodemon
Nodeアプリに変更を加えた際に自動で再起動して設定を反映してくれる
node install --save-dev nodemon
nodemonを起動するにはpackage.jsonに以下を加える
{
// ..
"scripts": {
"start": "node index.js",
"dev": "nodemon index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
// ..
}
そして"npm run dev"で実行
REST
Representational State Transfer
全てのリソースにはリソースの一意のURLが関連付けられる、というイメージ
一般的なイメージではこんな感じ
Fetching a single resource
Expressではコロン構文(/:id/など)を使ってルートのパラメータを定義できる
以下のような感じ
注意点
request.params.idはstring型なのでNumber型にキャストする必要あり
存在しないIDのnotesを取ろうとしたときはresponse.status(404).end()を返す
end()はデータがないときに返すもの
app.get('/api/notes/:id', (request, response) => {
const id = Number(request.params.id)
const note = notes.find(note => note.id === id)
if(note){
response.json(note)
}else{
response.status(404).end()
}
})
Postman
おなじみRESTクライアント
VSCode REST Client
こちらも便利。.rest拡張子のファイルを作れば利用できる
Receiving Data
app.use(express.json())を実行することで、ポストされたデータをJSONにパースすることができる
リクエストからデータを受け取るときはreq.bodyでアクセス
Postmanを使うときはBodyをrawにしてJSONを選択
全体としてはこんな感じ
const generateId = () => {
const maxId = notes.length > 0
? Math.max(...notes.map(n => n.id))
: 0
return maxId + 1
}
app.post('/api/notes', (request, response) => {
const body = request.body
if (!body.content) {
return response.status(400).json({
error: 'content missing'
})
}
const note = {
content: body.content,
important: body.important || false,
id: generateId(),
}
notes = notes.concat(note)
response.json(note)
})
Math.max(...notes.map(n => n.id))
mapでIDの配列にしているだけではmax関数を使えない
max関数は複数の引数を取るので、…を使って個別の数値に変換している
About HTTP Request Types
安全性(safety)と冪等性(idempotency)
安全性
GETリクエストがサーバーに影響を及ぼさないようにすること
冪等性
POST以外のHTTPリクエストでは、何度実行しても同じ結果であること
POSTは唯一安全でも冪等でもないリクエストである
いろんな種類のリクエストがあるが厳密に区別するものはない
Middleware
ミドルウェアとはリクエストとレスポンスのオブジェクトを処理するために使用できる機能
たとえばExpress json-parserなど(app.use(express.json())のこと)
ミドルウェアは自分でも定義できる, app.useで使用
3つパラメータを取る nextはパラメータとして渡された関数を最後に実行する
const requestLogger = (request, response, next) => {
console.log('Method:', request.method)
console.log('Path:', request.path)
console.log('Body:', request.body)
console.log('---')
next()
}
ミドルウェアはapp.use(express.json())の後に実行すること
この記事が気に入ったらサポートをしてみませんか?