I have an Angular app that communicates with an API hosted on heroku. Simply put it's a movie database where you can add movies to and remove from your favourites.
The request for adding a movie:
addMovie(username: any, movieId: any): Observable<any> {
const token = localStorage.getItem('token');
return this.http.post(apiUrl `users/${username}/movies/${movieId}`, {headers: new HttpHeaders(
{
Authorization: 'Bearer ' token,
}
)}).pipe(
map(this.extractResponseData),
catchError(this.handleError)
);
}
And removing a movie:
deleteMovie(username: any, movieId: any): Observable<any> {
const token = localStorage.getItem('token');
return this.http.delete(apiUrl `users/${username}/movies/${movieId}`, {headers: new HttpHeaders(
{
Authorization: 'Bearer ' token,
}
)}).pipe(
map(this.extractResponseData),
catchError(this.handleError)
);
}
Both requests are exactly the same but the POST request drops the Authorization header for some reason while the DELETE request doesn't. When looking at the preflight request for both, the preflight for the POST request doesn't even request allowance for the Authorization header, while the preflight for the DELETE request does.
Preflight for POST:
curl "https://somesite.com/users/tester/movies/6123fbc6a2a0fea2b1f81fd1" ^
-X "OPTIONS" ^
-H "Connection: keep-alive" ^
-H "Accept: */*" ^
-H "Access-Control-Request-Method: POST" ^
-H "Access-Control-Request-Headers: content-type" ^
-H "Origin: http://localhost:4200" ^
-H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36" ^
-H "Sec-Fetch-Mode: cors" ^
-H "Sec-Fetch-Site: cross-site" ^
-H "Sec-Fetch-Dest: empty" ^
-H "Referer: http://localhost:4200/" ^
-H "Accept-Language: de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7" ^
Preflight for DELETE:
curl "https://somesite.com/users/tester/movies/61240c5da2a0fea2b1f81fd9" ^
-X "OPTIONS" ^
-H "Connection: keep-alive" ^
-H "Accept: */*" ^
-H "Access-Control-Request-Method: DELETE" ^
-H "Access-Control-Request-Headers: authorization" ^
-H "Origin: http://localhost:4200" ^
-H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36" ^
-H "Sec-Fetch-Mode: cors" ^
-H "Sec-Fetch-Site: cross-site" ^
-H "Sec-Fetch-Dest: empty" ^
-H "Referer: http://localhost:4200/" ^
-H "Accept-Language: de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7" ^
Replacing POST with PUT results in the same problem.
CodePudding user response:
The second argument in a POST request is the body. The third argument in a POST request is options. The second argument in a DELETE request is options. Currently, you're sending the authentication header in the body in the POST request, but it belongs to options.
You can send an empty body
addMovie(username: any, movieId: any): Observable<any> {
const token = localStorage.getItem('token');
return this.http.post(apiUrl `users/${username}/movies/${movieId}`, {}, {headers: new HttpHeaders(
{
Authorization: 'Bearer ' token,
}
)}).pipe(
map(this.extractResponseData),
catchError(this.handleError)
);
}