#angular #express #async-await #get #http-headers
#angular #экспресс #async-await #получить #http-заголовки
Вопрос:
Я собираюсь изложить каждый шаг моего процесса для моего вызова get. Каждый вызов GET на моем веб-сайте настроен точно так же, и они работают в 99% случаев. Несколько вызовов API иногда приводят к 404, и я понятия не имею, почему.
Процесс работает в течение 100 секунд вызовов GET в этом режиме.
Поток:
- Страница Angular вызывает службу DB.
- Служба БД отправляет запрос GET на серверный маршрутизатор.
- Затем маршрутизатор переходит к промежуточному программному обеспечению для проверки токена.
- Затем маршрутизатор обращается к контроллеру, который ожидает получения данных из базы данных.
- Контроллер вызывает вызов db_api с фактическим SQL
- Данные возвращаются в 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 — вызов моего серверного узла / экспресс-сервера
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 — router for API call
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;
middleware for validating token of API call header
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 amp;amp; 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();
}
controller/o_l_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;
Ответ №1:
Вам нужно переместить return next();
в нижней части Validate
функции внутри else
:
else {
return next();
}
В том виде, в котором он у вас сейчас есть, он вызывается next
дважды при наличии authorization
предоставленного заголовка.
Комментарии:
1. Вау. Большое вам спасибо!