Javascript 如何使用x-www-form-urlencoded强制Angular2发布
我有一个项目需要使用Angular2(final)发布到一个旧的、遗留的Tomcat7服务器上,该服务器使用.jsp页面提供了一个有点REST风格的API 当该项目只是一个执行AJAX请求的简单JQuery应用程序时,这种方法工作得很好。然而,该项目的范围已经扩大,因此需要使用更现代的框架对其进行重写。Angular2看起来非常适合这项工作,但有一个例外:它拒绝使用任何选项执行POST请求,但将其作为表单数据,而API不会提取表单数据。API希望所有内容都是URL编码的,依靠Java的Javascript 如何使用x-www-form-urlencoded强制Angular2发布,javascript,angular,Javascript,Angular,我有一个项目需要使用Angular2(final)发布到一个旧的、遗留的Tomcat7服务器上,该服务器使用.jsp页面提供了一个有点REST风格的API 当该项目只是一个执行AJAX请求的简单JQuery应用程序时,这种方法工作得很好。然而,该项目的范围已经扩大,因此需要使用更现代的框架对其进行重写。Angular2看起来非常适合这项工作,但有一个例外:它拒绝使用任何选项执行POST请求,但将其作为表单数据,而API不会提取表单数据。API希望所有内容都是URL编码的,依靠Java的reque
request.getParameter(“param”)
语法来提取各个字段
这是从我的user.service.ts剪下的:
从'@angular/core'导入{Injectable};
从'@angular/Http'导入{Headers,Response,Http,RequestOptions};
从“rxjs/Observable”导入{Observable};
导入'rxjs/add/operator/map';
@可注射()
导出类用户服务{
私有loggedIn=false;
私人罗吉努尔酒店http://localhost:8080/mpadmin/api/login.jsp';
私有头=新头({'Content-Type':'application/x-www-form-urlencoded'});
构造函数(私有http:http){}
登录(用户名、密码){
返回this.http.post(this.loginUrl,{'username':username,'password':password},this.headers)
.map((响应:响应)=>{
让user=response.json();
如果(用户){
localStorage.setItem('currentUser',JSON.stringify(user));
}
}
);
}
}
无论我将标题内容类型设置为什么,它总是以非编码表单数据的形式到达。这不是为了纪念我的头球
还有其他人遇到过这种情况吗?如何使用request.getParameter(“param”)
强制Angular2以旧Java API可以读取的格式发布数据
编辑:对于将来发现这一点的任何人来说,解决方案其实非常简单。将帖子的主体设置为:
let body = `username=${username}&password=${password}`;`
let body = `username=${username}&password=${password}`;
this.http.post(this.loginUrl, body, { headers: headers }).map(...);
请参见下面的Brad示例。2020年6月更新:此答案已存在4年,并且由于角度的API变化而不再有效。有关当前版本的方法,请参阅最新的答案。
您可以使用
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(...);
它当前不适用于您的原因是您没有以正确的格式编码正文数据,并且没有正确设置标题选项
您需要对身体进行如下编码:
let body = `username=${username}&password=${password}`;`
let body = `username=${username}&password=${password}`;
this.http.post(this.loginUrl, body, { headers: headers }).map(...);
您需要如下设置标题选项:
let body = `username=${username}&password=${password}`;`
let body = `username=${username}&password=${password}`;
this.http.post(this.loginUrl, body, { headers: headers }).map(...);
对于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 => {
//...
});
注3:使其按预期工作的事项:
注意:较旧的浏览器确实需要polyfill!我使用了:
npm I url search params polyfill--save
然后添加到polyfills.ts:import'url search params polyfill'代码>对于那些仍在寻找答案的人,我就是这样用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);
不要设置内容类型标题,angular将为您解决此问题 这就是Angular 7对我起作用的原因:
const payload = new HttpParams()
.set('username', username)
.set('password', password);
this.http.post(url, payload);
无需使用此方法显式设置标头
请注意,HttpParams对象是不可变的。所以,像这样做是行不通的,它会给你一个空的身体:
const payload = new HttpParams();
payload.set('username', username);
payload.set('password', password);
this.http.post(url, payload);
我在这个问题上工作了几个小时后发现了这个解决方案
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);
}));
}伙计们,我一直在研究这个问题,多亏了Josh Morony的这篇文章,我才知道问题出在哪里。基本上,当我开始测试我的api时,我使用的是POSTMAN,它工作得很好,但是当它用Ionic Angular实现它时,它就成了一个问题。本文中的解决方案只涉及导入body parser
,并将其用作服务器端根文件(索引)上的app.use(bodyParser.json())
之类的应用程序中间件
希望这会有所帮助,谢谢 使用角度表单时,大多数参数将作为对象发送,因此您的登录函数很可能具有此对象
form.value={username:'someone',password:'1234',grant_type:'password'}
作为参数
要将此对象作为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);
}
导出类身份验证服务{
私有标头=新的HttpHeader(
{
“内容类型”:“应用程序/x-www-form-urlencoded”,
接受:“*/*”,
}
);
构造函数(私有http:HttpClient){}
登录(数据):可观察{
const body=新的HttpParams({fromObject:data});
const options={headers:this.headers};
返回此.http.post(`${environment.baseUrl}/token`,body.toString(),options);
}
8
角度9 这是一个有效的代码 选择其他适合您的选项以返回非成功答案
let params=新的HttpParams({
fromObject:{email:usuario.email,密码:usuario.password,角色:usuario.role},
});
让httpOptions={
标题:新的HttpHeaders({'Content Type':'application/x-www-form-urlencoded'}),
};
返回this.http.post(`${this.url}/usuario/signup`,params.toString(),httpOptions)(
地图(
(resp)=>{
log('returnhttp',resp);
返回响应;
},
(错误)=>{
log('返回http错误',错误);
返回误差;
}
)
);
尝试了URLSearchParams()选项,该选项不起作用,但您对正文的格式完全正确。这就成功了。标记为