質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Heroku

HerokuはHeroku社が開発と運営を行っているPaaSの名称です。RubyやNode.js、Python、そしてJVMベース(Java、Scala、Clojureなど)の複数のプログラミング言語をサポートしている。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

Express

ExpressはNode.jsのWebアプリケーションフレームワークです。 マルチページを構築するための機能セットおよびハイブリッドのWebアプリケーションを提供します。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

Q&A

解決済

1回答

2279閲覧

heroku でデプロイしたAPIのresponseが htmlで返ってくる Node.js(Express) / React / Typescript / mongodb

shuya-tamaru

総合スコア26

Heroku

HerokuはHeroku社が開発と運営を行っているPaaSの名称です。RubyやNode.js、Python、そしてJVMベース(Java、Scala、Clojureなど)の複数のプログラミング言語をサポートしている。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

Express

ExpressはNode.jsのWebアプリケーションフレームワークです。 マルチページを構築するための機能セットおよびハイブリッドのWebアプリケーションを提供します。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

0グッド

0クリップ

投稿2022/06/09 07:33

前提

api → node.js (express) + typescript + DB mongodb
frontend → React + typescript
でアプリを作成

api → heroku
frontend → firebase
でデプロイしました。

データベースに保存済みの、データのリストを取得する処理において、本番環境にて問題が発生いたしました。

発生していること

本番環境で、responseがうまく取得できない。

frontendからapiに対して、ユーザーが紐づいているデータのリストを取得するためにrequestを送り、そのresponseのdataは、本来オブジェクトを格納したArray型↓
data: [ { }, { }, { }, .... ] でcontent-type : application/json; 返ってくるはずだったのですが、

以下の様に、

response.data

1data: "<!doctype html><html lang=\"en\"><head><meta charset=\"utf-8\"/><link rel=\"icon\" href=\"/favicon.ico\"/><meta name=\"viewport\" content=\"width=device-width,initi .............

といった感じで、content-type: "text/html; でreponseが返ってきてしまい、その後受け取ったデータをmap関数で展開する処理があるので、エラーを吐いてしまいます。

ローカル環境では、問題なくcontent-type : application/json; でArray型が返ってきてました。以下が、本来想定するresponseのdataです。

response.data

1[ 2 { 3 "_id": "628c35365b15252e6422c9ee", 4 "name": "ビル名1", 5 "buildingPath": "https://bbbbbbbbb", 6 "userId": [], 7 "companyId": "12345", 8 "createdAt": "2022-05-24T01:30:30.391Z", 9 "updatedAt": "2022-05-24T01:40:26.205Z", 10 "__v": 0 11 }, 12 { 13......省略 14 }, 15]

また、postmanを使用して、デプロイ済みのapiに対してrequestを送ったところ、こちらも問題なくcontent-type : application/json;でarray型が返ってきました。

本番環境においてうまく行かない原因が特定できず苦戦しております。
基本的な内容かもしれませんが、ご教授いただけると幸いです。

実現したいこと

本番環境において、herokuでデプロイしたAPIから、目的とする形式でresponse.dataを受け取りたい。

発生している問題・エラーメッセージ

エラーは発生しておらず、本番環境において、responseの形式が予期せぬものとなってしまっている。

該当のソースコード

API↓

users.ts

1import { Router } from "express"; 2import User from "../models/User"; 3import Building from "../models/Building"; 4 5const router = Router(); 6 7........省略 8 9// get user's all building 10router.get("/timeline/:id", async (req, res) => { 11 try{ 12 const currentUser = await User.findById(req.params.id); 13 const userBuildings = await Building.find({companyId: currentUser!.companyId}) 14 return res.status(200).json(userBuildings); 15 }catch(err){ 16 return res.status(403).json(err); 17 } 18}); 19 20export default router;

frontend ↓

BuildingList.tsx

1import React, { useState, useEffect } from 'react'; 2import { Link } from 'react-router-dom'; 3 4import styled from "styled-components"; 5import { AiOutlineMore } from 'react-icons/ai'; 6import axios from "axios"; 7 8import IBuilding from "../interface/IBuilding" 9 10const BuildingList: React.FC = () => { 11 12 const HEADERS = { 13 Accept: 'application/json', 14 'Content-Type': 'application/json' 15 }; 16 17 const [buildings, setBuildings] = useState<IBuilding[]>([]); 18 19 useEffect(() => { 20 const fetchBuildings = async () => { 21 const response = await axios.get( ###①ここでAPIにrequest 22 "/users/timeline/62874078c008a45d53c48981",{ 23 headers: HEADERS, 24 } 25 ); 26 setBuildings(response.data); ###②受け取ったresponse.dataをuseStateにセット。ここが本来はArrayだが、本番環境だとhtmlで返ってきてしまう。ローカルは問題なし。postman→deploy済みのAPIへも問題なし。 27 }; 28 fetchBuildings(); 29 }, []); 30 31 return ( 32 <SCenter> 33 <span>Building List</span> 34   ###③buildingsをmap関数で展開。本番環境だとここでエラーを吐いてしまう。ローカルだとちゃんとarray型でresponseが返ってきているので問題なし。 35 {buildings.map((building)=>( 36 <Sbuilding key={building._id}> 37 <SImage> 38 <Link to={`/building/${building._id}`}> 39 </Link> 40 </SImage> 41 42.........以下関係ないので省力します。 43 44 </Sbuilding> 45 ) 46}; 47 48.....以下 styled component 省略 49 50export default BuildingList

念のため↓
↓API側

server.ts

1import express from "express"; 2 3import userRoute from "./routes/users"; 4import authRoute from "./routes/auth"; 5import postRoute from "./routes/posts"; 6import buildingRoute from "./routes/building"; 7import uploadRoute from "./routes/upload"; 8 9import mongoose from 'mongoose'; 10import 'dotenv/config' 11 12// Connect to MongoDB 13mongoose 14 .connect(`${process.env.MONGOURL}`) 15 .then(() => { 16 console.log("connecting to DB..."); 17 }) 18 .catch((err: unknown) => { 19 console.log(err); 20 }); 21 22//middleware 23const app = express(); 24const PORT = 5000; 25 26app.use(express.json()); 27app.use("/api/users", userRoute); 28app.use("/api/auth", authRoute); 29app.use("/api/posts", postRoute); 30app.use("/api/buildings", buildingRoute); 31app.use("/api/upload", uploadRoute); 32 33app.listen( process.env.PORT || PORT, () => console.log("running server..."));

試したこと

requestを送る際に、headersで以下を指定してみましたが、特に影響なし。

const HEADERS = { Accept: 'application/json', 'Content-Type': 'application/json' }; const response = await axios.get( "/users/timeline/62874078c008a45d53c48981",{ headers: HEADERS, } );

補足情報(FW/ツールのバージョンなど)

[version]
express : 4.18.1
react : 18.1.0
typescript : 4.7.2

基本的な内容かもしれませんがご教授いただけますと幸いです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hoshi-takanori

2022/06/09 09:24

その HTML をブラウザで開いたらエラーメッセージが書いてあるのでは。(DB の接続とかかな…。)
shuya-tamaru

2022/06/09 10:26

コメントありがとうございます。 受け取ったデータを見てみたのですが、以下の様なものでした。 特に、エラーメッセージの様なものはなさそうでした・・・ もう一度、初めからデプロイの手順を見直してみようと思います。 <!doctype html> <html lang="en"> <head> <meta charset="utf-8"/> <link rel="icon" href="/favicon.ico"/> <meta name="viewport" content="width=device-width,initial-scale=1"/> <meta name="theme-color" content="#000000"/> <meta name="description" content="Web site created using create-react-app"/> <link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/> <title>React App</title> <script defer="defer" src="/static/js/main.3c11bf54.js"></script> <link href="/static/css/main.f2a43568.css" rel="stylesheet"> </head> <body> <noscript>You need to enable JavaScript to run this app.</noscript> <div id="root"></div> </body> </html>
shuya-tamaru

2022/06/09 10:28

ただ、ここの部分が気になるので、調べてみようと思います。 <noscript>You need to enable JavaScript to run this app.</noscript>
hoshi-takanori

2022/06/09 10:41

それは React アプリの index.html ですね。そして、api と react は別のサイトにデプロイしたようですが、それなら axios で API を叩く際には絶対パス (ホスト名か IP アドレスを含む URL) を指定する必要があるのでは。
shuya-tamaru

2022/06/09 10:57

おっしゃる通りでした、非常に基本的な間違いでハマっておりました。 大変お手間おかけいたしました。 ご回答いただき感謝いたします。 ありがとうございました。
shuya-tamaru

2022/06/09 11:01

もしお手間でなければ、回答欄に記載していただきたく、ベストアンサーに選ばせていただきたいと思っております。 お手間でしたら、こちらのやりとりで解決した旨を自己解決にて書かせていただきます。
guest

回答1

0

自己解決

質問への追記・修正依頼の欄にある様に、
hoshi-takanori様 からのご指摘通り、
apiへrequestを送る際のpathが間違っておりました。
本番環境では、apiとfrontを別ドメインでデプロイしているため、絶対パスで書く必要がありました。

投稿2022/06/10 06:42

shuya-tamaru

総合スコア26

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問