Javascript 如何使用 x-www-form-urlencoded 强制 Angular2 POST
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/39863317/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to force Angular2 to POST using x-www-form-urlencoded
提问by Damon Kaswell
I have a project that needs to use Angular2 (final) to post to an old, legacy Tomcat 7 server providing a somewhat REST-ish API using .jsp pages.
我有一个项目需要使用 Angular2(最终版)发布到旧的遗留 Tomcat 7 服务器,该服务器使用 .jsp 页面提供某种 REST-ish API。
This worked fine when the project was just a simple JQuery app performing AJAX requests. However, the scope of the project has grown such that it will need to be rewritten using a more modern framework. Angular2 looks fantastic for the job, with one exception: It refuses to perform POST requests using anything option but as form-data, which the API doesn't extract. The API expects everything to be urlencoded, relying on Java's request.getParameter("param")
syntax to extract individual fields.
当项目只是一个执行 AJAX 请求的简单 JQuery 应用程序时,这很有效。但是,该项目的范围已经扩大,因此需要使用更现代的框架对其进行重写。Angular2 看起来非常适合这项工作,但有一个例外:它拒绝使用任何选项执行 POST 请求,但作为表单数据,API 不会提取这些数据。API 期望所有内容都经过 urlencoded,依靠 Java 的request.getParameter("param")
语法来提取各个字段。
This is a snipped from my user.service.ts:
这是从我的 user.service.ts 中截取的:
import { Injectable } from '@angular/core';
import { Headers, Response, Http, RequestOptions } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
@Injectable()
export class UserService {
private loggedIn = false;
private loginUrl = 'http://localhost:8080/mpadmin/api/login.jsp';
private headers = new Headers({'Content-Type': 'application/x-www-form-urlencoded'});
constructor(private http: Http) {}
login(username, password) {
return this.http.post(this.loginUrl, {'username': username, 'password': password}, this.headers)
.map((response: Response) => {
let user = response.json();
if (user) {
localStorage.setItem('currentUser', JSON.stringify(user));
}
}
);
}
}
No matter what I set the header content type to be, it always ends up arriving as non-encoded form-data. It's not honoring the header I'm setting.
无论我将标题内容类型设置为什么,它最终总是以未编码的表单数据的形式到达。这不是尊重我设置的标题。
Has anyone else encountered this? How do you go about forcing Angular2 to POST data in a format that can be read by an old Java API using request.getParameter("param")
?
有人遇到过这种情况么?您如何强制 Angular2 以可以使用旧 Java API 读取的格式发布数据request.getParameter("param")
?
Edit: For anyone else who finds this in the future, the solution is actually really simple. Set the body of the post like this:
编辑:对于将来发现此问题的任何其他人,解决方案实际上非常简单。像这样设置帖子的正文:
let body = `username=${username}&password=${password}`;`
See Brad's example below.
请参阅下面的 Brad 示例。
回答by Brad
You can do this using URLSearchParams
as the body of the request and angular will automatically set the content type to application/x-www-form-urlencoded
and encode the body properly.
您可以使用URLSearchParams
作为请求的正文来执行此操作,Angular 将自动将内容类型设置为application/x-www-form-urlencoded
并正确编码正文。
let body = new URLSearchParams();
body.set('username', username);
body.set('password', password);
this.http.post(this.loginUrl, body).map(...);
The reason it's not currently working for you is you're not encoding the body data in the correct format and you're not setting the header options correctly.
它目前不适合您的原因是您没有以正确的格式对正文数据进行编码,并且您没有正确设置标题选项。
You need to encode the body like this:
您需要像这样对主体进行编码:
let body = `username=${username}&password=${password}`;
You need to set the header options like this:
您需要像这样设置标题选项:
this.http.post(this.loginUrl, body, { headers: headers }).map(...);
回答by Mick
For Angular 4.3+/5+ (New HTTPClient) use the following:
对于 Angular 4.3+/5+(新 HTTPClient),请使用以下内容:
let body = new URLSearchParams();
body.set('user', username);
body.set('password', password);
let options = {
headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded')
};
this.http
.post('//yourUrl.com/login', body.toString(), options)
.subscribe(response => {
//...
});
Note 3 things to make it work as expected:
请注意 3 件事以使其按预期工作:
- Use URLSearchParams for your body
- Convert body to string
- Set the header's content-type
- 为您的身体使用 URLSearchParams
- 将正文转换为字符串
- 设置标题的内容类型
Attention: Older browsers do need a polyfill! I used: npm i url-search-params-polyfill --save
and then added to polyfills.ts: import 'url-search-params-polyfill';
注意:旧版浏览器确实需要 polyfill!我使用:npm i url-search-params-polyfill --save
然后添加到polyfills.ts:import 'url-search-params-polyfill';
回答by Johan Kvint
For those still looking for an answer this is how I solved it with Angular 5 and HttpClient:
对于那些仍在寻找答案的人,这就是我使用 Angular 5 和 HttpClient 解决的方法:
const formData = new FormData();
// append your data
formData.append('myKey1', 'some value 1');
formData.append('myKey1', 'some value 2');
formData.append('myKey3', true);
this.httpClient.post('apiPath', formData);
Do NOTset Content-Type header, angular will fix this for you!
难道不设置Content-Type头,角将解决您的问题!
回答by Robert Hegner
This is what worked for me with Angular 7:
这就是 Angular 7 对我有用的方法:
const payload = new HttpParams()
.set('username', username)
.set('password', password);
this.http.post(url, payload);
No need to explicitly set the header with this approach.
无需使用此方法显式设置标头。
Note that the HttpParams object is immutable. So doing something like the following won't work, it will give you an empty body:
请注意,HttpParams 对象是不可变的。所以做类似下面的事情是行不通的,它会给你一个空的身体:
const payload = new HttpParams();
payload.set('username', username);
payload.set('password', password);
this.http.post(url, payload);
回答by khaleel
I found out this solution after working several hours on this issue
我在这个问题上工作了几个小时后找到了这个解决方案
login(userName: string, password: string) {
const headers = new Headers();
headers.append('Accept', 'application/json');
headers.append('Content-Type', 'application/x-www-form-urlencoded');
headers.append( 'No-Auth', 'True');
const body = new URLSearchParams();
body.set('username', userName);
body.set('password', password);
body.set('grant_type', 'password');
return this.http.post(
this.baseUrl + '/token'
, body.toString()
, { headers: headers }
)
.pipe(map(res => res.json()))
.pipe(map(res => {
localStorage.setItem('auth_token', res.auth_token);
return true;
}))
.pipe(catchError((error: any) => {
return Observable.throw(error);
}));
}
}
回答by reynold adade
When using angular forms most parameters will be sent as objects, hence your login function will most likely have this object
form.value = {username: 'someone', password:'1234', grant_type: 'password'}
as the parameter
使用角度形式时,大多数参数将作为对象发送,因此您的登录函数很可能将此对象
form.value = {username: 'someone', password:'1234', grant_type: 'password'}
作为参数
to send this object as x-www-form-urlencodedyour code will be
将此对象作为x-www-form-urlencoded 发送,您的代码将是
export class AuthService {
private headers = new HttpHeaders(
{
'Content-Type': 'application/x-www-form-urlencoded',
Accept: '*/*',
}
);
constructor(private http: HttpClient) { }
login(data): Observable<any> {
const body = new HttpParams({fromObject: data});
const options = { headers: this.headers};
return this.http.post(`${environment.baseUrl}/token`, body.toString(), options);
}
回答by Brady Huang
Angular 8
角 8
const headers = new HttpHeaders({
'Content-Type': 'application/x-www-form-urlencoded'
});
const params = new HttpParams();
params.set('username', 'username');
params.set('password', 'password');
this.http.post(
'https://localhost:5000/api',
params.toString(),
{ headers }
);
回答by ghiles ybeggazene
export class MaintenanceService {
constructor(private http: HttpClient) { }
//header de requete http
private headers = new HttpHeaders(
{ 'Content-Type': 'application/x-www-form-urlencoded' }
);
// requete http pour recuperer le type des maintenances
createMaintenance(data: createMaintenance){
const options = { headers: this.headers};
return this.http.post('api/v2/admin/maintenances', data, options ).subscribe(status=> console.log(JSON.stringify(status)));
}
回答by WinnersProx
Guys I've been working on this since a while and thanks to this post from Josh Morony https://www.joshmorony.com/integrating-an-ionic-application-with-a-nodejs-backend/I figured out what the problem was. Basically, when I started testing my api I was using POSTMAN and it was working perfectly but when it came to implementing it with Ionic Angular it became a problem. The solution in this post is only about importing body-parser
and use it as app middleware like this app.use(bodyParser.json())
on your server-side root file(index).
伙计们,我一直在研究这个,感谢 Josh Morony 的这篇文章https://www.joshmorony.com/integrating-an-ionic-application-with-a-nodejs-backend/我想出了什么问题是。基本上,当我开始测试我的 api 时,我使用的是 POSTMAN 并且它运行良好,但是当涉及到使用 Ionic Angular 实现它时,它就成了一个问题。这篇文章中的解决方案只是关于在服务器端根文件(索引)中导入body-parser
和使用它作为应用程序中间件app.use(bodyParser.json())
。
Hopefully, this will help, Thanks!
希望这会有所帮助,谢谢!