简体   繁体   中英

How to make api endpoint target user's localhost when deployed to Heroku

I have this api which works fine when running locally. But, once it is deployed to Heroku i get a error 503 which is because it tries to target localhost on Heroku's server and not the user's localhost. Is there a way to make this target the user's localhost instead?

The frontend is React. Here's the code in React that fetches this api every 5sec.

axiosFunc = () => {
    const { user } = this.props.auth;
    console.log(user);
    axios.get(`api/avaya/${user.id}`).then((res) => console.log(res));
  };

  timer = (time) => {
    const date = new Date(time);
    return `${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`;
  };

  componentDidMount() {
    this.axiosFunc();
    this.interval = setInterval(this.axiosFunc, 5000);
  }

  componentWillUnmount() {
    clearInterval(this.interval);
  }

and this is the API on the backend with express

const router = require("express").Router();
const xml2js = require("xml2js");
const Avaya = require("../../models/Avaya");
const User = require("../../models/User");

router.route("/:id").get(async (req, res) => {
  const user = await User.findById(req.params.id);
  const axios = require("axios");

  axios({
    method: "post",
    baseURL: `http://127.0.0.1:60000/onexagent/api/registerclient?name=${user.username}`,
    timeout: 2000,
  })
    .then((reg) => {
      xml2js
        .parseStringPromise(reg.data, { mergeAttrs: true })
        .then((result) => {
          if (result.RegisterClientResponse.ResponseCode[0] === "0") {
            const clientId = result.RegisterClientResponse.ClientId[0];
            user.avayaClientId = clientId;
            user.save();
          }
          const clientId = user.avayaClientId;
          axios({
            method: "post",
            url: `http://127.0.0.1:60000/onexagent/api/nextnotification?clientid=${clientId}`,
          }).then((notification) => {
            xml2js
              .parseStringPromise(notification.data, { mergeAttrs: true })
              .then((result) => {
                const notifType = [];
                const notifDetails = [];

                for (let i in result.NextNotificationResponse) {
                  notifType.push(i);
                }

                const arranged = {
                  NotificationType: notifType[1],
                  ResponseCode:
                    result.NextNotificationResponse[notifType[0]][0],
                };

                for (let i in result.NextNotificationResponse[
                  notifType[1]
                ][0]) {
                  notifDetails.push(i);
                }

                for (let i = 0; i < notifDetails.length; i++) {
                  arranged[[notifDetails[i]][0]] =
                    result.NextNotificationResponse[notifType[1]][0][
                      notifDetails[i]
                    ][0];
                }

                for (let i in arranged) {
                  if ("Outbound" in arranged) {
                    arranged.CallType = "Outbound";
                  } else if ("Inbound" in arranged)
                    arranged.CallType = "Inbound";
                  else {
                    arranged.CallType = " ";
                  }
                }

                if (
                  arranged.NotificationType === "VoiceInteractionCreated" ||
                  arranged.NotificationType === "VoiceInteractionMissed" ||
                  arranged.NotificationType === "VoiceInteractionTerminated"
                ) {
                  const newLogs = new Avaya({
                    notification: arranged,
                  });

                  newLogs.owner = user;

                  newLogs.save();

                  user.avayaNotifications.push(newLogs),
                    user
                      .save()
                      .then((logs) => res.json(logs))
                      .catch((err) => res.status(400).json("Error: " + err));
                } else {
                  res.send("Nothing to record");
                }
              });
          });
        });
    })
    .catch((err) => res.status(503).json(err));
});

router.route("/history/:username").get(async (req, res) => {
  const user = await User.findOne({ username: [`${req.params.username}`] });
  Avaya.find({ owner: [`${await user.id}`] }).then((user) => res.json(user));
});

module.exports = router;
 

EDIT: I was able to fix thanks to @Molda using fetch instead of axios doesn't result in cors error. New frontend code

  getLogs = async () => {
    const { user } = this.props.auth;
    const reg = await fetch(
      `http://127.0.0.1:60000/onexagent/api/registerclient?name=${user.id}`
    );

    let regData = await reg.text();
    let regxml = new XMLParser().parseFromString(regData);

    if (regxml.attributes.ResponseCode === "0") {
      axios.post(`/api/avaya/register/${user.id}`, regxml);
      console.log(regxml.attributes.ResponseCode);
    }

    let resp = await fetch(`/api/avaya/getid/${user.id}`);
    let clientId = await resp.text();

    let logs = await fetch(
      `http://127.0.0.1:60000/onexagent/api/nextnotification?clientid=${clientId}`
    );

    let data = await logs.text();
    var xml = new XMLParser().parseFromString(data);
    axios.post(`/api/avaya/getlogs/${user.id}`, xml);
  };

  timer = (time) => {
    const date = new Date(time);
    return `${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`;
  };

  componentDidMount() {
    this.getLogs();
    this.interval = setInterval(this.getLogs, 5000);
  }

New backend code:

const router = require("express").Router();
const Avaya = require("../../models/Avaya");
const User = require("../../models/User");

router.route("/register/:id").post(async (req, res) => {
  const user = await User.findById(req.params.id);
  const clientId = req.body.attributes.ClientId;
  user.avayaClientId = clientId;
  user.save();
});

router.route("/getid/:id").get(async (req, res) => {
  const user = await User.findById(req.params.id);
  res.send(user.avayaClientId);
});

router.route("/getlogs/:id").post(async (req, res) => {
  const user = await User.findById(req.params.id);

  const arranged = {
    NotificationType: req.body.children[0].name,
    ResponseCode: req.body.attributes.ResponseCode,
    CallType: " ",
  };

  for (let i in req.body.children[0].attributes) {
    if (i === "Outbound") {
      arranged.CallType = "Outbound";
    }
    if (i === "Inbound") {
      arranged.CallType = "Inbound";
    }
    arranged[i] = req.body.children[0].attributes[i];
  }

  console.log(arranged);

  if (
    arranged.NotificationType === "VoiceInteractionCreated" ||
    arranged.NotificationType === "VoiceInteractionMissed" ||
    arranged.NotificationType === "VoiceInteractionTerminated"
  ) {
    const newLogs = new Avaya({
      notification: arranged,
    });

    newLogs.owner = user;

    newLogs.save();

    user.avayaNotifications.push(newLogs),
      user
        .save()
        .then((logs) => res.json(logs))
        .catch((err) => res.status(400).json("Error: " + err));
  } else {
    res.send("Nothing to record");
  }
});

router.route("/history/:username").get(async (req, res) => {
  const user = await User.findOne({ username: [`${req.params.username}`] });
  Avaya.find({ owner: [`${await user.id}`] }).then((user) => res.json(user));
});

module.exports = router;

I really don't get the part of (requesting with Axios in API)
Is this a third party API?

But I suggest you to use (.env) which is a file in your root folder contains the development config like base URLs, expire tokens, API keys... etc and when you upload to Heroku you have to make a (.env) in Heroku app and but your config
Let's take an example

in my development mode, my.env looks like

app_url = localhost:4000
port = 4000
db = development_api
db_username = root
db_password = 
db_engine = mysql2

in my production mode, my.env looks like

app_url = http://appsomething.heroku.com
port = 80
db = production_api
db_username = root
db_password = 3210LDWAK@AALKQ
db_engine = mysql2

and read more about how to use .ENV

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM