Я использую Angular2 на стороне клиента и сервер node-express в качестве бэкэнда. Узел-сервер работает как промежуточное программное обеспечение API, а также как моя служба аутентификации. Пользовательские запросы должны содержать действительный токен JWT для выполнения запросов на узле-сервере.
Все мои функции GET и другие функции PUT работают правильно. Я написал новый, который просто должен удалить идентификатор в стороннем API, а не удалить.
Кроме того, мой сервер node-express в некоторых моментах отправляет клиенту пользовательские сообщения об ошибках. Это касается моей проблемы: всякий раз, когда я запускаю свою последнюю функцию PUT, мой сервер отвечает: «Токен не предоставлен». Это происходит, когда пользователь не вошел в систему на стороне клиента.
Как я уже сказал, все мои другие функции работают. this.createAuthenticationHeaders(); необходим для выполнения действительного запроса на стороне сервера. Но это реализовано.
Другими словами, аутентификация между клиентом и сервером теряется, и я получаю собственное сообщение об ошибке: "Токен не предоставлен".
Назначение-Detail.Component.ts
cancelAppointment() {
this.authService.getProfile().subscribe(profile => {
this.username = profile.user.username; // Set username
this.email = profile.user.email; // Set e-mail
if (profile.user.email) {
this.apiService.cancelUserAppointment(this.id).subscribe(data => {
console.info(this.id);
if (!data.success) {
this.messageClass = 'alert alert-danger'; // Set error bootstrap class
this.message = data.message; // Set error message
} else {
this.messageClass = 'alert alert-success'; // Set success bootstrap class
this.message = data.message; // Set success message
// After two seconds, navigate back to blog page
}
});
}
});
}
Служба API
cancelUserAppointment(id) {
this.createAuthenticationHeaders();
console.info('API SERVICE ' + id);
return this.http
.put(this.domain + 'api/appointments/' + id + '/cancel', this.options)
.map(res => res.json());
}
Функции службы API, которые работают
getCertificatesByUser(email) {
this.createAuthenticationHeaders();
return this.http
.get(this.domain + 'api/user/' + email + '/certificates', this.options)
.map(res => res.json());
}
Маршрут сервера к стороннему API
router.put('/appointments/:id/cancel', (req, res) => {
console.info('hi');
var id = req.params.id;
const url = process.env.acuityUri + '/appointments/' + id + '/cancel';
console.info(id);
});
ПО промежуточного слоя аутентификации
router.use((req, res, next) => {
const token = req.headers['authorization']; // Create token found in headers
// Check if token was found in headers
if (!token) {
res.json({
success: false,
message: 'No token provided'
}); // Return error
} else {
// Verify the token is valid
jwt.verify(token, config.secret, (err, decoded) => {
// Check if error is expired or invalid
if (err) {
res.json({
success: false,
message: 'Token invalid: ' + err
}); // Return error for token validation
} else {
req.decoded = decoded; // Create global variable to use in any request beyond
next(); // Exit middleware
}
});
}
});



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Не углубляясь в ваши заголовки аутентификации, я вижу довольно вопиющую проблему, которая, как мне кажется, может быть причиной ваших проблем.
Глаголы HTTP REST несут разные «намерения», намерение, о котором мы особенно заботимся в этом случае, заключается в том, должен ли ваш запрос иметь тело.
GET запросы нет несут с собой тело.
PUT запросы делать содержат тело.
Из-за этого методы запросов angular HttpClient (http.get, http.post и т. д.) имеют разные сигнатуры методов.
Чтобы перейти к делу, Сигнатура метода http.put принимает 3 параметра: url, body и options, тогда как сигнатура метода http.get принимает только 2: url и options.
Если вы посмотрите на свой пример, для http.put вы предоставляете this.httpOptions в качестве параметра второй вместо третьего, поэтому Angular упаковывает ваш объект options в тело запроса PUT. Вот почему у вас есть рабочий пример и нерабочий пример; рабочий пример - GET!
Решение? Просто поместите что-нибудь еще в качестве тела запроса во второй параметр и переместите this.options вниз в слот третьего параметра. Если вам все равно, что это такое, просто используйте пустой объект: {}.
Таким образом, ваш запрос должен выглядеть так:
return this.http
.put(this.domain + 'api/appointments/' + id + '/cancel', {}, this.options)
По крайней мере, это должно правильно отправлять все, что находится в this.options, на сервер. Теперь, правильно ли то, что в this.options, это другая история.
Пример вызова PUT из документации Angular: https://angular.io/guide/http#making-a-put-request
Это вызвало ошибку! Спасибо за ваше объяснение, имеет смысл для меня. :)