React Express Routing работает локально, но не на Heroku - PullRequest
0 голосов
/ 04 ноября 2018

Я разработал приложение, которое использует файл роутера feedback.router.js . Я настроил сервер для импорта этого файла маршрутизатора и использования его для '/feedback' запросов.

Я использую различные маршруты GET, POST, DELETE, PUT для связи с базой данных. Локально мои запросы к приложениям направляются правильно и правильно интегрируются с моей базой данных. В моем файле server.js я прочитал другие вопросы и реализовал то, что, по моему мнению, должно быть использовано для рабочей версии. Когда я запускаю приложение на Heroku, ответ, который я получаю на любой запрос axios, выглядит как HTML-файл, который указывает, что маршрут не распознан, но мне не повезло определить ошибку. Я считаю, что правильно настроил базу данных для Heroku, хотя, возможно, проблема в этом.

Одна косвенная проблема, которую это выдвинуло на первый план, заключается в том, что я понятия не имею, как устранять неполадки этих типов запросов после развертывания на Heroku. Я подключил его к своему репозиторию на Github и не могу найти «серверный терминал», чтобы помочь в поиске ошибок. Любые советы о том, как решить эту проблему с Heroku, очень приветствуются.

ОБНОВЛЕНИЕ для включения журналов Heroku для запроса GET и POST:

2018-11-04T03: 20: 11.564616 + 00:00 геройку [роутер]: at = метод информации = POST путь = "/ обратная связь" хост = prime-feedback-app.herokuapp.com request_id = 65732134-d050-4f82-ab08-9d0764266cb3 fwd = "73.242.14.56" dyno = web.1 connect = 0ms service = 3ms status = 200 bytes = 2377 протокол = https

2018-11-04T03: 21: 05.866976 + 00:00 герою [роутер]: at = info method = GET path = "/ feedback" хозяйничать = prime-feedback-app.herokuapp.com request_id = 6b1b7341-5dbf-443d-bff4-e0a6e3080e51 fwd = "73.242.14.56" dyno = web.1 connect = 0ms service = 3ms status = 200 bytes = 2377 протокол = HTTPS

Я включил, какие файлы, я думаю, может быть полезен.

Структура файла (звездочки обозначают папки)

feedback-app
    **build**
    **public**
    **server**
        **modules**
             pool.js
        **routes**
             feedback.router.js
        server.js
    **src**
        **components**
             ...
        index.js
        registerServiceWorker.js
     data.sql
     package.json
     package-lock.json

пример моего запроса axios:

axios({
    method: 'GET',
    url: '/feedback'
}).then((response) => {
    console.log('response:',response);
    this.setState({
        display: 'all',
        feedback: response.data
    });
}).catch((error) => {
    console.log('error',error);
})

server.js

    const express = require('express');
    const app = express();
    const bodyParser = require('body-parser');
    const path = require('path');
    const PORT = process.env.PORT || 5000;
    const feedbackRouter = require('./routes/feedback.router');

    /** ---------- MIDDLEWARE ---------- **/
    app.use(bodyParser.json()); // needed for angular requests
    app.use(bodyParser.urlencoded({extended: true}));

    if (process.env.NODE_ENV === 'production') {
        // Exprees will serve up production assets
        app.use(express.static(path.join(__dirname, 'build')));

        // Express serve up index.html file if it doesn't recognize route
        app.get('*', (req, res) => {
          res.sendFile(path.join(__dirname, 'build', 'index.html'));
        });
    }

    /** ---------- EXPRESS ROUTES ---------- **/
    app.use('/feedback', feedbackRouter);

    /** ---------- START SERVER ---------- **/
    app.listen(PORT, () => {
        console.log('Listening on port: ', PORT);
    });

pool.js

const pg = require('pg');
const url = require('url');
let config = {};

if (process.env.DATABASE_URL) {
    // Heroku gives a url, not a connection object
    // https://github.com/brianc/node-pg-pool
    let params = url.parse(process.env.DATABASE_URL);
    let auth = params.auth.split(':');

    config = {
        user: auth[0],
        password: auth[1],
        host: params.hostname,
        port: params.port,
        database: params.pathname.split('/')[1],
        ssl: true, // heroku requires ssl to be true
        max: 10, // max number of clients in the pool
        idleTimeoutMillis: 30000, // how long a client is allowed to remain idle before being closed
    };

} else {
    // only change the things on the right side of the ||
    config = {
        user: process.env.PG_USER || null, //env var: PGUSER
        password: process.env.DATABASE_SECRET || null, //env var: PGPASSWORD
        host: process.env.DATABASE_SERVER || 'localhost', // Server hosting the postgres database
        port: process.env.DATABASE_PORT || 5432, //env var: PGPORT
        database: process.env.DATABASE_NAME || 'prime_feedback', //env var: PGDATABASE or the name of your database (e.g. database: process.env.DATABASE_NAME || 'koala_holla',)
        max: 10, // max number of clients in the pool
        idleTimeoutMillis: 30000, // how long a client is allowed to remain idle before being closed
    };
}

module.exports = new pg.Pool(config);

package.json

{
  "name": "react-reflection-board",
  "version": "0.1.0",
  "private": true,
  "proxy": "http://localhost:5000",
  "engines": {
    "npm": "6.4.1",
    "node": "10.11.0"
  },
  "dependencies": {
    "@material-ui/core": "^3.3.2",
    "@material-ui/icons": "^3.0.1",
    "axios": "^0.17.1",
    "bootstrap": "^4.1.3",
    "pg": "^7.4.1",
    "react": "^16.3.0",
    "react-confirm-alert": "^2.0.6",
    "react-dom": "^16.3.0",
    "react-progressbar": "^15.4.1",
    "react-redux": "^5.1.0",
    "react-router-dom": "^4.3.1",
    "react-scripts": "^2.1.1",
    "react-swal": "^3.0.0",
    "reactstrap": "^6.5.0",
    "recompose": "^0.30.0",
    "redux": "^4.0.1",
    "redux-logger": "^3.0.6",
    "serve": "^10.0.2"
  },
  "devDependencies": {
    "nodemon": "^1.18.5"
  },
  "scripts": {
    "dev": "react-scripts start",
    "start": "serve -s build",
    "build": "react-scripts build",
    "heroku-postbuild": "npm run build",
    "client": "react-scripts start",
    "server": "nodemon --watch server server/server.js",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  },
  "browserslist": [
    ">0.2%",
    "not dead",
    "not ie <= 11",
    "not op_mini all"
  ]
}

feedback.router.js

    const express = require('express');
    const router = express.Router();
    const pool = require('../modules/pool');

    // GET feedback
    router.get('/', (req, res) => {
        // Request all entered feedback and return them
        pool.query('SELECT * FROM feedback ORDER BY id DESC;')
            .then((result) => {
                res.send(result.rows);
            }).catch((error) => {
                console.log('Error GET /api/feedback', error);
                res.sendStatus(500);  
        });
    })

    // GET feedback
    router.get('/flagged', (req, res) => {
        // Request all entered feedback and return them
        pool.query('SELECT * FROM feedback WHERE flagged = true ORDER BY id DESC;')
            .then((result) => {
                res.send(result.rows);
            }).catch((error) => {
                console.log('Error GET /api/feedback/flagged', error);
                res.sendStatus(500);  
        });
    })

    // POST new feedback entry
    router.post('/', async (req, res) => {
        const client = await pool.connect();

        try {
            const {
                feeling,
                understanding,
                support,
                comments,
                flagged
            } = req.body;
            await client.query('BEGIN')
            const orderInsertResults = await client.query(`INSERT INTO feedback ("feeling","understanding","support","comments","flagged")
            VALUES ($1, $2, $3, $4, $5);`, [feeling, understanding, support, comments, flagged]);

            await client.query('COMMIT')
            res.sendStatus(201);
        } catch (error) {
            await client.query('ROLLBACK')
            console.log('Error post /api/feedback', error);
            res.sendStatus(500);
        } finally {
            client.release()
        }
    });

    // DELETE a feedback entry
    router.delete('/:id', (req, res) => {
        pool.query('DELETE FROM feedback WHERE id=$1', [req.params.id]).then((result) => {
            res.sendStatus(200);
        }).catch((error) => {
            console.log('Error delete /api/feedback', error);
            res.sendStatus(500);
        })
    });

    // PUT / update a feedback entry
    router.put('/:id', (req,res) => {
        let feedbackId = req.params.id;
        let updatedFlagStatus = req.body.updatedFlagStatus;
        console.log('to update flag of item',feedbackId,'to',updatedFlagStatus);
        const sqlText = `UPDATE feedback SET flagged = $2 WHERE id=$1`;
        console.log('sqlText:',sqlText);
        pool.query(sqlText,[feedbackId, updatedFlagStatus])
            .then( (result) => {
                console.log('successfully updated flag status', result);
                res.sendStatus(200);
            })
            .catch( (error) => {
                console.log('error updating flag status', error);
                res.sendStatus(500);
            })
    })

    module.exports = router;

1 Ответ

0 голосов
/ 04 ноября 2018

Каждый раз, когда вы используете Express для обслуживания приложения React + ReactRouter, вы сталкиваетесь с такой ситуацией, когда Express маршрутизация и React Router "конфликтуют".

В производственных средах ваш сервер Express будет "обслуживать файл index.html, если он не распознает маршрут" , поэтому при запросе /feedback первое совпадение - это строка app.get('*'... Вот почему ваш Ajax-запрос на самом деле возвращает файл index.html.

if (process.env.NODE_ENV === 'production') {
    // Exprees will serve up production assets
    app.use(express.static(path.join(__dirname, 'build')));

    // Express serve up index.html file if it doesn't recognize route
    app.get('*', (req, res) => {
      res.sendFile(path.join(__dirname, 'build', 'index.html'));
    });
}

/** ---------- EXPRESS ROUTES ---------- **/
app.use('/feedback', feedbackRouter);

Поместите строку app.use('/feedback', feedbackRouter); в начало строки, и она должна работать.

Теперь вы должны полностью установить Heroku Toolbelt https://devcenter.heroku.com/articles/heroku-cli, чтобы вы могли запустить heroku logs -t на своем терминале, чтобы иметь возможность отлаживать ваш серверный код.

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...