I'm exploring Bitso API (Bitso is a mexican crypto exchange).
The docs of the API is well explained at some languages such as Python and Ruby for its use. The problem here is that there are no examples using straight URLs for request.
What I'm planning to do is to create the URL that the code is creating on its requests function.
There is a request for balance account, that is the data I'd like to get.
According documentation, this is a private request that need some headers at the request (Key, nonce and signature), you can take a look here.
The code to make this request in Python is the following one:
import time
import hmac
import hashlib
import requests
bitso_key = "BITSO_KEY"
bitso_secret = "BITSO_SECRET"
nonce = str(int(round(time.time() * 1000)))
http_method = "GET"
request_path = "/v3/balance/"
json_payload = ""
# Create signature
message = nonce+http_method+request_path+json_payload
signature = hmac.new(bitso_secret.encode('utf-8'),
message.encode('utf-8'),
hashlib.sha256).hexdigest()
# Build the auth header
auth_header = 'Bitso %s:%s:%s' % (bitso_key, nonce, signature)
# Send request
response = requests.get("https://api.bitso.com/v3/balance/", headers={"Authorization": auth_header})
print(response.content)
So based in this I could say that the URL is something like this:
https://api.bitso.com/v3/balance/Bitso%20<Key>:<nonce>:<signature>
I'm sure that I'm wrong with that supposition, I understand that headers={"Authorization": auth_header} seems to be a JSON object used as header in the URL, but I'd like to know how that JSON object is translated at the URL to make a request. I'd like to copy-paste that URL at the browser and get the data as response.
I need that URL so I could use it to connect the service to a Business Intelligence tool.
Thanks!
According to the documentation this Authorization is a header in the request. You can try using postman but you still need hash the destination URL with your api key and the nonce to avoid replay attacks.
Related
Background
I am making a spreadsheet that refers to information security license registration provided by the Japanese government (https://riss.ipa.go.jp/). The spreadsheet will be used on Microsoft Excel/LibreOffice Calc on Windows/Linux, so I want to avoid using platform-specific functionality like a script with the XMLHTTP60 module.
The site https://riss.ipa.go.jp has a URI that can retrieve registration information with a registration number (https://riss.ipa.go.jp/ajax/findRissRequest). The URI only works with a POST request with the application/x-www-form-urlencoded style request body and doesn't work with a GET request. The response of the URI is JSON format.
Problem #1
Microsoft Excel and LibreOffice Calc have the WEBSERVICE function that can be used to send a request to a URI. This function is supported on all platforms and is suitable for my use case.
Unfortunately, the WEBSERVICE function only supports GET requests, and the URI I want to use only supports POST requests.
Problem #2
Microsoft Excel and LibreOffice Calc have the FILTERXML function that can be used to extract a specific element from XML.
Unfortunately, the URI I want to use returns response in JSON format. There are no functions to parse JSON in Microsoft Excel and LibreOffice Calc.
Question
Is there any way to convert GET request to POST request and extract a JSON property?
For example, is there any Web API like http://api.example.com/convert/get-to-post?uri=https://riss.ipa.go.jp/ajax/findRissRequest®_no=000006&property=result.reg_date that calls https://riss.ipa.go.jp/ajax/findRissRequest with POST request body reg_no=000006 and extract property result.reg_date from its response?
After all, I could not find any existing services. So I made a web API service with AWS Lambda and API Gateway.
First, I made a Lambda function like this:
import json
import urllib.request
import urllib.parse
def lambda_handler(event, context):
queryStringParameters = event.get('params').get('querystring')
data = urllib.parse.urlencode(queryStringParameters)
data = data.encode('UTF-8')
f = urllib.request.urlopen("https://riss.ipa.go.jp/ajax/findRissRequest", data)
j = json.loads(f.read().decode('utf-8'))
return j
Then I made a resource with a GET method in API Gateway and connect it with the Lambda function.
In Integration Request, you have to use non-proxy integration. Also, you have to specify a mapping template for Content-Type application/json with Method Request passthrough template.
In Integration Response, you have to specify a mapping template for Content-Type application/xml like this:
<?xml version="1.0" encoding="UTF-8" ?>
#set($root = $input.path('$.result[0]'))
<result>
#foreach($key in $root.keySet())
<$key>$root.get($key)</$key>
#end
</result>
Then I added the HEAD and OPTIONS method for the resource. It is because the WEBSERVICE function of LibreOffice sends OPTIONS and HEAD requests before a GET request.
You can use a mock in Integration Request with a mapping template for Content-Type application/json like { "statusCode": 200 }.
The result of WEBSERVICE function will be #VALUE! without these methods.
Finally, I can get a property from a web service that only accepts POST requests and returns a JSON with WEBSERVICE and FILTERXML like:
=FILTERXML(WEBSERVICE("https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/prod/passthru?reg_no=000006"),"//result/reg_date")
I am trying to send some JSON data to an Odoo controller, but when I send the request, I always get 404 as response.
This is the code of my controller:
import openerp.http as http
import logging
_logger = logging.getLogger(__name__)
class Controller(http.Controller):
#http.route('/test/result', type='json', auth='public')
def index(self, **args):
_logger.info('The controller is called.')
return '{"response": "OK"}'
Now, I type the URL (http://localhost:8069/test/result) on the browser to check if it is available, and I get function index at 0x7f04a28>, /test/result: Function declared as capable of handling request of type 'json' but called with a request of type 'http'. This way I know that the controller is listening at that URL and is expecting JSON data.
So I open a Python console and type:
import json
import requests
data = {'test': 'Hello'}
data_json = json.dumps(data)
r = requests.get('http://localhost:8069/test/result', data=data_json)
When I print r in the console, it returns <Response [404]>, and I cannot see any message in the log (I was expecting The controller is called.).
There is a similar question here, but it is not exactly the same case:
OpenERP #http.route('demo_json', type="json") URL not displaying JSON Data
Can anyone help me? What am I doing wrong?
I have just solved the problem.
Firstly, as #techsavvy told, I had to modify the decorator, to write type='http' instead of type='json'.
And after that, the request from the console returned a 404 error because it did not know which database it was sending data to. In localhost:8069 I had more than one database. So I tried to have only one at that port. And that is, now it works great!
To manage that without removing any of the other databases, I have just modified the config file to change the parameter db_filter and put there a regular expression which only included my current database.
I have just gone through your issue and I noticed that you have written JSON route which is call from javascript. if you want to call it from browser url hit then you have to define router with type="http" and auth="public" argument in route:
#http.route('/', type='http', auth="public", website=True)
It's not under the supported libraries here:
https://developers.google.com/api-client-library/python/reference/supported_apis
Is it just not available with Python? If not, what language is it available for?
Andre's answer points you at a correct place to reference the API. Since your question was python specific, allow me to show you a basic approach to building your submitted search URL in python. This example will get you all the way to search content in just a few minutes after you sign up for Google's free API key.
ACCESS_TOKEN = <Get one of these following the directions on the places page>
import urllib
def build_URL(search_text='',types_text=''):
base_url = 'https://maps.googleapis.com/maps/api/place/textsearch/json' # Can change json to xml to change output type
key_string = '?key='+ACCESS_TOKEN # First think after the base_url starts with ? instead of &
query_string = '&query='+urllib.quote(search_text)
sensor_string = '&sensor=false' # Presumably you are not getting location from device GPS
type_string = ''
if types_text!='':
type_string = '&types='+urllib.quote(types_text) # More on types: https://developers.google.com/places/documentation/supported_types
url = base_url+key_string+query_string+sensor_string+type_string
return url
print(build_URL(search_text='Your search string here'))
This code will build and print a URL searching for whatever you put in the last line replacing "Your search string here". You need to build one of those URLs for each search. In this case I've printed it so you can copy and paste it into your browser address bar, which will give you a return (in the browser) of a JSON text object the same as you will get when your program submits that URL. I recommend using the python requests library to get that within your program and you can do that simply by taking the returned URL and doing this:
response = requests.get(url)
Next up you need to parse the returned response JSON, which you can do by converting it with the json library (look for json.loads for example). After running that response through json.loads you will have a nice python dictionary with all your results. You can also paste that return (e.g. from the browser or a saved file) into an online JSON viewer to understand the structure while you write code to access the dictionary that comes out of json.loads.
Please feel free to post more questions if part of this isn't clear.
Somebody has written a wrapper for the API: https://github.com/slimkrazy/python-google-places
Basically it's just HTTP with JSON responses. It's easier to access through JavaScript but it's just as easy to use urllib and the json library to connect to the API.
Ezekiel's answer worked great for me and all of the credit goes to him. I had to change his code in order for it to work with python3. Below is the code I used:
def build_URL(search_text='',types_text=''):
base_url = 'https://maps.googleapis.com/maps/api/place/textsearch/json'
key_string = '?key=' + ACCESS_TOKEN
query_string = '&query=' + urllib.parse.quote(search_text)
type_string = ''
if types_text != '':
type_string = '&types='+urllib.parse.quote(types_text)
url = base_url+key_string+query_string+type_string
return url
The changes were urllib.quote was changed to urllib.parse.quote and sensor was removed because google is deprecating it.
I have successfully created my app and now want to connect it to a localhost to check the working of my app. I have been suggested to use restsharp for connecting to the server using php and json to receive data from server.
I have looked at codes for both but do not completely understand how the process works. I have looked into all forums but found could snippets with no explanation as how it works. I have even tried restsharp.org and google search results. Please explain me as to how this works.
RestSharp is a library that helps you invoking REST web services.
You use RestSharp on your client to invoke Rest style Web Services (send and receive data)
Here is an example on the usage of your service:
var client = new RestClient(baseUrl);
var request = new RestRequest("/*rest_resource*/", Method.POST);
// see Rest services
// set the request format - HTTP Content-Type text/xml
request.RequestFormat = DataFormat.Xml;
// add data to the request
request.AddBody("<books><book>RestSharp Book</book></books>");
/* send the request and if your service returns text put the as expected return type; otherwise you will get raw byte array*/
IRestResponse response = client.Execute(request);
//HTTP status code 200-success
Assert.IsTrue(response.StatusCode == HttpStatusCode.OK);
Assert.IsTrue(!string.IsNullOrEmpty(response.Data)); // the response is not empty
I have a web application for iPhone, which will ultimately run within a PhoneGap application - but for now I'm running it in Safari.
The application needs to access tweets from Twitter friends, including private tweets. So I've implemented OAuth using the Scribe library. I successfully bounce users to Twitter, have them authenticate, then bounce back.
At this point the web app has oAuth credentials (key and token) which it persists locally. From here on I'd like it to user the Twitter statuses/user_timeline.json method to grab tweets for a particular user. I have the application using JSONP requests to do this with unprotected tweets successfully; when it accesses the timeline of a private Twitter feed, an HTTP basic authentication dialog appears in the app.
I believe that I need to provide the OAuth credentials to Twitter, so that my web application can identify and authenticate itself. Twitter recommends doing so through the addition of an HTTP Authorization header, but as I'm using JSONP for the request I don't think this is an option for me. Am I right in assuming this?
My options therefore appear to either be putting the oAuth credentials as query-string parameters (which Twitter recommends against, but documentation suggests still supports); or proxying all the Tweets through an intermediate server. I'd rather avoid the latter.
I access the Twitter API using URLs of the form
http://api.twitter.com/1/statuses/user_timeline.json?user_id=29191439&oauth_nonce=XXXXXXXXXXX&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1272323042&oauth_consumer_key=XXXXXXXXXX&oauth_signature=XXXXXXXXXX&oauth_version=1.0
When user_id is a public user, this works fine. When user_id is a private user, I get that HTTP Basic Auth dialog. Any idea what I'm doing wrong? I'm hoping it's something embarrassingly simple like "forgetting an important parameter"...
The oAuth stanza needs to be exact, as per http://dev.twitter.com/pages/auth#auth-request - I ended up building an Authorization: header that I could first check with curl.
I built it using the really helpful interactive request checker at http://hueniverse.com/2008/10/beginners-guide-to-oauth-part-iv-signing-requests/
Here's a friends API request for a protected user:
curl -v -H 'Authorization: OAuth realm="https://api.twitter.com/1/friends/ids.json", oauth_consumer_key="XXXXXXXXXXXXXXXX", oauth_token="XXXXXXXXXXXXXXXX", oauth_nonce="XXXXXXXXXXXXXXXX", oauth_timestamp="1300728665", oauth_signature_method="HMAC-SHA1", oauth_version="1.0", oauth_signature="XXXXXXXXXXXXXXXX%3D"' https://api.twitter.com/1/friends/ids.json?user_id=254723679
It's worth re-iterating that as you've tried to do, instead of setting the Authorization header via e.g. jquery's beforeSend function, that for cross-domain JSONP requests (which can't add HTTP headers) you can make oAuth requests by putting all the relevant key/value pairs in the GET request. This should hopefully help out various other questioners, e.g
Set Headers with jQuery.ajax and JSONP?
Modify HTTP Headers for a JSONP request
Using only JQuery to update Twitter (OAuth)
Your request looks like it has a couple of problems; it's missing the user's oauth_token plus the oauth_signature doesn't look like it has been base64 encoded (because it's missing a hex encoded = or ==, %3 or %3D%3D respectively).
Here's my GET equivalent using oAuth encoded querystring params, which you can use in a cross-domain JSONP call:
https://api.twitter.com/1/friends/ids.json?user_id=254723679&realm=https://api.twitter.com/1/friends/ids.json&oauth_consumer_key=XXXXXXXXXXXXXXXX&oauth_token=XXXXXXXXXXXXXXXX&oauth_nonce=XXXXXXXXXXXXXXXX&oauth_timestamp=1300728665&oauth_signature_method=HMAC-SHA1&oauth_version=1.0&oauth_signature=XXXXXXXXXXXXXXXX%3D
I was struggling with similar problem of making JSONP requests from Jquery, the above answer helped just to add what I did to achieve my solution.
I am doing server to server oauth and then I send oauth token, secret, consumer key and secret (this is temporary solution by the time we put a proxy to protect consumer secret). You can replace this to token acquiring code at client.
Oauth.js and Sha1.js download link!
Once signature is generated.
Now there are 2 problems:
JSONP header cannot be edited
Signed arguments which needs to be sent as part of oauth have problem with callback=? (a regular way of using JSONP).
As above answer says 1 cannot be done.
Also, callback=? won't work as the parameter list has to be signed and while sending the request to remote server Jquery replace callback=? to some name like callback=Jquery1232453234. So a named handler has to be used.
function my_twitter_resp_handler(data){
console.log(JSON.stringify(data));
}
and getJSON did not work with named function handler, so I used
var accessor = {
consumerSecret: XXXXXXXXXXXXXXXXXXXXXX,
tokenSecret : XXXXXXXXXXXXXXXXXXXXXX
};
var message = { action: "https://api.twitter.com/1/statuses/home_timeline.json",
method: "GET",
parameters: []
};
message.parameters.push(['realm', "https://api.twitter.com/1/statuses/home_timeline.json"]);
message.parameters.push(['oauth_version', '1.0']);
message.parameters.push(['oauth_signature_method', 'HMAC-SHA1']);
message.parameters.push(['oauth_consumer_key', XXXXXXXXXXXXXXXX]);
message.parameters.push(['oauth_token', XXXXXXXXXXXXXXX]);
message.parameters.push(['callback', 'my_twitter_resp_handler']);
OAuth.completeRequest(message, accessor);
var parameterMap = OAuth.getParameterMap(message.parameters);
Create url with base url and key value pairs from parameterMap
jQuery.ajax({
url: url,
dataType: "jsonp",
type: "GET",
});