Angular2中的 Http.DELETE 请求体

我正在尝试从 Angular 2的前端访问一个 RESTful API。

为了从一个集合中删除一些条目,除了 Removée 惟一 id (可以附加到 URL)之外,我还需要发送一些其他数据,即一个身份验证令牌、一些集合信息和一些辅助数据。

我发现最直接的方法是将身份验证令牌放在请求 Header 中,将其他数据放在主体中。

然而,Angular 2的 Http 模块并不完全同意一个带有主体的 DELETE 请求,并试图发出这个请求

let headers= new Headers();
headers.append('access-token', token);


let body= JSON.stringify({
target: targetId,
subset: "fruits",
reason: "rotten"
});


let options= new RequestOptions({headers:headers});
this.http.delete('http://testAPI:3000/stuff', body,options).subscribe((ok)=>{console.log(ok)}); <------line 67

给出了这个错误

app/services/test.service.ts(67,4): error TS2346: Supplied parameters do not match any signature of call target.

现在,我是不是在语法方面做错了什么? 我很确定每个 RFC 都支持 DELETE 主体

有没有更好的方法来发送这些数据?

或者我应该把它扔进标题里,然后收工?

如果你对这个难题有任何见解,我将不胜感激

145693 次浏览

Definition in http.js from the @angular/http:

delete(url, options)

The request doesn't accept a body so it seem your only option is to but your data in the URI.

I found another topic with references to correspond RFC, among other things: How to pass data in the ajax DELETE request other than headers

The http.delete(url, options) does accept a body. You just need to put it within the options object.

http.delete('/api/something', new RequestOptions({
headers: headers,
body: anyObject
}))

Reference options interface: https://angular.io/api/http/RequestOptions

UPDATE:

The above snippet only works for Angular 2.x, 4.x and 5.x.

For versions 6.x onwards, Angular offers 15 different overloads. Check all overloads here: https://angular.io/api/common/http/HttpClient#delete

Usage sample:

const options = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
}),
body: {
id: 1,
name: 'test',
},
};


this.httpClient
.delete('http://localhost:8080/something', options)
.subscribe((s) => {
console.log(s);
});

You are actually able to fool Angular2 HTTP into sending a body with a DELETE by using the request method. This is how:

let body = {
target: targetId,
subset: "fruits",
reason: "rotten"
};


let options = new RequestOptionsArgs({
body: body,
method: RequestMethod.Delete
});


this.http.request('http://testAPI:3000/stuff', options)
.subscribe((ok)=>{console.log(ok)});

Note, you will have to set the request method in the RequestOptionsArgs and not in http.request's alternative first parameter Request. That for some reason yields the same result as using http.delete

I hope this helps and that I am not to late. I think the angular guys are wrong here to not allow a body to be passed with delete, even though it is discouraged.

The REST doesn't prevent body inclusion with DELETE request but it is better to use query string as it is most standarized (unless you need the data to be encrypted)

I got it to work with angular 2 by doing following:

let options:any = {}
option.header = new Headers({
'header_name':'value'
});


options.search = new URLSearchParams();
options.search.set("query_string_key", "query_string_value");


this.http.delete("/your/url", options).subscribe(...)

Below is the relevant code example for Angular 2/4/5 projects:

let headers = new Headers({
'Content-Type': 'application/json'
});


let options = new RequestOptions({
headers: headers,
body: {
id: 123
}
});


return this.http.delete("http//delete.example.com/delete", options)
.map((response: Response) => {
return response.json()
})
.catch(err => {
return err;
});

Notice that body is passed through RequestOptions

Below is a relevant code example for Angular 4/5 with the new HttpClient.

import { HttpClient } from '@angular/common/http';
import { HttpHeaders } from '@angular/common/http';


public removeItem(item) {
let options = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
}),
body: item,
};


return this._http
.delete('/api/menu-items', options)
.map((response: Response) => response)
.toPromise()
.catch(this.handleError);
}

In Angular 5, I had to use the request method instead of delete to send a body. The documentation for the delete method does not include body, but it is included in the request method.

import { HttpClient, HttpHeaders } from '@angular/common/http';


this.http.request('DELETE', url, {
headers: new HttpHeaders({
'Content-Type': 'application/json',
}),
body: { foo: bar }
});

Below is an example for Angular 6

deleteAccount(email) {
const header: HttpHeaders = new HttpHeaders()
.append('Content-Type', 'application/json; charset=UTF-8')
.append('Authorization', 'Bearer ' + sessionStorage.getItem('accessToken'));
const httpOptions = {
headers: header,
body: { Email: email }
};
return this.http.delete<any>(AppSettings.API_ENDPOINT + '/api/Account/DeleteAccount', httpOptions);
}

If you use Angular 6 we can put body in http.request method.

Reference from github

You can try this, for me it works.

import { HttpClient } from '@angular/common/http';


@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent {


constructor(
private http: HttpClient
) {
http.request('delete', url, {body: body}).subscribe();
}
}

In Angular Http 7, the DELETE method accepts as a second parameter options object in which you provide the request parameters as params object along with the headers object. This is different than Angular6.

See example:

this.httpClient.delete('https://api-url', {
headers: {},
params: {
'param1': paramValue1,
'param2': paramValue2
}
});
deleteInsurance(insuranceId: any) {
const insuranceData = {
id : insuranceId
}
var reqHeader = new HttpHeaders({
"Content-Type": "application/json",
});
const httpOptions = {
headers: reqHeader,
body: insuranceData,
};
return this.http.delete<any>(this.url + "users/insurance", httpOptions);
}

Since the deprecation of RequestOptions, sending data as body in a DELETE request is not supported.

If you look at the definition of DELETE, it looks like this:

    delete<T>(url: string, options?: {
headers?: HttpHeaders | {
[header: string]: string | string[];
};
observe?: 'body';
params?: HttpParams | {
[param: string]: string | string[];
};
reportProgress?: boolean;
responseType?: 'json';
withCredentials?: boolean;
}): Observable<T>;

You can send payload along with the DELETE request as part of the params in the options object as follows:

this.http.delete('http://testAPI:3000/stuff', { params: {
data: yourData
}).subscribe((data)=>.
{console.log(data)});

However, note that params only accept data as string or string[] so you will not be able to send your own interface data unless you stringify it.

For angular 10, you can use also the generic request format and the DELETE method:

http.request('DELETE',  path, {
body:body,
headers: httpHeaders,
params: ((params != null) ? params : new HttpParams())
})

In Angular 13 this works well for me:

const options = {
headers: this._headers,
body: JSON.stringify(user)
};


return this._http.delete<DeleteVirtualAssistantResult>(`${this._apiUrl}/users`, options);