0

I have here an app that displays the location of the ISS on a map, and a user can send a message to the ISS which puts an icon where the ISS was when the message was sent.

It works wonderfully both when I start up the server and client locally and when I use the server to send the index.html page, but as soon as I deploy to Heroku, the requests to the server are failing and I cannot get the ISS location or add a message.

Here is my index.js file

const express = require("express");
const app = express();
const path = require("path");
const cors = require("cors");
const coords = require("./schema");
const axios = require("axios");
var moment = require("moment");
moment().format();

app.use(express.json());

app.use(cors("*"));

app.post("/message", (req, res) => {
  axios
    .get(
      `https://nominatim.openstreetmap.org/reverse?lat=${req.body.lat}&lon=${req.body.long}&format=json`
    )
    .then(({ data }) => {
      var testCoords = new coords({
        lat: req.body.lat,
        long: req.body.long,
        text: req.body.text,
        date: Date.now(),
        location: data.error ? "the ocean" : data.display_name
      });

      testCoords.save(err => {
        if (err) {
          console.log(err);
        } else {
          coords.find({}, (err, docs) => {
            res.status(200).send(docs);
          });
        }
      });
    });
});

app.get("/message", (req, res) => {
  coords.find({}, (err, docs) => {
    res.status(200).send(docs);
  });
});

app.use(express.static(`${__dirname}/../build`));

app.get("*", (req, res) => {
    process.env.PORT && res.sendFile(path.join(__dirname, "../build/index.html"));
});

app.listen(process.env.PORT || 3000, () => {
  console.log("Server started");
});


and my App.js client

import React, { Component } from "react";
import { Map, Marker, TileLayer, Popup } from "react-leaflet";
import axios from "axios";
import L from "leaflet";
import Form from "./Form";
import Moment from 'moment';
export default class App extends Component {
  constructor() {
    super();
    this.state = {
      lat: "",
      long: "",
      zoom: 10,
      messages: [],
      showForm: true
    };
  }

  componentDidMount = () => {
    axios.get("/message").then(res => {
      this.setState({
        messages: res.data
      });
      setInterval(this.getIss, 2500);
    });
  };

  postMessage = message => {
    axios
      .post("/message", {
        text: message,
        lat: this.state.lat,
        long: this.state.long
      })
      .then(res => {
        this.setState({
          messages: res.data,
          showForm: false
        });
      });
  };

  getIss = () => {
    axios.get("https://api.wheretheiss.at/v1/satellites/25544").then(res => {
      this.setState({
        lat: res.data.latitude,
        long: res.data.longitude
      });
    });
  };

  formatDate = date => { 
    return Moment(date)
      ._d.toString()
      .split(" ")
      .splice(0, 4)
      .join(" ");
  }
  render() {
    const myIcon = L.icon({
      iconUrl: require("./assets/ISS-sm.png"),
      iconSize: [64, 64],
      iconAnchor: [32, 64],
      popupAnchor: null,
      shadowUrl: null,
      shadowSize: null,
      shadowAnchor: null
    });

    const messages = this.state.messages.map(message => {
      return (
        <Marker position={[message.lat, message.long]}>
          <Popup>
            <div>
              <h1>{message.text}</h1>
              <p>{`${this.formatDate(message.date)} over ${message.location}`}</p>
            </div>
          </Popup>
        </Marker>
      );
    });
    return (
        <div>
          <Form postMessage={this.postMessage} show={this.state.showForm} />
          <Map center={[this.state.lat, this.state.long]} zoom={3}>
            <TileLayer
              url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
              attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
            />
            {messages}
            <Marker
              icon={myIcon}
              position={[this.state.lat, this.state.long]}
            />
          </Map>
        </div>
    );
  }
}

I get a 503 error.

I have tried sending a GET to https://myherokuapp.com/messages, but that also does not work. and I do not know how to get this thing to run properly.

Any help is appreciated.

1 Answer 1

2

I'm not really sure without knowing what's in "./schema", since that seems to be some sort of mapping/lat-long schema. Of course, when I ran your code, I got a Error: Cannot find module './schema' error, which... makes sense, since I don't have that file.

Keeping in mind that an error in your front-end code should not (usually!) return a 5xx error, your best bet in this case is to view the Heroku logs and see what's happening on the back-end.

To do this:

  1. Go to your Heroku dashboard for the app in question.
  2. In the top-right, click the "More" button, and then click "Restart all dynos. This isn't strictly necessary, but it'll help you by allowing you to pinpoint exactly when the problem(s) occurred.
  3. In your console, assuming you have the heroku CLI installed (if not, do that!) do heroku logs --app myherokuapp --tail, where myherokuapp is of course the name of your app.
  4. Try going to your (live) website, and take a look at the logs. Do they show anything?

In general, an HTTP 503 means "service unavailable", meaning that whatever server it is you're trying to reach is not responding, or otherwise, well, unavailable.

Some preliminary research shows that in a lot of cases, 503's can be the result of someone not having an appropriate dependency saved in their package.json file, so check that first: Try copying your project (except the node_modules folder!) to another folder, running npm install, and then npm start (or node index.js or whatever).

5
  • 1
    My ./schema is just this const mongoose = require("mongoose"); mongoose.connect("mongodb://localhost:27017/ISS", { useNewUrlParser: true, useUnifiedTopology: true }); var db = mongoose.connection; db.on("error", console.error.bind(console, "connection error:")); var coordsSchema = mongoose.Schema({ lat: Number, long: Number, text: String, date: Date, location: String }); module.exports = mongoose.model("ISS", coordsSchema); Ill go ahead and try out your solution tomorrow afternoon and report back, thanks a ton! Commented Dec 11, 2019 at 1:04
  • Hey, one possible issue i can see is the line mongoose.connect("mongodb://localhost:27017/ISS",.... If it's like that in your remote (i.e., heroku-hosted) version, then it's going to be trying to connect to a mongodb instance at localhost. That won't work; you'll need to use an external mongodb URI (I use mlab, personally).
    – Newms
    Commented Dec 12, 2019 at 3:02
  • Ok yeah I just created an external mongo db as you said, still not working, but I have also used the CLI to check whats going on, and it still break when trying to make a GET or POST to /message. It says the requests to /message are toming out. I've hosted with Heroku once before and didn't have this problem :( Commented Dec 12, 2019 at 22:51
  • Okay, then I'd suggest you start console.log-ing everything. In particular, I notice that if you get a non-falsey error (if (err) {...) in your /message POST route, then you do not send a response. Any time your route isn't responding correctly, console.log whatever it is your function(s) is (are) spitting out. On the other hand, try creating a test route (i.e., a GET route to /derp) that just spits out "Hello!". Does that work?
    – Newms
    Commented Dec 13, 2019 at 0:39
  • Okay! I figured it out and its working. The problem was my DB was only accepting data from my local IP. I needed to do some configuration to allow my heroku app to talk to the DB as well. Couldn't have figured this out without you, so if you leave a new answer and tell me to 1) set up an external mongo instance with mLab 2) whitelist my heroku app on said mongo instance I will go ahead and mark the answer as correct. Thanks a million. Commented Dec 16, 2019 at 15:34

Not the answer you're looking for? Browse other questions tagged or ask your own question.