安装了heroku的CLI工具包后,在mac终端登录时出现错误 20C

$ heroku login
heroku: Enter your login credentials
Email: TypeError: Cannot read property 'body' of undefined
at new HerokuAPIError (/usr/local/Cellar/heroku/7.0.86/libexec/node_modules/@heroku-cli/command/lib/api_client.js:12:33)
at Login.login (/usr/local/Cellar/heroku/7.0.86/libexec/node_modules/@heroku-cli/command/lib/login.js:78:19)# New Document

    本人初学ruby on rails,这些错误代码是安装的工具自带的,而且是最新版,重新安装过了也没用,https://devcenter.heroku.com/articles/heroku-cli  安装的官网在这里,按照步骤操作的,为什么会出现这个问题呢,希望大神们帮帮我!js文件代码如下。

第一个:

    "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const errors_1 = require("@oclif/errors");
const netrc_parser_1 = tslib_1.__importDefault(require("netrc-parser"));
const url = tslib_1.__importStar(require("url"));
const deps_1 = tslib_1.__importDefault(require("./deps"));
const login_1 = require("./login");
const vars_1 = require("./vars");
class HerokuAPIError extends errors_1.CLIError {
constructor(httpError) {
let options = httpError.body;
if (!options || !options.message)
throw httpError;
let info = [];
if (options.id)
info.push(Error ID: ${options.id});
if (options.app && options.app.name)
info.push(App: ${options.app.name});
if (options.url)
info.push(See ${options.url} for more information.);
if (info.length)
super([options.message, ''].concat(info).join('\n'));
else
super(options.message);
this.http = httpError;
this.body = options;
}
}
exports.HerokuAPIError = HerokuAPIError;
class APIClient {
constructor(config, options = {}) {
this.config = config;
this.options = options;
this._login = new login_1.Login(this.config, this);
this.config = config;
if (options.required === ‘undefined’)
options.required = true;
options.preauth = options.preauth !== false;
this.options = options;
let apiUrl = url.URL ? new url.URL(vars_1.vars.apiUrl) : url.parse(vars_1.vars.apiUrl);
let envHeaders = JSON.parse(process.env.HEROKU_HEADERS || '{}');
this.preauthPromises = {};
let self = this;
const opts = {
host: apiUrl.host,
headers: Object.assign({ accept: 'application/vnd.heroku+json; version=3', 'user-agent': heroku-cli/${self.config.version} ${self.config.platform} }, envHeaders),
};
this.http = class APIHTTPClient extends deps_1.default.HTTP.HTTP.create(opts) {
static async twoFactorRetry(err, url, opts = {}, retries = 3) {
const app = err.body.app ? err.body.app.name : null;
if (!app || !options.preauth) {
opts.headers = opts.headers || {};
opts.headers['Heroku-Two-Factor-Code'] = await self.twoFactorPrompt();
return this.request(url, opts, retries);
}
else {
// if multiple requests are run in parallel for the same app, we should
// only preauth for the first so save the fact we already preauthed
if (!self.preauthPromises[app]) {
self.preauthPromises[app] = self.twoFactorPrompt().then((factor) => self.preauth(app, factor));
}
await self.preauthPromises[app];
return this.request(url, opts, retries);
}
}
static async request(url, opts = {}, retries = 3) {
opts.headers = opts.headers || {};
if (!Object.keys(opts.headers).find(h => h.toLowerCase() === 'authorization')) {
opts.headers.authorization = Bearer ${self.auth};
}
retries--;
try {
return await super.request(url, opts);
}
catch (err) {
if (!(err instanceof deps_1.default.HTTP.HTTPError))
throw err;
if (retries > 0) {
if (opts.retryAuth !== false && err.http.statusCode === 401 && err.body.id === 'unauthorized') {
if (!self.authPromise)
self.authPromise = self.login();
await self.authPromise;
opts.headers.authorization = Bearer ${self.auth};
return this.request(url, opts, retries);
}
if (err.http.statusCode === 403 && err.body.id === 'two_factor') {
return this.twoFactorRetry(err, url, opts, retries);
}
}
throw new HerokuAPIError(err);
}
}
};
}
get twoFactorMutex() {
if (!this._twoFactorMutex) {
this._twoFactorMutex = new deps_1.default.Mutex();
}
return this._twoFactorMutex;
}
get auth() {
if (!this._auth) {
if (process.env.HEROKU_API_TOKEN && !process.env.HEROKU_API_KEY)
deps_1.default.cli.warn('HEROKU_API_TOKEN is set but you probably meant HEROKU_API_KEY');
this._auth = process.env.HEROKU_API_KEY;
if (!this._auth) {
deps_1.default.netrc.loadSync();
this._auth = deps_1.default.netrc.machines[vars_1.vars.apiHost] && deps_1.default.netrc.machines[vars_1.vars.apiHost].password;
}
}
return this._auth;
}
set auth(token) {
delete this.authPromise;
this._auth = token;
}
twoFactorPrompt() {
deps_1.default.yubikey.enable();
return this.twoFactorMutex.synchronize(async () => {
try {
let factor = await deps_1.default.cli.prompt('Two-factor code', { type: 'mask' });
deps_1.default.yubikey.disable();
return factor;
}
catch (err) {
deps_1.default.yubikey.disable();
throw err;
}
});
}
preauth(app, factor) {
return this.put(/apps/${app}/pre-authorizations, {
headers: { 'Heroku-Two-Factor-Code': factor },
});
}
get(url, options = {}) {
return this.http.get(url, options);
}
post(url, options = {}) {
return this.http.post(url, options);
}
put(url, options = {}) {
return this.http.put(url, options);
}
patch(url, options = {}) {
return this.http.patch(url, options);
}
delete(url, options = {}) {
return this.http.delete(url, options);
}
stream(url, options = {}) {
return this.http.stream(url, options);
}
request(url, options = {}) {
return this.http.request(url, options);
}
login(opts = {}) {
return this._login.login(opts);
}
async logout() {
try {
await this._login.logout();
}
catch (err) {
errors_1.warn(err);
}
delete netrc_parser_1.default.machines['api.heroku.com'];
delete netrc_parser_1.default.machines['git.heroku.com'];
await netrc_parser_1.default.save();
}
get defaults() {
return this.http.defaults;
}
}
exports.APIClient = APIClient;

第二个:

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const color_1 = tslib_1.__importDefault(require("@heroku-cli/color"));
const cli_ux_1 = tslib_1.__importDefault(require("cli-ux"));
const fs = tslib_1.__importStar(require("fs-extra"));
const http_call_1 = tslib_1.__importDefault(require("http-call"));
const netrc_parser_1 = tslib_1.__importDefault(require("netrc-parser"));
const opn = require("opn");
const os_1 = require("os");
const path = tslib_1.__importStar(require("path"));
const api_client_1 = require("./api_client");
const vars_1 = require("./vars");
const debug = require('debug')('heroku-cli-command');
const headers = (token) => ({ headers: { accept: 'application/vnd.heroku+json; version=3', authorization: Bearer ${token} } });
class Login {
constructor(config, heroku) {
this.config = config;
this.heroku = heroku;
this.loginHost = process.env.HEROKU_LOGIN_HOST || 'https://cli-login.heroku.com';
}
async login(opts = {}) {
await this.loadSettings();
let loggedIn = false;
try {
// timeout after 10 minutes
setTimeout(() => {
if (!loggedIn)
cli_ux_1.default.error('timed out');
}, 1000 * 60 * 10).unref();
if (process.env.HEROKU_API_KEY)
cli_ux_1.default.error('Cannot log in with HEROKU_API_KEY set');
await netrc_parser_1.default.load();
const previousEntry = netrc_parser_1.default.machines['api.heroku.com'];
let input = opts.method;
const defaultMethod = this.settings.method || 'interactive';
if (!input) {
if (opts.expiresIn) {
// can't use browser with --expires-in
input = 'interactive';
}
else if (this.enableBrowserLogin()) {
input = await cli_ux_1.default.prompt(heroku: Login with [${color_1.default.green('b')}]rowser, [${color_1.default.green('i')}]nteractive, or [${color_1.default.green('s')}]so (enterprise-only), { default: defaultMethod });
}
else {
input = defaultMethod || 'interactive';
}
}
try {
if (previousEntry && previousEntry.password)
await this.logout(previousEntry.password);
}
catch (err) {
cli_ux_1.default.warn(err);
}
let auth;
delete this.settings.method;
switch (input) {
case 'b':
case 'browser':
auth = await this.browser();
break;
case 'i':
case 'interactive':
auth = await this.interactive(previousEntry && previousEntry.login, opts.expiresIn);
break;
case 's':
case 'sso':
auth = await this.sso();
break;
default:
return this.login(opts);
}
await this.saveToken(auth);
await this.saveSettings();
}
catch (err) {
throw new api_client_1.HerokuAPIError(err);
}
finally {
loggedIn = true;
}
}
async logout(token = this.heroku.auth) {
if (!token)
return debug('no credentials to logout');
const requests = [];
// for SSO logins we delete the session since those do not show up in
// authorizations because they are created a trusted client
requests.push(http_call_1.default.delete(${vars_1.vars.apiUrl}/oauth/sessions/~, headers(token))
.catch(err => {
if (!err.http)
throw err;
if (err.http.statusCode === 404 && err.http.body && err.http.body.id === 'not_found' && err.http.body.resource === 'session') {
return;
}
if (err.http.statusCode === 401 && err.http.body && err.http.body.id === 'unauthorized') {
return;
}
throw err;
}));
// grab all the authorizations so that we can delete the token they are
// using in the CLI. we have to do this rather than delete ~ because
// the ~ is the API Key, not the authorization that is currently requesting
requests.push(http_call_1.default.get(${vars_1.vars.apiUrl}/oauth/authorizations, headers(token))
.then(async ({ body: authorizations }) => {
// grab the default authorization because that is the token shown in the
// dashboard as API Key and they may be using it for something else and we
// would unwittingly break an integration that they are depending on
const d = await this.defaultToken();
if (d === token)
return;
return Promise.all(authorizations
.filter(a => a.access_token && a.access_token.token === this.heroku.auth)
.map(a => http_call_1.default.delete(${vars_1.vars.apiUrl}/oauth/authorizations/${a.id}, headers(token))));
})
.catch(err => {
if (!err.http)
throw err;
if (err.http.statusCode === 401 && err.http.body && err.http.body.id === 'unauthorized') {
return [];
}
throw err;
}));
await Promise.all(requests);
}
async browser() {
const { body: urls } = await http_call_1.default.post(${this.loginHost}/auth);
// TODO: handle browser
const url = ${this.loginHost}${urls.browser_url};
debug(opening browser to ${url});
const cp = await opn(url, { wait: false });
cp.on('error', cli_ux_1.default.error);
const showUrl = () => cli_ux_1.default.warn(Cannot open browser. Go to ${color_1.default.greenBright(url)} to finish login or run ${color_1.default.cmd('heroku login --interactive')}\n);
if (process.env.HEROKU_TESTING_HEADLESS_LOGIN === '1')
showUrl();
cp.on('close', code => {
if (code !== 0)
showUrl();
});
cli_ux_1.default.action.start('Waiting for login');
const { body: auth } = await http_call_1.default.get(${this.loginHost}${urls.cli_url}, {
headers: {
authorization: Bearer ${urls.token},
}
});
if (auth.error)
cli_ux_1.default.error(auth.error);
this.heroku.auth = auth.access_token;
cli_ux_1.default.action.start('Logging in');
const { body: account } = await http_call_1.default.get(${vars_1.vars.apiUrl}/account, headers(auth.access_token));
cli_ux_1.default.action.stop();
return {
login: account.email,
password: auth.access_token,
};
}
async interactive(login, expiresIn) {
process.stderr.write('heroku: Enter your login credentials\n');
login = await cli_ux_1.default.prompt('Email', { default: login });
let password = await cli_ux_1.default.prompt('Password', { type: 'hide' });
let auth;
try {
auth = await this.createOAuthToken(login, password, { expiresIn });
}
catch (err) {
if (!err.body || err.body.id !== 'two_factor')
throw err;
let secondFactor = await cli_ux_1.default.prompt('Two-factor code', { type: 'mask' });
auth = await this.createOAuthToken(login, password, { expiresIn, secondFactor });
}
this.heroku.auth = auth.password;
return auth;
}
async createOAuthToken(username, password, opts = {}) {
function basicAuth(username, password) {
let auth = [username, password].join(':');
auth = Buffer.from(auth).toString('base64');
return Basic ${auth};
}
let headers = {
accept: 'application/vnd.heroku+json; version=3',
authorization: basicAuth(username, password)
};
if (opts.secondFactor)
headers['Heroku-Two-Factor-Code'] = opts.secondFactor;
const { body: auth } = await http_call_1.default.post(${vars_1.vars.apiUrl}/oauth/authorizations, {
headers,
body: {
scope: ['global'],
description: Heroku CLI login from ${os_1.hostname()},
expires_in: opts.expiresIn || 60 * 60 * 24 * 365 // 1 year
}
});
return { password: auth.access_token.token, login: auth.user.email };
}
async saveToken(entry) {
const hosts = [vars_1.vars.apiHost, vars_1.vars.httpGitHost];
hosts.forEach(host => {
if (!netrc_parser_1.default.machines[host])
netrc_parser_1.default.machines[host] = {};
netrc_parser_1.default.machines[host].login = entry.login;
netrc_parser_1.default.machines[host].password = entry.password;
delete netrc_parser_1.default.machines[host].method;
delete netrc_parser_1.default.machines[host].org;
});
if (netrc_parser_1.default.machines._tokens) {
netrc_parser_1.default.machines._tokens.forEach((token) => {
if (hosts.includes(token.host)) {
token.internalWhitespace = '\n ';
}
});
}
await netrc_parser_1.default.save();
}
async defaultToken() {
try {
const { body: authorization } = await http_call_1.default.get(${vars_1.vars.apiUrl}/oauth/authorizations/~, headers(this.heroku.auth));
return authorization.access_token && authorization.access_token.token;
}
catch (err) {
if (!err.http)
throw err;
if (err.http.statusCode === 404 && err.http.body && err.http.body.id === 'not_found' && err.body.resource === 'authorization')
return;
if (err.http.statusCode === 401 && err.http.body && err.http.body.id === 'unauthorized')
return;
throw err;
}
}
enableBrowserLogin() {
if (!process.env.HEROKU_LOGIN_HOST)
return false;
if (this.config.name === '@heroku-cli/command')
return true;
return this.config.channel !== 'stable';
}
async sso() {
let url = process.env.SSO_URL;
let org = process.env.HEROKU_ORGANIZATION || this.settings.org;
if (!url) {
if (org) {
org = await cli_ux_1.default.prompt('Organization name', { default: org });
}
else {
org = await cli_ux_1.default.prompt('Organization name');
}
url = https://sso.heroku.com/saml/${encodeURIComponent(org)}/init?cli=true;
}
cli_ux_1.default.action.start('Opening browser for login');
// TODO: handle browser
debug(opening browser to ${url});
await opn(url, { wait: false });
const password = await cli_ux_1.default.prompt('Access token', { type: 'mask' });
cli_ux_1.default.action.start('Validating token');
this.heroku.auth = password;
const { body: account } = await http_call_1.default.get(${vars_1.vars.apiUrl}/account, headers(password));
this.settings.method = 'sso';
this.settings.org = org;
return { password, login: account.email };
}
async loadSettings() {
try {
this.settings = await fs.readJSON(this.settingsPath);
}
catch (err) {
if (err.code !== 'ENOENT')
cli_ux_1.default.warn(err);
else
debug(err);
this.settings = {};
}
}
async saveSettings() {
try {
if (Object.keys(this.settings).length === 0) {
await fs.remove(this.settingsPath);
}
else {
await fs.outputJSON(this.settingsPath, this.settings);
}
}
catch (err) {
cli_ux_1.default.warn(err);
}
}
get settingsPath() { return path.join(this.config.dataDir, 'login.json'); }
}
exports.Login = Login;

1个回答

他说 body 没有定义,无法读取,你应该去 它 提示的 js文件里去看一下,是什么导致的body属性 未定义

qq_39499400
qq_39499400 贴上去了
一年多之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!