Adding query parameter for every flask GET request - python-3.x

Trying to figure out the right mechanism to use here.
I want to modify the flask request coming in every time.
I think the request is immutable, so I am trying to figure out if this mechanism exists.
Basically, I want to append a string onto the end of the request coming in.
I can hook into the request and the right time in a before_request handler like this:
#app.before_app_request
def before_request_custom():
# Get the request
req = flask.request
method = str(req.method)
if method == "GET":
# Do stuff here
pass
But I am not sure what to actually do to add this in, and don't see a way to accomplish it...I guess i could redirect, but that seems silly in this case. Any ideas?

The request object is immutable (https://werkzeug.palletsprojects.com/en/1.0.x/wrappers/#base-wrappers), but request.args or request.form can be set from ImmutableOrderedMultiDict to just OrderedMultiDict using Subclassing on Flask (https://flask.palletsprojects.com/en/1.1.x/patterns/subclassing/). Here's an example of how you could add that filter[is_deleted]=False URL param:
from flask import Flask, request, Request
from werkzeug.datastructures import OrderedMultiDict
class MyRequest(Request):
parameter_storage_class = OrderedMultiDict
class MyApp(Flask):
def __init__(self, import_name):
super(MyApp, self).__init__(import_name)
self.before_request(self.my_before_method)
def my_before_method(self):
if "endpoint" in request.base_url:
request.args["filter[is_deleted]"] = "False"
app = MyApp(__name__)
app.request_class = MyRequest
#app.route('/endpoint/')
def endpoint():
filter = request.args.get('filter[is_deleted]')
return filter
This way you can modify request.args before you actually send the request.

How about this?
from flask import g
#app.before_request
def before_request():
# Get the request
req = flask.request
method = str(req.method)
if method == "GET":
g.my_addon = "secret sauce"
return None
Then, g.my_addon is available in every view function:
from flask import g
#app.route('/my_view')
def my_view():
if g.my_addon == "secret sauce":
print('it worked!')

Using test_request_context() you can make the trick.
Related: https://flask.palletsprojects.com/en/1.1.x/quickstart/#accessing-request-data

Related

How do I create a callable object to mimic an API call?

How do I create a object that I can invoke to mimic the following api call and response. I am aware of the mock library but the use case prohibits me from using it.
response = client.users.create(email='test#gmail.com', phone=123)
outcome = response.ok
My current solution below works however I feel like there is a more pythonic and generic way to do this so I can mimic other calls without having to rewrite different inner classes
class Client:
ok = True
class users:
class create():
ok = True
def __init__(self, email, phone):
pass
Input
client = Client()
response = client.users.create(email='test#gmail.com', phone=123)
response.ok
Output
True

Google Functions Python: how to get a path parameter

I have a REST API such as: /portfolios/{userid} as the Swagger Path and this points to a google function built using Python 3.
The code is as below:
from flask import Flask, request
...
...
def portfolio_routes(request):
request_json = request.get_json()
path = request.path.lower()
method = request.method.lower()
...
Assume that the function to execute has been set to: portfolio_routes.
If I pass a URL such as: https:// ..../portfolios/1234, I get the path as: portfolios/1234. Obviously, the 1234 is userid. Like we have #app.routes by placing the userid as , is there a manner we can split the path automatically and get the userid without writing splitting code?
Thanks
I dont know much about google-cloud-functions, but if is a standard Flask request object the variables passed through url is putted in view_args, so you do
from flask import Flask, request
...
...
def portfolio_routes(request):
request_json = request.get_json()
path = request.path.lower()
method = request.method.lower()
user_id = request.view_args['userId']
...
In other way, you can do a route split, and compare you masked url(the '/portfolios/{userid}') with the coming url('/portfolios/1234'), your masked url is localized in request.url_rule and the coming url in request.PATH_INFO

How to make put request with nested dictionaries to flask-restful?

The documentation example for a simple restful api is:
from flask import Flask, request
from flask_restful import Resource, Api
app = Flask(__name__)
api = Api(app)
todos = {}
class TodoSimple(Resource):
def get(self, todo_id):
return {todo_id: todos[todo_id]}
def put(self, todo_id):
todos[todo_id] = request.form['data']
return {todo_id: todos[todo_id]}
api.add_resource(TodoSimple, '/<string:todo_id>')
if __name__ == '__main__':
app.run(host="0.0.0.0",port="80",debug=True)
However, suppose I made a put request with a nested dictionary,ie {'data':{'fruit':'orange'}}. The TodoSimple would have request.form.to_dict() = {'data':'fruit'}. How can I work with the full nested dictionary?
You should probably use Schemas to achieve this goal. Take a good look at this first example of marshmallow docs:
https://marshmallow.readthedocs.io/en/3.0/
As flask-restful docs says:
The whole request parser part of Flask-RESTful is slated for removal
and will be replaced by documentation on how to integrate with other
packages that do the input/output stuff better (such as marshmallow).

Add a new instance variable to subclass of http.server.BaseHTTPRequestHandler

I want to be able to add an instance variable to my subclass of http.server.BaseHTTPRequestHandler.
Here's my code:
from http.server import BaseHTTPRequestHandler, HTTPServer
import urllib
class Server(BaseHTTPRequestHandler):
def __init__(self, request, client_addr, server):
super().__init__(request, client_addr, server)
self.pathobj = urllib.parse.urlparse(self.path)
def do_HEAD(self):
self.send_response(200)
def do_GET(self):
print(self.pathobj)
self.send_response(200)
self.end_headers()
def do_POST(self):
print(self.pathobj)
self.send_response(405)
self.end_headers()
def run(server_class=HTTPServer, handler_class=Server, port=8080):
server_address = ("", port)
httpd = server_class(server_address, handler_class)
print("Starting httpd on port {}...".format(port))
httpd.serve_forever()
if __name__ == "__main__":
run()
I want to be able to access the ParseResult object returned by urllib.parse.urlparse in each class method without needing to rewrite self.pathobj = urllib.parse.urlparse(self.path) at the beginning of every class method.
The above code does not work -- when do_GET or do_POST are called it complains that 'Server' object has no attribute 'pathobj'.
The above docs for http.server.BaseHTTPRequestHandler say:
All of the relevant information is stored in instance variables of the handler. Subclasses should not need to override or extend the __init__() method.
But I don't see another way to do this. Is it possible?
The docs say
The handler will parse the request and the headers, then call a method specific to the request type.
As it turns out, http.server.BaseHTTPRequestHandler ultimately inherits from socketserver.BaseRequestHandler, and socketserver.BaseRequestHandler.__init__() (defined here) calls do_GET(). So the issue is that the instance variable is actually being set after do_GET() has already been called.
So in order to make this work, you'll need to move the self.pathobj line above the super() line and then rewrite it to do the parsing that BaseHTTPRequestHandler does to construct self.path.

CherryPy server name tag

When running a CherryPy app it will send server name tag something like CherryPy/version.
Is it possible to rename/overwrite that from the app without modifying CherryPy so it will show something else?
Maybe something like MyAppName/version (CherryPy/version)
This can now be set on a per application basis in the config file/dict
[/]
response.headers.server = "CherryPy Dev01"
Actually asking on IRC on their official channel fumanchu gived me a more clean way to do this (using latest svn):
import cherrypy
from cherrypy import _cpwsgi_server
class HelloWorld(object):
def index(self):
return "Hello World!"
index.exposed = True
serverTag = "MyApp/%s (CherryPy/%s)" % ("1.2.3", cherrypy.__version__)
_cpwsgi_server.CPWSGIServer.environ['SERVER_SOFTWARE'] = serverTag
cherrypy.config.update({'tools.response_headers.on': True,
'tools.response_headers.headers': [('Server', serverTag)]})
cherrypy.quickstart(HelloWorld())
This string appears to be being set in the CherrPy Response class:
def __init__(self):
self.status = None
self.header_list = None
self._body = []
self.time = time.time()
self.headers = http.HeaderMap()
# Since we know all our keys are titled strings, we can
# bypass HeaderMap.update and get a big speed boost.
dict.update(self.headers, {
"Content-Type": 'text/html',
"Server": "CherryPy/" + cherrypy.__version__,
"Date": http.HTTPDate(self.time),
})
So when you're creating your Response object, you can update the "Server" header to display your desired string. From the CherrPy Response Object documentation:
headers
A dictionary containing the headers of the response. You may set values in
this dict anytime before the finalize phase, after which CherryPy switches
to using header_list ...
EDIT: To avoid needing to make this change with every response object you create, one simple way to get around this is to wrap the Response object. For example, you can create your own Response object that inherits from CherryPy's Response and updates the headers key after initializing:
class MyResponse(Response):
def __init__(self):
Response.__init__(self)
dict.update(self.headers, {
"Server": "MyServer/1.0",
})
RespObject = MyResponse()
print RespObject.headers["Server"]
Then you can can call your object for uses where you need to create a Response object, and it will always have the Server header set to your desired string.

Resources