Heroku + Node.js - 由于不同原因失败

时间:2021-01-11 18:11:23

标签: node.js api heroku

首先,感谢您花时间阅读本文。过去我的格式不是最好的,所以这次我会做得更好。

前言:我对 api/node.js 领域非常陌生,甚至对 heroku 也很陌生。我在互联网上搜索并应用了大约 30 次提交价值的更改,并取得了不同形式的成功。

我的问题是,有没有人对如何克服这个问题有任何建议、想法和指导? 2021-01-11T17:54:19.095682+00:00 heroku[router]: at=info method=GET path="/" host=november-td-ameri.herokuapp.com request_id=d2cb2e61-8b9c-4490 -928d-a41d1e9e9dcb fwd="85.217.133.162" dyno=web.1 connect=0ms service=20ms status=404 bytes=383 protocol=https

在这里你会找到我的package.json

  "name": "project1",
  "version": "1.0.0",
  "description": "Goal is to learn heroku/node/api.",
  "main": "app.js",
  "dependencies": {
    "express": "^4.17.1",
    "heroku": "^7.47.7",
    "http": "0.0.1-security",
    "nodemon": "^2.0.7",
    "puppeteer": "^5.5.0",
    "request": "^2.88.2"
  },
  "engines": {
    "node": ">= 13.5.0",
    "npm": ">= 6.13.4"
  },
  "devDependencies": {},
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "nodemon app.js",
    "start": "node app.js"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/Ztarlink/Project1.git"
  },
  "author": "",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/Ztarlink/Project1/issues"
  },
  "homepage": "https://github.com/Ztarlink/Project1#readme",
  "keywords": []
}

在这里您可以找到我的Procfile: web: node ./app.js

最后,这是我的 app.js 文件:

var http = require("http");
var request = require("request");
var express = require("express");
const puppeteer = require("puppeteer");
const fs = require("fs");
const detailsFileName = "./details.json";
var details = require(detailsFileName);
const Days90 = 7776000; // 90 days in seconds
const Minutes30 = 1800; // 30 mins in seconds

var app = express();
const redirect_uri = "http://november-td-ameri.herokuapp.com/auth";

/**
 * Callback endpoint the TDA app uses.
 * To understand more about how the API authenticates, see this link.
 * https://developer.tdameritrade.com/content/simple-auth-local-apps
 */
app.get("/auth", (req, res) => {
  var authRequest = {
    url: "https://api.tdameritrade.com/v1/oauth2/token",
    method: "POST",
    headers: {
      "Content-Type": "application/x-www-form-urlencoded",
    },
    form: {
      grant_type: "authorization_code",
      access_type: "offline",
      code: req.query.code, // get the code from url
      client_id: process.env.CLIENT_ID + "@AMER.OAUTHAP", // client id stored in heroku
      redirect_uri: redirect_uri,
    },
  };

  request(authRequest, function (error, response, body) {
    // If there's no errors
    if (!error && response.statusCode == 200) {
      // get the TDA response
      var authReply = JSON.parse(body);
      // to check it's correct, display it
      res.send(authReply);
    }
  });
});

app.get("/reset", (req, res) => {
  resetTokens().then(
    function (result) {
      res.send(result);
    },
    function (err) {
      res.send(err);
    }
  );
});

/**
 * Automatically fill in the login form to authenticate the TDA app
 * NB:
 * The refresh token expires in 90 days after creating
 * The access token expires in 30 minutes after creating
 */
async function resetTokens() {
  // Launch the browser
  const browser = await puppeteer.launch({
    args: ["--no-sandbox"],
  });
  const page = await browser.newPage();

  // Go to the authentication page
  await page.goto(
    `https://auth.tdameritrade.com/auth?response_type=code&redirect_uri=${encodeURI(
      redirect_uri
    )}&client_id=${process.env.CLIENT_ID}%40AMER.OAUTHAP`
  );

  // Enter username
  await page.click("#username");
  await page.keyboard.type(process.env.USERNAME);

  // Enter password
  await page.click("#password");
  await page.keyboard.type(process.env.PASSWORD);

  // Click login button
  await page.click("#accept");

  // Click allow button
  await page.click("#accept");

  // get the tokens from the pre element
  var elem = await page.$("pre");
  var text = await page.evaluate((elem) => elem.textContent, elem);

  // parse the response to a new object
  var jsonText = JSON.parse(text);
  console.log(jsonText);

  // update the details file object
  details.access_token = jsonText.access_token;
  details.refresh_token = jsonText.refresh_token;
  let time = Date().toString();
  details.access_last_update = time;
  details.refresh_last_update = time;

  // write the updated object to the details.json file
  fs.writeFile(
    detailsFileName,
    JSON.stringify(details, null, 2),
    function (err) {
      if (err) console.error(err);
    }
  );

  // Close browser
  await browser.close();

  // return the text
  return text;
}

/**
 * Reset the TDA access token
 */
function resetAccessToken() {
  var refresh_token_req = {
    url: "https://api.tdameritrade.com/v1/oauth2/token",
    method: "POST",
    headers: {
      "Content-Type": "application/x-www-form-urlencoded",
    },
    form: {
      grant_type: "refresh_token",
      refresh_token: details.refresh_token,
      client_id: process.env.CLIENT_ID,
    },
  };

  request(refresh_token_req, function (error, response, body) {
    if (!error && response.statusCode == 200) {
      // get the TDA response
      var authReply = JSON.parse(body);
      details.access_token = authReply.access_token;
      details.access_last_update = Date().toString();

      // write the updated object to the details.json file
      fs.writeFileSync(
        detailsFileName,
        JSON.stringify(details, null, 2),
        function (err) {
          if (err) console.error(err);
        }
      );
    }
  });
}

/**
 * returns true if the time difference is more than or equal to the maxDifference
 * maxDifference should be in seconds
 */
function compareTimeDifference(t1, t2, maxDifference) {
  var date1 = new Date(t1);
  var date2 = new Date(t2);

  var diff = Math.floor((date2 - date1) / 1000); // difference in seconds

  return diff >= maxDifference;
}

/**
 * checks if the access/refresh are valid and if not then
 * generate new tokens
 */
function validateTokens() {
  let time = Date().toString();
  // if the refresh token is expired, then reset both tokens
  if (compareTimeDifference(details.refresh_last_update, time, Days90)) {
    resetTokens();
    // if the access token is expired, then reset it
  } else if (
    compareTimeDifference(details.access_last_update, time, Minutes30)
  ) {
    resetAccessToken();
  }
}

// start server
var httpServer = http.createServer(app);
var port = process.env.PORT || 8080;
httpServer.listen(port, () => {
  console.log(`Listening at ${port}`);
});

更新 #1 新结果

heroku[web.1]: Process exited with status 137
heroku[web.1]: Starting process with command `node ./app.js`
app[web.1]: Listening at 5942
heroku[web.1]: State changed from starting to up
heroku[router]: at=error code=H12 desc="Request timeout" method=GET path="/auth?code=code" host=november-td-ameri.herokuapp.
heroku[router]: at=error code=H12 desc="Request timeout" method=GET path="/reset" host=november-td-ameri.herokuapp.com 

0 个答案:

没有答案
相关问题