Closed atsushi0124 closed 11 months ago
追記いたします。 2023/12/30 httpリクエストでDBに接続する方法は理解することができました。 しかし、ログイン後にどうやってログインしたトークンをメモの追加の際に取得できなくて、行き詰まってしまいました。
試したこと 最初に質問したコードのまま、Dockerを再起動したところ、エラーで401エラーが返ってくるようになりました。
キャプチャーは下記の通りです。 https://drive.google.com/file/d/1Ntyhrm1wWOPkJlxfdmDArKzQbv7f-kt4/view?usp=sharing ![Uploading スクリーンショット 2023-12-31 11.34.44.png…]()
わからないこと サインインで使用したトークンをメモを追加した際に mavs-task/backend/src/middleware/authenticate.js このファイルでトークンを管理していることが分かったのですが、なぜ、トークン情報を取得することができないのかがわからないです。
お手隙の際にご教示していただきたいです! よろしくお願いいたします。
上記の件に関して、「DB」ブランチというのを作成いただいていることを確認し、 こちらでも本事象が再現することと、解消出来ました!
🔸 トークンチェックに関して2点ほどアドバイス
backend/src/middleware/authenticate.js
おっしゃる通り、こちらでAPI実行時の共通処理としてトークンチェックを行っています。(=401エラー判定しているところ)
その中でconst token = req.headers.authorization;
が、実際のトークン取得をしている箇所となりますが、
意味としては、APIのリクエストヘッダー「authorization」を取得している(=トークン取得)
となります。
ですので、まず1点目としてはフロント側でAPIを実行する毎にリクエストヘッダーの付与が必要ということになります。
2点目はフロント側ではどこでトークンを管理しているか、ですが、
それはfrontend/src/pages/signin.vue
のサインイン処理を参照いただければ見つけることが出来ると思います!
その管理しているトークンをAPI実行毎に使用するイメージになります。
🔸 上記の対応が出来た後のハマりポイント
backend/src/routes/articles/articles.router.js
backend/src/services/articles/ArticleService.js
上記の2ファイルでそれぞれエラーが出るのがハマりポイントですが、
backend/src/routes/auth/auth.router.js
、および、backend/src/services/users/UserService.js
と見比べていただいて差異箇所を見つけていただけたらきっと解消出来るかと思います。
また以前にバックエンド側でconsole.log
でログ出力出来ないとおっしゃっていたと記憶していますが、
console.info
にするとバックエンド側もログ出力されると思いますので、調査等でお使いいただければと思います‥!
以上です!
お正月休みに、ご教示いただき、誠にありがとうございます! また、検証していたき、ありがとうございます!
ご教示していただいた箇所を試してみます!
また、わからないことがあれば、質問させていただきます!
先日のアドバイスで理解できたこと frontend/src/pages/signin.vueでトークンを保存しているところは理解することができました。 68行目の「userStore.token = response.token;」でuserStoreに保存しているということがわかりました。
何がわからないかというと、リクエストを送る際にヘッダー情報をつけて、送る方法を教えていただきたいです。
よろしくお願いいたします。
課題アプリではNuxt3のuseFetchを使用してAPIリクエストを行っています。
「Nuxt3 useFetch headers」で検索して出てきたページをいくつか送りますので、ご確認いただいて試してみていただければと思います‥! https://zenn.dev/mm67/articles/nuxt3-use-fetch https://shibayama-masaki.com/2023/04/01/nuxt3-useasyncdata-usefetch/ https://zenn.dev/airrnot1106/articles/d068cbd863af71
夜分遅くに対応していただき、ありがとうございます! また、参考資料の添付までしていただき、ありがとうございます!
いただいた参考資料をもとに調べながら課題に取り組みたいと思います!
試してわからなかった場合はまたお聞きします!
申し訳ありません... 昨日添付していただいた、サイトをもとに行ってみたのですが、わかりませんでした。
行ったこと https://zenn.dev/airrnot1106/articles/d068cbd863af71 この記事をもとに、下記コードを追加しました。
frontend/src/pages/createArticle.vue
// postのヘッダー情報の更新をできるようにする const authorization = computed(() =>
Bearer ${token}); const headers = computed(() => ({ authorization: authorization, })); console.log(headers.value);
このコードにより、トークンとヘッダー情報が固定にならないように管理しているところは理解できました。
そのコードを追記しても下記エラーが出てしまいました。 createArticle.vue:66 POST http://localhost:3001/articles/createArticle 401 (Unauthorized)
backend/src/routes/articles/articles.router.jsを見たところ クラスをインスタンス化を行っていなかったので、下記一行を追加いたしました。
const articleService = new ArticleService();
するとエラーが変わって、 createArticle.vue:66 POST http://localhost:3001/articles/createArticle net::ERR_CONNECTION_RESET になりました。
しかし、このコードを追加するとログインがなぜかできなくなってしまいました。 メモの追加ができなくなるのはわかるのですが、ログインできなくなるのはわからないです。
気になった箇所
useFetchの使い方はなんとなく理解できたのですが、signin.vueの50行目
const { data } = await useFetch
メモデータがDBに追加できなくて、困っています。 ArticleService.jsのcreateArticleを実行する際にuser_idの値が渡ってきている(ログには値がちゃんと入っています。)にもかかわらず、処理の方になると値がnullになってしまいます。
解決策がわからず、困っています。
試したこと 1.createArticle.vue `let memoId = 0; //メモIDを宣言し、初期化
// addMemoという名前の関数を定義
// この関数は、ユーザーが保存ボタンをクリックしたときに実行
// メモのタイトルと内容をログに出力し、APIを呼び出してメモを保存
const addMemo = handleSubmit(async () => {
try {
if (user_id) {
memoId += 1; //メモIDをカウント
}
// const { signin } = await useFetch${apiBaseUrl}/articles/createArticle
,
{
method: "POST",
headers: {
authorization: token,
},
body: JSON.stringify({
id: memoId, //追加
title: memoTitle.value,
content: memoDesc.value,
user_id: user_id, //追加
}),
}
);
console.log(data.value);
return memoId;
} catch (error) {
console.log(error);
}
});`
2.articles.router.js
router.post('/createArticle', authenticate, async (req, res, next) => { try { // // 認証用のトークン設定 // const token = req.headers.token; // const decode = jwt.verify(token, config.jwt.secret); // console.log(decode); const { id, title, content, user_id } = req.body; //id, title, content, userIdをreqに渡す console.info(
=========== ${id} =============================`); //フロントからデータが渡ってきているか確認
// 新しい記事を作成
const newArticle = await articleService.createArticle(id, title, content, user_id); //articleServiceにid, title, content, user_idを渡す
// 返却用データを生成
const body = {
id: newArticle.id,
title: newArticle.title,
content: newArticle.content,
user_id: newArticle.user_id,
created_at: newArticle.created_at,
};
console.log(body);
res.status(200).json(body);
} catch (error) { console.error(error); res.status(500).json({}); } });`
3.ArticleService.js
async createArticle(id, title, content, user_id, created_at) {
console.log(================= ${created_at} ========================
);
console.log(================= ${user_id} ========================
);
const newArticle = await db.Articles.create({
id,
title,
content,
user_id, //ここではnullになる
created_at,
});
return newArticle;
} /**
dockerのログになります。
2024-01-09 21:33:40 (Use node --trace-warnings ...
to show where the warning was created)
2024-01-09 21:33:41 API Server Start
2024-01-09 21:33:45 =========== 2 =============================
2024-01-09 21:33:45 ================= undefined ========================
2024-01-09 21:33:45 ================= 1 ========================
2024-01-09 21:33:45 Executing (default): INSERT INTO "articles" ("id","title","content","created_at","updated_at") VALUES ($1,$2,$3,$4,$5) RETURNING "id","title","content","author_id","created_at","updated_at","created_at","updated_at";
2024-01-09 21:33:45 Error
2024-01-09 21:33:45 at Query.run (/usr/src/backend/node_modules/sequelize/lib/dialects/postgres/query.js:50:25)
2024-01-09 21:33:45 at /usr/src/backend/node_modules/sequelize/lib/sequelize.js:315:28
2024-01-09 21:33:45 at processTicksAndRejections (node:internal/process/task_queues:96:5)
2024-01-09 21:33:45 at async PostgresQueryInterface.insert (/usr/src/backend/node_modules/sequelize/lib/dialects/abstract/query-interface.js:308:21)
2024-01-09 21:33:45 at async articles.save (/usr/src/backend/node_modules/sequelize/lib/model.js:2490:35)
2024-01-09 21:33:45 at async Function.create (/usr/src/backend/node_modules/sequelize/lib/model.js:1362:12)
2024-01-09 21:33:45 at async ArticleService.createArticle (file:///usr/src/backend/src/services/articles/ArticleService.js:29:24)
2024-01-09 21:33:45 at async file:///usr/src/backend/src/routes/articles/articles.router.js:22:24 {
2024-01-09 21:33:45 name: 'SequelizeDatabaseError',
2024-01-09 21:33:45 parent: error: null value in column "author_id" violates not-null constraint
2024-01-09 21:33:45 at Parser.parseErrorMessage (/usr/src/backend/node_modules/pg-protocol/dist/parser.js:287:98)
2024-01-09 21:33:45 at Parser.handlePacket (/usr/src/backend/node_modules/pg-protocol/dist/parser.js:126:29)
2024-01-09 21:33:45 at Parser.parse (/usr/src/backend/node_modules/pg-protocol/dist/parser.js:39:38)
2024-01-09 21:33:45 at Socket.node src/index.js
2024-01-09 21:45:50 (node:348) ExperimentalWarning: Importing JSON modules is an experimental feature. This feature could change at any time
2024-01-09 21:45:50 (Use node --trace-warnings ...
to show where the warning was created)
2024-01-09 21:45:50 API Server Start
画面キャプチャ https://drive.google.com/file/d/1Ntyhrm1wWOPkJlxfdmDArKzQbv7f-kt4/view?usp=drive_link
2点ほどお伝えいたします!
🔸DBにデータが追加出来ない件について 送っていただいたログに何故追加出来ないのか書いてあります。
・実行しようとしているSQL文
2024-01-09 21:33:45 sql: 'INSERT INTO "articles" ("id","title","content","created_at","updated_at") VALUES ($1,$2,$3,$4,$5) RETURNING "id","title","content","author_id","created_at","updated_at","created_at","updated_at";',
・実行した結果(エラーログ)
2024-01-09 21:33:45 original: error: null value in column "author_id" violates not-null constraint
上記のログを見ていただいて大体お察しがつくかと思いますが、
それに加えてテーブル定義も見ていただけると原因が分かるかと思います‥!
postgres/initdb/init.sql
🔸メモのIDについて
memoId += 1; //メモIDをカウント
というように自前でIDを作成していますが、こちらも同じくpostgres/initdb/init.sql
をご確認ください。
articlesテーブルのIDカラムはデータ型が「SERIAL」なので、INSERTの度にIDが採番されるので自前で設定する必要はありません!
https://postgresweb.com/post-5455
以上です!
コメントしていただきありがとうございます! いただいたエラー文の箇所をもう一度調べてみます!
また、メモIdは自動採番するとのこと承知いたしました! ありがとうございます!
お疲れ様です! DBに値を登録することができました!! 検証などをしていただき、ありがとうございました!!
このissueはクローズにさせていただきます!
行き詰まっているところ signin.vueを参考にcreateArticle.vueに書き換え、バックエンドの mavs-task/backend/src/routes/articles/articles.router.jsに接続できるように 「
${apiBaseUrl}/articles/createArticle
,」を追加したのですが、実際に接続できているのかの確認の方法がわからなくて、行き詰まっています。まずは、DBの接続を確認したいと思っているので、ご教示していただければ、幸いです。
画面のキャプチャです。 https://github.com/atsushi0124/mavs-task/assets/71283865/7521be7a-a9ce-40b9-b199-b2801275721f
下記に追加したコード記載いたします。
お手隙の際にご回答いただければ幸いです。
===================================================================
追記したコード frontend/src/pages/createArticle.vue `// フォームの設定 const { handleSubmit, isSubmitting } = useForm({ // バリデーションルール validationSchema: { email(value: string) { // 必須 if (!value) { return "タイトルを入力してください"; } return true; }, password(value: string) { if (!value) { return "内容を入力してください"; } return true; }, }, });
// フィールドの値とエラーメッセージを取得 const { value: memoTitle, errorMessage: emailErrorMessage } = useField("memoTitle"); const { value: memoDesc, errorMessage: passwordErrorMessage } = useField("memoDesc");
// addMemoという名前の関数を定義 // この関数は、ユーザーが保存ボタンをクリックしたときに実行されます const addMemo = handleSubmit(async () => { try { console.log(memoTitle.value, memoDesc.value); // ログインAPIを呼び出す -> /backend/src/routes/articles/createArticleを参照 const { data } = await useFetch(
${apiBaseUrl}/articles/createArticle
, { method: "POST", body: { title: memoTitle.value, content: memoDesc.value, }, } ); console.log(data); } catch (error) { console.log(error); } });`=================================================================== frontend/src/types/api.ts
export interface AddMemoResponse { title: string; content: string; }
===================================================================
backend/src/routes/articles/articles.router.js 既存のコードを使用 `import articleService from '../../services/articles/ArticleService.js'; import express from 'express'; import authenticate from '../../middleware/authenticate.js';
const router = express.Router();
/**
メモ新規登録 */ router.post('/createArticle', authenticate, async (req, res, next) => { try { // リクエストパラメーター const { title, content, created_at } = req.body;
// 新しい記事を作成 const newArticle = await articleService.createArticle('', title, content, created_at);
// 返却用データを生成 const body = { id: newArticle.id, title: newArticle.title, content: newArticle.content, created_at: newArticle.created_at, };
res.status(200).json(body); } catch (error) { console.error(error); res.status(500).json({}); } });
export default router;`