Insightly CRM Ajax API 代理
Insightly CRM Ajax API proxy
更新
您好,我目前在尝试连接到 Insightlys CRM API 时遇到 CORS 错误。我正在通过 POSTMAN 成功检索我的 Insightly CRM 数据。
Insightly 不支持 AJAX 请求 (http://support.insight.ly/hc/en-us/community/posts/206961417-Using-the-API-with-AJAX) 的 CORS,您必须设置 API 代理脚本。我使用了在 python 中完成的以下提供的代理脚本并上传到我的专用主机。但是我仍然收到 401 错误?
我对 API 代理很陌生,所以不确定我是否遗漏了什么?
GET https://api.insight.ly/v2.2/Contacts 401 (Unauthorized)
apiproxy.py
#
# Insightly API Proxy for Python / App Engine
# Brian McConnell <brian@insightly.com>
#
# This utility is designed to act as an API proxy server. It is written in Python 2.7
# and will run without modification on Google App Engine. Just serve your JavaScript
# from the /js directory in this project, and AJAX requests should be relayed through
# to the Insightly service. This should also run on any webapp2 compatible server platform
#
import base64
import os
import string
import types
import urllib
import urllib2
import webapp2
import wsgiref.handlers
#
# import google app engine libraries, replace these with standard
#
try:
from google.appengine.ext import webapp
except:
# skip Google App Engine webapp library
pass
base_url = 'https://api.insight.ly/v2.2'
def authenticate():
#
# add user validation logic here, be careful to do this in a way that does not expose user secrets such as
# the user API key (this is why we do not allow CORS in the first place)
#
# hardcoding API key for now
apikey = 'fillinhere'
return base64.encode(apikey)
def generateRequest(url, method, data, alt_auth=None, test=False, headers=None):
"""
This method is used by other helper functions to generate HTTPS requests and parse server responses. This will minimize the amount of work developers need to do to integrate with the Insightly API, and will also eliminate common sources of errors such as authentication issues and malformed requests. Uses the urllib2 standard library, so it is not dependent on third party libraries like Requests
"""
if type(url) is not str: raise Exception('url must be a string')
if type(method) is not str: raise Exception('method must be a string')
valid_method = False
response = None
text = ''
if method == 'GET' or method == 'PUT' or method == 'DELETE' or method == 'POST':
valid_method = True
else:
raise Exception('parameter method must be GET|DELETE|PUT|UPDATE')
request = urllib2.Request(url)
request.get_method = lambda: method
request.add_header('Content-Type', 'application/json')
if headers is not None:
headerkeys = headers.keys()
for h in headerkeys:
request.add_header(h, headers[h])
# open the URL, if an error code is returned it should raise an exception
if method == 'PUT' or method == 'POST':
result = urllib2.urlopen(request, data)
else:
result = urllib2.urlopen(request)
text = result.read()
return text
class APIProxyHandler(webapp2.RequestHandler):
def delete(self):
apikey = authenticate()
path_qs = self.request.headers['path_qs']
url = base_url + path_qs
headers = {'Authorization','Basic ' + api_key}
text = generateRequest(url, 'DELETE', None, headers=headers)
self.response.headers['Content-Type']='application/json'
self.response.out.write(text)
def get(self):
apikey = authenticate()
path_qs = self.request.headers['path_qs']
url = base_url + path_qs
headers = {'Authorization','Basic ' + api_key}
text = generateRequest(url, 'GET', None, headers=headers)
self.response.headers['Content-Type']='application/json'
self.response.out.write(text)
def post(self):
body = self.request.headers['body']
path_qs = self.request.headers['path_qs']
url = base_url + path_qs
headers = {'Authorization','Basic ' + api_key}
text = generateRequest(url, 'POST', body, headers=headers)
self.response.headers['Content-Type']='application/json'
self.response.out.write(text)
def put(self):
body = self.request.headers['body']
path_qs = self.request.headers['path_qs']
url = base_url + path_qs
headers = {'Authorization','Basic ' + api_key}
text = generateRequest(url, 'PUT', body, headers=headers)
self.response.headers['Content-Type']='application/json'
self.response.out.write(text)
app = webapp2.WSGIApplication([("r/(.*)", APIProxyHandler)], debug=True)
# map generic page server request handler
jQuery/Ajax 通话:
Insightly = function () {
var _t = this;
this.events = function () {
$(".contactsform").submit(_t.searchContacts);
};
this.searchContacts = function (event) {
event.preventDefault();
var $search = $(this);
console.log('[ Search contacts event ]');
$.ajaxPrefilter( function( options ) {
if ( options.crossDomain ) {
var newData = {};
newData.data = $.extend({}, options.data);
newData.url = options.url;
options = {};
// Set the proxy URL
options.url = "http://www.blahblah.comm/apiproxy.py";
console.log("ajaxprefilter");
options.data = $.param(newData);
console.log(options);
options.crossDomain = false;
}
});
// How to use the cross domain proxy
$.ajax({
url: 'https://api.insight.ly/v2.2/Contacts',
crossDomain: true,
processData: false
}).success(function(data) {
var jsonData = JSON.parse(data);
console.log(jsonData);
});
};//End SearchContacts
this.init = function () {
_t.events();
};
this.init();
return (this);
};//End main function
var LZ = new Insightly();
非常感谢您的帮助。
这意味着您无法使用来自 client-side 的 AJAX 或 javascript http 请求直接访问他们的 API。您需要做的是创建一个 "Proxy" API。
A "Proxy" API 是您需要在客户端代码所在的域中托管的服务。您需要使用您最喜欢的 server-side 语言编写对 Insightly CRM API 的经过身份验证的 server-side API 调用,并使用您的 jquery AJAX 调用它。
所以下面的代码将是:
var searchNotesUrl = "https://myowndomain.com/your/api/proxy/notes"
换句话说,您的 server-side 脚本将是将数据从 CRM API 中继到您的客户的脚本。
如果它仍然收到 401 响应,那么您可能需要检查用户和 API 密钥凭据是否正确。
更新
你现在完全改变了问题。我上面的回答是针对你的最后一个问题版本。
对于新答案,您对这段代码有疑问:
$.ajaxPrefilter( function( options ) {
if ( options.crossDomain ) {
var newData = {};
newData.data = $.extend({}, options.data);
newData.url = options.url;
options = {};
// Set the proxy URL
options.url = "http://www.blahblah.comm/apiproxy.py";
console.log("ajaxprefilter");
options.data = $.param(newData);
console.log(options);
options.crossDomain = false;
}
});
// How to use the cross domain proxy
$.ajax({
url: 'https://api.insight.ly/v2.2/Contacts',
crossDomain: true,
processData: false
}).success(function(data) {
var jsonData = JSON.parse(data);
console.log(jsonData);
});
首先,您仍在向 'https://api.insight.ly/v2.2/Contacts'
请求。您不需要再请求此 URL,因为您已经拥有代理 api。代理 api ("http://www.blahblah.comm/apiproxy.py"
) 是您应该直接调用的代理,而不是向 insight.ly.
发送请求
您的代理 API,应该处理可以在 insight.ly 中发送的所有 api 请求。这意味着 "http://www.blahblah.comm/apiproxy.py"
可以支持 notes
, Contacts
等
其次,您可以阅读 python 脚本,它实际上查找请求 header 键 'path_qs'
。 path_qs
值应该类似于 /Contacts
。原因是因为 path_qs
通过 url = base_url + path_qs
.
在脚本中与 base_url = 'https://api.insight.ly/v2.2'
连接
所以代码应该是这样的:
$.ajax({
method: 'GET', //this is because it is supposed to be GET
crossDomain: true,
dataType: 'json',
url: 'http://www.blahblah.comm/apiproxy/that/executes',
headers: { 'path_qs': '/Contacts' },
success : function(data, status, xhr) {
console.log(data);
}
});
您需要在 Google 应用引擎云中将 Python 脚本设置为应用程序。要了解更多信息,这是一个全新的主题:
https://cloud.google.com/appengine/docs/python/gettingstartedpython27/helloworld
更新
您好,我目前在尝试连接到 Insightlys CRM API 时遇到 CORS 错误。我正在通过 POSTMAN 成功检索我的 Insightly CRM 数据。
Insightly 不支持 AJAX 请求 (http://support.insight.ly/hc/en-us/community/posts/206961417-Using-the-API-with-AJAX) 的 CORS,您必须设置 API 代理脚本。我使用了在 python 中完成的以下提供的代理脚本并上传到我的专用主机。但是我仍然收到 401 错误?
我对 API 代理很陌生,所以不确定我是否遗漏了什么?
GET https://api.insight.ly/v2.2/Contacts 401 (Unauthorized)
apiproxy.py
#
# Insightly API Proxy for Python / App Engine
# Brian McConnell <brian@insightly.com>
#
# This utility is designed to act as an API proxy server. It is written in Python 2.7
# and will run without modification on Google App Engine. Just serve your JavaScript
# from the /js directory in this project, and AJAX requests should be relayed through
# to the Insightly service. This should also run on any webapp2 compatible server platform
#
import base64
import os
import string
import types
import urllib
import urllib2
import webapp2
import wsgiref.handlers
#
# import google app engine libraries, replace these with standard
#
try:
from google.appengine.ext import webapp
except:
# skip Google App Engine webapp library
pass
base_url = 'https://api.insight.ly/v2.2'
def authenticate():
#
# add user validation logic here, be careful to do this in a way that does not expose user secrets such as
# the user API key (this is why we do not allow CORS in the first place)
#
# hardcoding API key for now
apikey = 'fillinhere'
return base64.encode(apikey)
def generateRequest(url, method, data, alt_auth=None, test=False, headers=None):
"""
This method is used by other helper functions to generate HTTPS requests and parse server responses. This will minimize the amount of work developers need to do to integrate with the Insightly API, and will also eliminate common sources of errors such as authentication issues and malformed requests. Uses the urllib2 standard library, so it is not dependent on third party libraries like Requests
"""
if type(url) is not str: raise Exception('url must be a string')
if type(method) is not str: raise Exception('method must be a string')
valid_method = False
response = None
text = ''
if method == 'GET' or method == 'PUT' or method == 'DELETE' or method == 'POST':
valid_method = True
else:
raise Exception('parameter method must be GET|DELETE|PUT|UPDATE')
request = urllib2.Request(url)
request.get_method = lambda: method
request.add_header('Content-Type', 'application/json')
if headers is not None:
headerkeys = headers.keys()
for h in headerkeys:
request.add_header(h, headers[h])
# open the URL, if an error code is returned it should raise an exception
if method == 'PUT' or method == 'POST':
result = urllib2.urlopen(request, data)
else:
result = urllib2.urlopen(request)
text = result.read()
return text
class APIProxyHandler(webapp2.RequestHandler):
def delete(self):
apikey = authenticate()
path_qs = self.request.headers['path_qs']
url = base_url + path_qs
headers = {'Authorization','Basic ' + api_key}
text = generateRequest(url, 'DELETE', None, headers=headers)
self.response.headers['Content-Type']='application/json'
self.response.out.write(text)
def get(self):
apikey = authenticate()
path_qs = self.request.headers['path_qs']
url = base_url + path_qs
headers = {'Authorization','Basic ' + api_key}
text = generateRequest(url, 'GET', None, headers=headers)
self.response.headers['Content-Type']='application/json'
self.response.out.write(text)
def post(self):
body = self.request.headers['body']
path_qs = self.request.headers['path_qs']
url = base_url + path_qs
headers = {'Authorization','Basic ' + api_key}
text = generateRequest(url, 'POST', body, headers=headers)
self.response.headers['Content-Type']='application/json'
self.response.out.write(text)
def put(self):
body = self.request.headers['body']
path_qs = self.request.headers['path_qs']
url = base_url + path_qs
headers = {'Authorization','Basic ' + api_key}
text = generateRequest(url, 'PUT', body, headers=headers)
self.response.headers['Content-Type']='application/json'
self.response.out.write(text)
app = webapp2.WSGIApplication([("r/(.*)", APIProxyHandler)], debug=True)
# map generic page server request handler
jQuery/Ajax 通话:
Insightly = function () {
var _t = this;
this.events = function () {
$(".contactsform").submit(_t.searchContacts);
};
this.searchContacts = function (event) {
event.preventDefault();
var $search = $(this);
console.log('[ Search contacts event ]');
$.ajaxPrefilter( function( options ) {
if ( options.crossDomain ) {
var newData = {};
newData.data = $.extend({}, options.data);
newData.url = options.url;
options = {};
// Set the proxy URL
options.url = "http://www.blahblah.comm/apiproxy.py";
console.log("ajaxprefilter");
options.data = $.param(newData);
console.log(options);
options.crossDomain = false;
}
});
// How to use the cross domain proxy
$.ajax({
url: 'https://api.insight.ly/v2.2/Contacts',
crossDomain: true,
processData: false
}).success(function(data) {
var jsonData = JSON.parse(data);
console.log(jsonData);
});
};//End SearchContacts
this.init = function () {
_t.events();
};
this.init();
return (this);
};//End main function
var LZ = new Insightly();
非常感谢您的帮助。
这意味着您无法使用来自 client-side 的 AJAX 或 javascript http 请求直接访问他们的 API。您需要做的是创建一个 "Proxy" API。
A "Proxy" API 是您需要在客户端代码所在的域中托管的服务。您需要使用您最喜欢的 server-side 语言编写对 Insightly CRM API 的经过身份验证的 server-side API 调用,并使用您的 jquery AJAX 调用它。
所以下面的代码将是:
var searchNotesUrl = "https://myowndomain.com/your/api/proxy/notes"
换句话说,您的 server-side 脚本将是将数据从 CRM API 中继到您的客户的脚本。
如果它仍然收到 401 响应,那么您可能需要检查用户和 API 密钥凭据是否正确。
更新
你现在完全改变了问题。我上面的回答是针对你的最后一个问题版本。
对于新答案,您对这段代码有疑问:
$.ajaxPrefilter( function( options ) {
if ( options.crossDomain ) {
var newData = {};
newData.data = $.extend({}, options.data);
newData.url = options.url;
options = {};
// Set the proxy URL
options.url = "http://www.blahblah.comm/apiproxy.py";
console.log("ajaxprefilter");
options.data = $.param(newData);
console.log(options);
options.crossDomain = false;
}
});
// How to use the cross domain proxy
$.ajax({
url: 'https://api.insight.ly/v2.2/Contacts',
crossDomain: true,
processData: false
}).success(function(data) {
var jsonData = JSON.parse(data);
console.log(jsonData);
});
首先,您仍在向 'https://api.insight.ly/v2.2/Contacts'
请求。您不需要再请求此 URL,因为您已经拥有代理 api。代理 api ("http://www.blahblah.comm/apiproxy.py"
) 是您应该直接调用的代理,而不是向 insight.ly.
您的代理 API,应该处理可以在 insight.ly 中发送的所有 api 请求。这意味着 "http://www.blahblah.comm/apiproxy.py"
可以支持 notes
, Contacts
等
其次,您可以阅读 python 脚本,它实际上查找请求 header 键 'path_qs'
。 path_qs
值应该类似于 /Contacts
。原因是因为 path_qs
通过 url = base_url + path_qs
.
base_url = 'https://api.insight.ly/v2.2'
连接
所以代码应该是这样的:
$.ajax({
method: 'GET', //this is because it is supposed to be GET
crossDomain: true,
dataType: 'json',
url: 'http://www.blahblah.comm/apiproxy/that/executes',
headers: { 'path_qs': '/Contacts' },
success : function(data, status, xhr) {
console.log(data);
}
});
您需要在 Google 应用引擎云中将 Python 脚本设置为应用程序。要了解更多信息,这是一个全新的主题: https://cloud.google.com/appengine/docs/python/gettingstartedpython27/helloworld