Twisted - Request did not return bytes - python-3.x

I have basic twister app and i keep getting errors like that:
Request did not return bytes
Request:
Resource:
<main.MainPageDispatcher object at 0x7f049fa62be0>
Value:
'hello'
Everywhere, even in official docs' examples I see that string is returned and yet it not works for me. If I comment out first return and send bytes instead of string it is working.
Can anyone help me understand how it works? If it has to be in bytes then why official guides are returning strings?
My code:
from twisted.web.server import Site
from twisted.web.static import File
from twisted.web.resource import Resource
from twisted.internet import reactor
class MainPageDispatcher(Resource):
isLeaf = True
def __init__(self):
super().__init__()
def render_GET(self, request):
request.setHeader(b"content-type", b"text/html")
return "hello"
return bytes("hello", "utf-8")
root = MainPageDispatcher()
factory = Site(root)
reactor.listenTCP(8888, factory)
reactor.run()

In python3 I'm using:
def render_GET(self, request):
request.setHeader("Content-Type", "text/html; charset=utf-8")
return "<html>Hello, world!</html>".encode('utf-8')
str.encode('utf-8') returns a bytes representation of the Unicode string

Related

Response not loading in localhost when using requests.request method in python

import tornado.web
import tornado.ioloop
from apiApplicationModel import userData
from cleanArray import Label_Correction
import json
import requests
colName=['age', 'resting_blood_pressure', 'cholesterol', 'max_heart_rate_achieved', 'st_depression', 'num_major_vessels', 'st_slope_downsloping', 'st_slope_flat', 'st_slope_upsloping', 'sex_male', 'chest_pain_type_atypical angina', 'chest_pain_type_non-anginal pain', 'chest_pain_type_typical angina', 'fasting_blood_sugar_lower than 120mg/ml', 'rest_ecg_left ventricular hypertrophy', 'rest_ecg_normal', 'exercise_induced_angina_yes', 'thalassemia_fixed defect', 'thalassemia_normal',
'thalassemia_reversable defect']
class processRequestHandler(tornado.web.RequestHandler):
def post(self):
data_input_array = []
for name in colName:
x = self.get_body_argument(name, default=0)
data_input_array.append(int(x))
label = Label_Correction(data_input_array)
finalResult = int(userData(label))
output = json.dumps({"Giveput":finalResult})
self.write(output)
class basicRequestHandler(tornado.web.RequestHandler):
def get(self):
self.render('report.html')
class staticRequestHandler(tornado.web.RequestHandler):
def post(self):
data_input_array = []
for name in colName:
x = self.get_body_argument(name, default=0)
data_input_array.append(str(x))
send_data = dict(zip(colName, data_input_array))
print(send_data)
print(type(send_data))
url = "http://localhost:8887/output"
headers={}
response = requests.request('POST',url,headers=headers,data=send_data)
print(response.text.encode('utf8'))
print("DONE")
if __name__=='__main__':
app = tornado.web.Application([(r"/",basicRequestHandler),
(r"/result",staticRequestHandler),
(r"/output",processRequestHandler)])
print("API IS RUNNING.......")
app.listen(8887)
tornado.ioloop.IOLoop.current().start()
Actually I am trying to create an API and the result of the API can be used but
The page keeps on loading, and no response is shown.
Response should be a python dictionary send by post function of class processRequestHandler
After using a debugger the lines after response = requests.request('POST',url,headers=headers,data=send_data) are not executed.
The class processRequestHandler is working fine when checked with POSTMAN.
requests.request is a blocking method. This blocks the event loop and prevents any other handlers from running. In a Tornado handler, you need to use Tornado's AsyncHTTPClient (or another non-blocking HTTP client such as aiohttp) instead.
async def post(self):
...
response = await AsyncHTTPClient().fetch(url, method='POST', headers=headers, body=send_data)
See the Tornado users's guide for more information.

Call Method of another class in Flask API

I am trying to expose a data service as an API for a PHP application. I have written the API logic in a file called APILogic.py. The code in this looks like this
class APILogic(object):
def __init__(self):
# the initialization is done here
...
def APIfunction(self):
# the API logic is built here, it uses the class variables and methods
...
I have created another file for the API purpose. Its called API.py. The code in this file looks like this
import APILogic from APILogic
class MyFlask:
def __init__(self):
self.test = APILogic()
from flask import Flask
app = Flask(__name__)
my_flask = MyFlask()
#app.route("/Test")
def Test():
return my_flask.test.APIfunction
if __name__ == "__main__":
app.run(debug=True,port=9999)
When I run the code, I get the error
> TypeError: APIfunction() takes 1 positional argument but 3 were given
The view function did not return a valid response. The return type must be a string, dict, tuple, Response instance, or WSGI callable, but it was a method.
There are no arguments for the APIfunction though.
Please help.
The view function did not return a valid response. The return type must be a string, dict, tuple, Response instance, or WSGI callable, but it was a method.
Looks like you're returning the method, but it sounds like you want to return the result of that method:
#app.route("/Test")
def Test():
return my_flask.test.APIfunction()
View function should return valid response.
Sample API code
from flask import Flask
app = Flask(__name__)
#app.route("/")
def hello():
return "Hello World!"
if __name__ == "__main__":
app.run()

How to capture API failure while using oauthlib.oauth2 fetch_token

The Python3 fetch_token method in this library does not check the response status before consuming the response. If the API call it makes fails, then the response will be invalid and the script crashes. Is there something I can set so that an exception will be raised on a non-success response before the library can read the response?
import requests
from requests.auth import HTTPBasicAuth
from requests_oauthlib import OAuth2Session
from oauthlib.oauth2 import BackendApplicationClient
from oauthlib.oauth2 import OAuth2Error
AUTH_TOKEN_URL = "https://httpstat.us/500" # For testing
AUTH = HTTPBasicAuth("anID", "aSecret")
CLIENT = BackendApplicationClient(client_id="anID")
SCOPES = "retailer.orders.write"
MAX_API_RETRIES = 4
class MyApp:
def __init__(self):
"""Initialize ... and obtain initial auth token for request"""
self.client = OAuth2Session(client=CLIENT)
self.client.headers.update(
{
"Content-Type": "application/json"
}
)
self.__authenticate()
def __authenticate(self):
"""Obtain auth token."""
server_errors = 0
# This needs more work. fetch_token is not raising errors but failing
# instead.
while True:
try:
self.token = self.client.fetch_token(
token_url=AUTH_TOKEN_URL, auth=AUTH, scope=SCOPES
)
break
except (OAuth2Error, requests.exceptions.RequestException) as e:
server_errors = MyApp.__process_retry(
server_errors, e, None, MAX_API_RETRIES
)
#staticmethod
def __process_retry(errors, exception, resp, max_retries):
# Log and process retries
# ...
return errors + 1
MyApp() # Try it out
You can add a "compliance hook" that will be passed the Response object from requests before the library attempts to parse it, like so:
def raise_on_error(response):
response.raise_for_status()
return response
self.client.register_compliance_hook('access_token_response', raise_on_error)
Depending on exactly when you may get errors, you might want to do this with 'refresh_token_response' and/or 'protected_request' as well. See the docstring for the register_compliance_hook method for more info.

Rauth with google provider and python3

I've got some problem using the rauth library with flask, python3 and google oauth, python2 works without problems.
It says TypeError: the JSON object must be str, not 'bytes'
Here is the log error:
I've found that Issue here and tried to convert the byte to string
decoder=lambda b: json.loads(str(b))
but without success.
Here is my Implementation
class GoogleSignIn(OAuthSignIn):
def __init__(self):
super(GoogleSignIn, self).__init__('google')
self.service = OAuth2Service(
name='google',
client_id=self.consumer_id,
client_secret=self.consumer_secret,
authorize_url='https://accounts.google.com/o/oauth2/auth',
access_token_url='https://accounts.google.com/o/oauth2/token',
base_url='https://www.googleapis.com/plus/v1/people/'
)
def authorize(self):
return redirect(self.service.get_authorize_url(
scope='email',
response_type='code',
redirect_uri=self.get_callback_url())
)
def callback(self):
if 'code' not in request.args:
return None, None, None
oauth_session = self.service.get_auth_session(
data={'code': request.args['code'],
'grant_type': 'authorization_code',
'redirect_uri': self.get_callback_url()},
decoder=json.loads
)
me = oauth_session.get('me').json()
me_email = None
for e in me['emails']:
if e['type'] == 'account':
me_email = e['value']
return (
me.get('id'),
me.get('displayName'),
me_email)
There is anothere way mentioned to use own decoder, but dont't know how to do that, please help me.
I figured out some dirty workaround using simplejson module (also got a loads method so nothing to change here)
importing that as
import simplejson as json
before Google class lets the authentification work as expected

How can I proxy big contents with tornado on Python3?

I am trying to implement asynchronous http reverse proxy with tornado on Python3.
Handler class is as follows:
class RProxyHandler(tornado.web.RequestHandler):
#tornado.web.asynchronous
def get(self):
backend_url = 'http://backend-host/content.html' # temporary fixed
req = tornado.httpclient.HTTPRequest(
url=backend_url)
http_client = tornado.httpclient.AsyncHTTPClient()
http_client.fetch(req, self.backend_callback)
def backend_callback(self, response):
self.write(response.body)
self.finish()
When content.html is small, this code works fine. But with large content.html, this code raises Exception:
ERROR:tornado.general:Reached maximum read buffer size
I found the way to handle large contents with pycurl. Though, it seems does not work with Python3.
In addition, I added streaming_callback option to HTTPRequest. But the callback won't be called when disabled chunked response by backend server.
How can I handle large contents?
Thanks.
You should be able to pass max_buffer_size to the tornado.httpclient.AsyncHTTPClient()
call to set the max buffer size. for a 50MB buffer:
import tornado.ioloop
import tornado.web
from tornado.httpclient import AsyncHTTPClient
from tornado import gen
from tornado.web import asynchronous
class MainHandler(tornado.web.RequestHandler):
client = AsyncHTTPClient(max_buffer_size=1024*1024*150)
#gen.coroutine
#asynchronous
def get(self):
response = yield self.client.fetch("http://test.gorillaservers.com/100mb.bin", request_timeout=180)
self.finish("%s\n" % len(response.body))
application = tornado.web.Application([
(r"/", MainHandler),
])
if __name__ == "__main__":
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
Update: Now a full example program.

Resources