Angular/Express GET Call有时有效,有时失败.获取错误[ERR_HTTP_HEADERS_SENT



我将为get调用布局流程的每个步骤。我网站上的每个GET调用都是完全相同的,它们99%的时间都在工作。一些API调用有时会导致404,我不知道为什么。

该过程在这种情况下适用于100秒的GET调用。

流量为:

  1. Angular页面调用DB服务
  2. DB服务向后端路由器发送GET请求
  3. 路由器然后转到中间件来验证令牌
  4. 路由器然后点击一个控制器,该控制器等待从数据库获取数据
  5. 控制器使用实际SQL调用db_api调用
  6. 数据将返回到Angular

当前错误:

ode:18) UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
ERROR FOUND o_l_vfn: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

2020-10-23 13:02:41(node:18) UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client7c0b5a9e69b741e1a231a5cc02d8583e
2020-10-23 13:02:41at ServerResponse.setHeader (_http_outgoing.js:535:11)7c0b5a9e69b741e1a231a5cc02d8583e
2020-10-23 13:02:41at ServerResponse.header (/usr/src/app/node_modules/express/lib/response.js:771:10)7c0b5a9e69b741e1a231a5cc02d8583e
2020-10-23 13:02:41at ServerResponse.contentType (/usr/src/app/node_modules/express/lib/response.js:599:15)7c0b5a9e69b741e1a231a5cc02d8583e
2020-10-23 13:02:41at ServerResponse.sendStatus (/usr/src/app/node_modules/express/lib/response.js:357:8)7c0b5a9e69b741e1a231a5cc02d8583e
2020-10-23 13:02:41at get (/usr/src/app/controllers/o_l_ar.js:15:5)7c0b5a9e69b741e1a231a5cc02d8583e
2020-10-23 13:02:41(node:18) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated eit
(node:18) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function
without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection,
use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 4)


dashboard.component.ts:171 ERROR: {"headers":{"normalizedNames":{},"lazyUpdate":null},"status":404,"statusText":"OK","url":/api/o_l_ar?issuerid=1","ok":false,"name":"HttpErrorResponse",
"message":"Http failure response for/api/o_l_ar?issuerid=1: 404 OK","error":"<!DOCTYPE html>n<html lang="en">n
<head>n<meta charset="utf-8">n<title>Error</title>n</head>n<body>n<pre>Cannot GET /api/o_l_ar</pre>n</body>n</html>n"}

dashboard.component.ts--包含对我的Angular服务的调用

import { Component, OnInit } from '@angular/core';
import { DbService, OperationVFN} from '../db.service';
import { ActivatedRoute } from '@angular/router';
import {MatDialog} from '@angular/material/dialog';
@Component({
selector: 'app-dashboard',
templateUrl: './dashboard.component.html',
styleUrls: ['../global.css']
})
export class DashboardComponent implements OnInit {
operationvfns: Array<OperationVFN>;
constructor(
private DbService: DbService,
private route: ActivatedRoute,
public dialog: MatDialog
) {}

rungetOperationVFN(id) {
return new Promise((resolve, reject) => {
this.DbService.getOperationVFN(id).subscribe(operationvfns => this.operationvfns = operationvfns,
(err) => { 
console.log('ERROR: ' + JSON.stringify(err)); 
reject('Rejected');
},() => {
resolve(1);
});
})
}

async ngOnInit() {
const id = this.route.snapshot.paramMap.get('id');
try { await this.rungetOperationVFN(id); } catch (e) {console.log('ang comp: ' + e)}
}
}

db.service.ts--调用我的后端Node/Express服务器

import { Injectable } from '@angular/core';
import { HttpClient , HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { Router, ActivatedRoute } from '@angular/router';
export class OperationVFN {
OPERATION_TYPE: string;
OPERATION_ID: string;
SIMPLE_NAME: string;
LINK_NAME: string;
TABLENAME: string;
MAX_CALC_DT: string;
}
const hosturl = 'https://webiste.com/api/'; 
@Injectable()
export class DbService {
constructor(private _http: HttpClient,
private route: ActivatedRoute,
private router: Router) {}
getOperationVFN(id): Observable<OperationVFN[]> {
const url = hosturl +'o_l_vfn';
const httpOptions = {
headers: new HttpHeaders({
'Access-Control-Allow-Origin':  '*',
'Content-Type': 'application/json'
}),
withCredentials: true,
params: {
'issuerid': id
}
};
return this._http.get(url, httpOptions)
.pipe(
map((res) => {
console.log(res);
return <OperationVFN[]> res;
})
);
}
}

router.js——API调用的路由器

const express = require('express');
const router = new express.Router();
var authMiddleware = require('../middleware/AuthMiddleware.js');
const o_l_vfn = require('../controllers/o_l_vfn.js');
router.get('/o_l_vfn', authMiddleware.Validate, o_l_vfn.get);
module.exports = router;

用于验证API调用头令牌的中间件

var jwkToPem = require('jwk-to-pem'),
jwt = require('jsonwebtoken');
const request = require('request');

exports.Validate = function(req, res, next) {

if (req.headers['authorization']) {
const token = req.headers['authorization'];
request({
url : `oauth/.well-known/jwks.json`,
json : true
}, function(error, response, body){
if (!error && response.statusCode === 200) {
pems = {};
var keys = body['keys'];
for(var i = 0; i < keys.length; i++) {
var key_id = keys[i].kid;
var modulus = keys[i].n;
var exponent = keys[i].e;
var key_type = keys[i].kty;
var jwk = { kty: key_type, n: modulus, e: exponent};
var pem = jwkToPem(jwk);
pems[key_id] = pem;
}
var decodedJwt = jwt.decode(token, {complete: true});
if (!decodedJwt) {
console.log("Not a valid JWT token");
res.status(401);
return res.send("Not a valid JWT token");
}
var kid = decodedJwt.header.kid;
var pem = pems[kid];
if (!pem) {
console.log('Invalid token - decodedJwt.header.kid');
res.status(401);
return res.send("Invalid token - decodedJwt.header.kid");              
}
jwt.verify(token, pem, function(err, payload) {
if(err) {
console.log("Invalid Token - verify");
res.status(401);
return res.send("Invalid token  - verify");
} else {
console.log("Valid Token.");
return next();
}
});
} else {
console.log("Error! Unable to download JWKs");
res.status(500);
return res.send("Error! Unable to download JWKs");
}
});
} else {
}
return next();
}

控制器/ol_vfn.js--控制器

const o_l_vfn = require('../db_apis/o_l_vfn.js');
const env = require('../config/dbconfig.js');
async function get(req, res, next) {
try {
const context = {};
context.tredb = env.tredb;
context.id = req.query.id;
const rows = await o_l_vfn.find(context);
res.send(rows);
} catch (err) { 
console.log('ERROR FOUND o_l_vfn: ' + err)
res.sendStatus(404);
next(err);
}
}
module.exports.get = get;

db_api--o_l_vfn.ts

const database = require('../services/database.js');
async function find(context) {
let query = "SELECT * from " + context.tredb + ".OPERATIONS WHERE Operation_Type = 'DR' and id = '" + context.id + "' ORDER BY Operation_Id ASC";
const binds = {};

console.log(query);
const result = await database.simpleExecute(query, binds);
console.log(result.rows);
return result.rows;
}
module.exports.find = find;

您需要在else:内移动Validate函数底部的return next();

else {
return next();
}

按照您目前的方式,当提供authorization标头时,它会调用next两次。

最新更新