why I use AsyncHTTPClient timeout? - timeout

#tornado.web.authenticated
#tornado.web.asynchronous
#tornado.gen.coroutine
def post(self):
try:
files_body = self.request.files['file']
except:
error_msg = u"failed to upload file"
error_msg = self.handle_error(error_msg)
self.finish(dict(is_succ=False, error_msg=error_msg))
return
file_ = files_body[0]
filename = file_['filename']
# asynchronous request, obtain OCR info
files = [('image', filename, file_['body'])]
fields = (('api_key', config.OCR_API_KEY), ('api_secret', config.OCR_API_SECRET))
content_type, body = encode_multipart_formdata(fields, files)
headers = {"Content-Type": content_type, 'content-length': str(len(body))}
request = tornado.httpclient.HTTPRequest(config.OCR_HOST, method="POST", headers=headers, body=body,
validate_cert=False, request_timeout = 30)
try:
response = yield tornado.httpclient.AsyncHTTPClient().fetch(request)
except Exception, e:
logging.error(u'orc timeout {}'.format(e))
error_msg = u"OCR timeout"
error_msg = self.handle_error(error_msg)
self.finish(dict(is_succ=False, error_msg=error_msg))
return
if not response.error and response.body:
data = json.loads(response.body)
self.extra_info(data)
result = dict(is_succ=True, error_msg=u"", data=data)
else:
result = dict(is_succ=False, error_msg=u"request timeout", data={})
self.finish(result)
as the code shown, I want to write an api to handle id-card picture upload, and post a request to third part interface for getting the information of id-card.
This api can run well on my PC,however it timeouts on Testing Server. I cannot figure out where the problem is.

Related

Why does HERE oauth2 token request api return 401300 with Rails but works fine with Postman?

When calling the HERE authentication service (https://account.api.here.com/oauth2/token) from one of the controllers of the RoR APP (Rails 5.0.6/ruby 2.6.1) I get a 401: "401300 Signature mismatch. Authorization signature or client credential is wrong"
The Key, secret, Authorization header, content type, request body etc ... are the same as the ones used by Postman.
Postman always returns a 200 OK but the rails app systematically returns "401"
Any suggestions on what the problem is?
def fetch_new_token
# URL
api_url = 'https://account.api.here.com/oauth2/token'
# VERSION
api_version='1.0'
# GRANT TYPE
api_grant_type_for_req_body='grant_type=client_credentials'
#KEY
api_access_key_id = CGI.escape(ENV['my_access_key_id'])
#SECRET
api_access_key_secret = CGI.escape(ENV['my_access_key_secret'])
#NONCE
draft_api_nonce= [('a'..'z'), ('A'..'Z')].map(&:to_a).flatten
api_nonce=(0...20).map { draft_api_nonce[rand(draft_api_nonce.length)] }.join
#TMESTAMP
api_timestamp = (Time.now).strftime('%s')
#NORMALIZED URL
api_url_normalized = CGI.escape(api_url)
#SIGNING METHOD
api_signature_method= CGI.escape('HMAC-SHA256')
#OAUTH PARAMETERS BASE STRING
api_parameters_string=('consumer_key='+api_access_key_id+'&nonce='+api_nonce+'&signature_method='+api_signature_method+'&timestamp='+api_timestamp+'&'+'version=1.0')
#ENCODED BASE STRING
api_normalized_string = 'POST&'+api_url_normalized+'&'+api_grant_type_for_req_body+CGI.escape('&'+api_parameters_string)
#SIGNNG KEY
api_signing_key = api_access_key_secret+'&'
#SIGNATURE
digest = OpenSSL::Digest.new('sha256')
api_signature = OpenSSL::HMAC.hexdigest(digest, api_normalized_string, api_signing_key)
# convert the HASHING result to a URL ENCODED base64 string.
api_signature_encoded = (Base64.strict_encode64(api_signature))
# AUTHORIZATION STRING - ESCAPED
api_authorization_string = ('OAuth consumer_key="'+api_access_key_id+'",signature_method="'+api_signature_method+'",timestamp="'+CGI.escape(api_timestamp)+'",nonce="'+CGI.escape(api_nonce)+'",version="'+CGI.escape(api_version)+'",signature="'+CGI.escape(api_signature_encoded)+'"')
# FARADAY OBJECT
connect_token_request = Faraday.new(url: 'https://account.api.here.com') do |faraday|
faraday.response :logger, nil, bodies: true
faraday.request :json
faraday.headers['Accept'] = 'application/json'
faraday.headers['Content-Type'] = 'application/x-www-form-urlencoded'
faraday.headers['Authorization'] = api_authorization_string
faraday.adapter Faraday.default_adapter
end
# FARADAY POST
response_token_request= connect_token_request.post('/oauth2/token', 'grant_type=client_credentials' )
# CHECK THE RESULT
puts response_token_request.body
#json = JSON.parse(response_token_request.body)
req_status = #json['httpStatus']
puts "The status returned in the body is:::: #{req_status}"
puts "===== ///// ======"
puts "===== ///// ======"
req_error_code = #json['errorCode']
puts "The ERROR CODE returned in the body is:::: #{req_error_code}"
end
I don't know RoR but I had the same problem in Javascript and this script solved my problem:
const axios = require('axios')
const cryptoJS = require('crypto-js');
const btoa = require('btoa');
exports.getToken = (app_key, app_secret) => {
let url = "https://account.api.here.com/oauth2/token";
let key = encodeURI(app_key);
let secret = encodeURI(app_secret);
let nonce = btoa(Math.random().toString(36)).substring(2, 13);
let timestamp = Math.floor(Date.now()/1000);
let normalizedUrl = encodeURIComponent(url);
let signing_method = encodeURI("HMAC-SHA256");
let sig_string = "oauth_consumer_key="
.concat(key)
.concat("&oauth_nonce=")
.concat(nonce)
.concat("&oauth_signature_method=")
.concat(signing_method)
.concat("&oauth_timestamp=")
.concat(timestamp)
.concat("&").concat("oauth_version=1.0");
let normalised_string = "POST&".concat(normalizedUrl).concat("&").concat(encodeURIComponent(sig_string));
let signingKey = secret.concat("&");
let digest = cryptoJS.HmacSHA256(normalised_string, signingKey);
let signature = cryptoJS.enc.Base64.stringify(digest);
let auth = 'OAuth oauth_consumer_key="'
.concat(key)
.concat('",oauth_signature_method="')
.concat(signing_method)
.concat('",oauth_signature="')
.concat(encodeURIComponent(signature))
.concat('",oauth_timestamp="')
.concat(timestamp)
.concat('",oauth_nonce="')
.concat(nonce)
.concat('",oauth_version="1.0"')
return axios({
method: 'post',
url: url,
data: JSON.stringify({grantType: "client_credentials"}),
headers: {
'Content-Type': "application/json",
'Authorization': auth
}
});
}

wrk with lua script - generating multiple POST requests with different body

I wrote some lua script for wrk to generate multiple POST requests.
My problem is that my script is working only for the first request. All further generated requests are exactly the same as the first one. I would like that user variable will be new generated for each POST request:
lowerCase = "abcdefghijklmnopqrstuvwxyz"
characterSet = lowerCase
keyLength = 13
user = ""
math.randomseed(os.time())
for i = 1, keyLength do
rand = math.random(#characterSet)
user = user .. string.sub(characterSet, rand, rand )
end
wrk.path = "/somepath"
wrk.method = "POST"
wrk.body = [[{"username":"]].. user .. [[,"password":"somepassword"}]]
wrk.headers["Content-Type"] = "application/json"
Try something like this. It should execute request3 ~50% of the time, and the other two ~25% of the time. Cheers!
names = { "Maverick", "Goose", "Viper", "Iceman", "Merlin", "Sundown", "Cougar", "Hollywood", "Wolfman", "Jester" }
request1 = function()
headers = {}
headers["Content-Type"] = "application/json"
body = '{"name": ' .. names[math.random(#names)] .. '}'
return wrk.format("POST", "/test1", headers, body)
end
request2 = function()
headers = {}
headers["Content-Type"] = "application/json"
body = '{"name": ' .. names[math.random(#names)] .. '}'
return wrk.format("POST", "/test2", headers, body)
end
request3 = function()
headers = {}
headers["Content-Type"] = "application/json"
body = '{"name": ' .. names[math.random(#names)] .. '}'
return wrk.format("GET", "/test3", headers, body)
end
requests = {}
requests[0] = request1
requests[1] = request2
requests[2] = request3
requests[3] = request3
request = function()
return requests[math.random(0, 3)]()
end
response = function(status, headers, body)
if status ~= 200 then
io.write("------------------------------\n")
io.write("Response with status: ".. status .."\n")
io.write("------------------------------\n")
io.write("[response] Body:\n")
io.write(body .. "\n")
end
end
I'm not familiar with wrk.
I guess you're running that code multiple times within a second. As os.time has second accuracy you'll have the same randomseed and hence the same user name within that second.
From looking into the scripting examples I'd say the script is only evaluated once or maybe once per thread. Those examples implement functions that will be called by wrk. It wouldn't make sense to define those functions for every request.
Add a print to your script to make sure.
Here is an example that counts requests. You probably can put your code into that function
function request()
requests = requests + 1
return wrk.request()
end

Twitter API app-only authorization error

I am following this https://dev.twitter.com/oauth/application-only
def get_bearer_token(self):
data = {"grant_type": "client_credentials"}
headers = {"Authorization": "Basic " + self.encoded_cred}
r = requests.post("https://api.twitter.com/oauth2/token",
data=data, headers=headers)
res = r.json()
if res.get('token_type') != 'bearer':
raise Exception("invalid type")
self.access_token = res['access_token']
def search(self, q):
data = {"count": 100, "q": q}
headers = {"Authorization": "Bearer " + self.access_token}
r = requests.get("https://api.twitter.com/1.1/search/tweets.json", data=data, headers=headers)
print r.status_code
print r.text
I was able to get an access_token but the search API call returns 400 with no content. Any idea?
Similar to this https://stackoverflow.com/questions/24102409/twitter-application-only-auth-returning-empty-response but no answer yet

Stubbing result of Net::HTTP.new(url.host, url.port)

I have a funciton that calls Net::HTTP.new(google_url.host, google_url.port) and I am trying to figure out how to stub the result for testing. Basically I don't want to be hitting the google URL shortener every time I run my test.
def shorten_url(long_url)
google_url = URI.parse("https://www.googleapis.com/urlshortener/v1/url")
data = JSON.generate({"longUrl" => "#{long_url}"})
header = {"Content-Type" => "application/json"}
http = Net::HTTP.new(google_url.host, google_url.port)
http.use_ssl = true
short_url = ""
res = http.request_post(google_url.path, data, header)
jsonResponse = JSON.parse(res.body)
short_url = jsonResponse["id"]
end
Basically I want to be able to set the result of that function.
I've tried things like: Net::HTTP.any_instance.stubs(:HTTP.new).returns("www.test.com") but cannot figure out how to get it to work.
class HTTP < Protocol
....
# Creates a new Net::HTTP object.
# If +proxy_addr+ is given, creates an Net::HTTP object with proxy support.
# This method does not open the TCP connection.
def HTTP.new(address, port = nil, p_addr = nil, p_port = nil, p_user = nil, p_pass = nil)
h = Proxy(p_addr, p_port, p_user, p_pass).newobj(address, port)
h.instance_eval {
#newimpl = ::Net::HTTP.version_1_2?
}
h
end
....
end
Check out webmock - this sounds like it will do exactly what you're looking for.

How do I use the Bilty API to shorten a list of URLs?

I have an account with Bitly which personalizes my URL shortening. How can I use the API to sign in and shorten a list of URLs?
Here is my solution in python using python requests library
import base64
import requests
import json
credentials = 'USERNAME:PASSWORD'
urls = ['www.google.com', 'www.google.co.uk', 'www.google.fr']
def getShortURLs(urls):
token = auth()
return shortenURLs(token, urls)
def auth():
base_auth = "https://api-ssl.bitly.com/oauth/access_token"
headers = {'Authorization': 'Basic ' + base64.b64encode(credentials)}
resp = requests.post(base_auth, headers=headers)
return resp.content
def shortenURLs(token, long_urls):
base = 'https://api-ssl.bitly.com/v3/shorten'
short_urls = []
for long_url in long_urls:
if long_url:
params = {'access_token':token, 'longUrl' : 'https://' + long_url}
response = requests.get(base, params=params)
r = json.loads(response.content)
short_urls.append(r['data']['url'])
return short_urls

Resources