我见过其他几个这样的问题,但是他们没有解决这个问题。我使用MailChimp的API进行简单调用,在注册时将成员添加到我的邮件列表中。
然而,当我测试时,我获得了401未授权,并且API抱怨没有提交API密钥。当我在Chrome中检查请求时,我看不到任何授权标头。这是我的代码:
const formData = {
email_address: this.emailControl.value,
status: 'subscribed',
merge_fields: {
NAME: this.nameControl.value
}
};
const header = new HttpHeaders({
'Authorization': 'apikey:' + environment.mailChimpApiKey
});
this.http.post(this.mailChimpUrl, formData, {
headers: header,
observe: 'response'
}).subscribe(response => {
console.log('response', response);
if (response.status === 200) {
this.submitted = true;
}
});
我检查并仔细检查了HttpClient.post方法签名,以及MailChimp API期望如何接收Auth头。看起来我做的一切都正确,那么为什么Angular不设置标题?
我注意到,当我设置可选标头时,值仅会更改为Access-Control-Request-Headers
。我读错了Chrome控制台吗?
Angular版本:5.2.4
答案 0 :(得分:3)
问题不在于Angular。现代浏览器为大多数跨域请求发送preflight OPTIONS request,而Mailchimp不支持这些请求。 Mailchimp API不支持客户端实现:
MailChimp不支持使用我们的API的客户端实现 CORS请求由于暴露帐户的潜在安全风险 API密钥。
如果更明显地说明这一点会很好,但我一开始并没有注意到它。最好的解决方案是使用jsonp。
答案 1 :(得分:1)
要执行此操作,我们需要从RequestOptions
库中导入Http
和@angular/http
以及withCredentials : true
。
正如@Maciej建议您也可以将import { Injectable } from '@angular/core';
import { Http, Headers, Response, RequestOptions } from '@angular/http';
@Injectable()
export class ApplicationService {
constructor(private http: Http) {
}
myformPost(id:number, formData : any){
let header = this.initHeaders();
let options = new RequestOptions({ headers: header, method: 'post'});
let body = JSON.stringify(formData);
return this.http.post(this.myapiUrl, body, options)
.map(res => {
return res.json();
})
.catch(this.handleError.bind(this));
}
private initHeaders(): Headers {
var headers = new Headers();
let token = localstorage.getItem(StorageKey.USER_TOKEN);
if (token !== null) {
headers.append('Authorization', token);
}
headers.append('Pragma', 'no-cache');
headers.append('Content-Type', 'application/json');
headers.append('Access-Control-Allow-Origin', '*');
return headers;
}
private handleError(error: any): Observable<any> {
return Observable.throw(error.message || error);
}
}
用于您的请求选项。
ApplicationService.ts
CALL DBMS_DEBUG_JDWP.CONNECT_TCP( '10.50.10.117', '62378' )
CALL DBMS_DEBUG_JDWP.CONNECT_TCP( '10.50.10.117', '62388' )
答案 2 :(得分:0)
从屏幕截图中,我假设您正在提出OPTIONS
请求,而不是POST
。
可能问题出在服务器端。看看这个答案:http post - how to send Authorization header?
您还应该考虑在您的请求选项中添加withCredentials
。
const formData = {
email_address: this.emailControl.value,
status: 'subscribed',
merge_fields: {
NAME: this.nameControl.value
}
};
const header = new HttpHeaders({
'Authorization': 'apikey:' + environment.mailChimpApiKey
});
this.http.post(this.mailChimpUrl, formData, {
headers: header,
observe: 'response',
withCredentials: true
}).subscribe(response => {
console.log('response', response);
if (response.status === 200) {
this.submitted = true;
}
});
withCredentials:boolean | null
启用请求的使用凭据。
答案 3 :(得分:0)
我非常愿意评论原始海报的答案,因为我认为这是正确的,澄清评论可能有助于该人获得+1回答。
所以......
如果我在angular和我的两个域之间运行代码并使用say节点来提供数据,我必须在节点服务器的开发过程中输入以下内容。我最初这样做是为了确保所有人都在开发中工作。
app.use(function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT,
PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
res.setHeader('Access-Control-Allow-Credentials', true); //
next();
});
这会清除您的错误,但是对于交叉脚本来说太开放了,您可以阅读如何允许特定域等访问它而不是此处提供的*。