Get Pyramid View callable by it's path (request context) - python

I am making an app that would translate websocket messages to AJAX requests to the server. Mainly the decision is based on the fact that Pyramid already has a good URL dispatch system and it would be stupid not to use it.
The question is if there is an easy way to dispatch a URL in Pyramid (possibly an instanced Request object) to it's according view callable and get the view callable? Or at least get the output of the view callable related to the request?
I have tried the script from "prequest.py" which basically emulates a whole HTTP client and gives you the response (I have still not managed to get it work, but a look through the sources makes sense anyway) and I wouldn't like to do it that way.

You can reuse the code from the pview command to turn a path into a view reference:
from pyramid.scripts.pviews import PViewsCommand
pvcomm = PViewsCommand([])
view = pvcomm._find_view(path, request.registry)
The actual code to do this is a little involved, but the PViewsCommand does it all for us already.

I have managed to do it using Router.invoke_subrequest in the latest version of Pyramid (1.4a1).
This enables all the features related to routing. URL dispatch, parameter passing, tweens.
You can read about it here: http://docs.pylonsproject.org/projects/pyramid/en/latest/api/request.html#pyramid.request.Request.invoke_subrequest

Related

Authlib 0.6+ does not work with Auth0 impersonation and Flask

Auth0 impersonation directly calls the on success authentication callback URL skipping the initial step of authentication. This causes an issue because flask/client/OAuth.authorize_access_token(), which is called as part of the callback processing, requires the presence of the session variable _auth0_callback_ but this variable is not set because the only place it is set, flask/client/OAuth.authorize_redirect(), is not called in this situation.
We've added a hack to set the _auth0_callback_ session variable if it doesn't exist just before the call to flask/client/OAuth.authorize_access_token() but this doesn't seem right and I'm just wondering if we're doing something wrong.
We've also experienced a similar issue with the _auth0_state_ session variable but this might have been fixed in v0.7 that I'm testing now. We currently are using Authlib v0.6 in production.
Have raised this issue with Auth0 but have not had any response.
Any help appreciated, thx
UPDATE...
Looking deeper into Authlib it looks like that for the flask/client/OAuth.authorize_access_token() call the callback URL is not required in OAuth2Session.fetch_access_token() to fetch the token if the token is included in the authorisation response and it kind of makes sense that the access token is included in the authorisation response in the case of the impersonation - see OAuth2Session.fetch_access_token()#152.
So maybe that authorisation response access token from Auth0 impersonation doesn't exist or is not being properly passed through...
According to my acknowledge, Auth0 accepts a redirect_uri parameter. Check this example: https://github.com/lepture/auth0-python-web-app/blob/patch-1/01-Login/server.py
The Flask integration is a wrapper on OAuth2Session which provides authorize_redirect and authorize_access_token methods to handle everything automatically for you. If you find the high level integration can't meet your need, you can always use the methods of OAuthClient.

How can I understand what is the method performed when an API implemented in Django is called?

I am absolutly not a Python developer (I am a Java dev) but I have to do some minor change on a Python projcet based on Django framework and I am finding some difficulties trying to understand how it works.
Basically I have to do a change into an API that have the following endpoint:
https://MY-PROJECT-NAME-backend.herokuapp.com/api/v1/accounts:accounts/
(I retrireved it analyzing te call made by a web application using the Chrome DevTool Network tab)
Coming from Java Spring framework I am pretty sure that also DJango should map this endpoint to a method that implement my API logic, is it?
How can I retrieve this method? (I need to understand what method is performed when this call happens).
Another doubt is: I think that this is the endpoint URL:
https://MY-PROJECT-NAME-backend.herokuapp.com/api/v1/accounts
but what is this :accounts/ appended at the end of the URL?
Thank you
EDIT-1: Into the urls.py file I only have these line:
from django.conf.urls import url
from ressource.views import *
urlpatterns = [
url(r'^connexion/', connexion,name="connexion"),
]
url() need at least two argument, a regex pattern (r'^connexion/') and a view. The view is the method called. In this case it's connection.
It could be a GET method of lists of accounts or both GET and POST method together or even just a POST method depending on how the views was configured

what does endpoint mean in flask-restful

I defined some resource called WorkerAPI using flask-restful and the plan is to process POST request from /api/workers/new and GET request from /api/workers/. When using the following code
api.add_resource(WorkerAPI, '/api/workers/new')
api.add_resource(WorkerAPI, '/api/workers/')
I get errors:
AssertionError: View function mapping is overwriting an existing endpoint function: workerapi
Then I tried to use the following, which seems to work, although I don't know why it works.
api.add_resource(WorkerAPI, '/api/workers/new', endpoint='/workers/new')
api.add_resource(WorkerAPI, '/api/workers/', endpoint='/workers/')
It looks like redundant information to me though. It seems the site works as long as the two endpoints are defined as different strings. What does endpoint mean here?
The thing is that the add_resource function registers the routes with the framework using the given endpoint. If an endpoint isn't given then Flask-RESTful generates one for you from the class name.
Your case is WorkerAPI, the endpoint will beworkerapi for these two methods, better make endpoint explicit and avoid to have conflicting endpoint names registered.
For what's endpoint, you can refer to this answer for more details.
'endpoint' is actually an identifier that is used in determining what logical unit of your code should handle a specific request.
So, an URL path is mapped to an endpoint and then an endpoint is mapped to a view function in your flask app.
In your case, when you are explicitly defining your endpoints for your resources, it helps the flask app internally to map it efficiently to a list of routes, while when your are not explicitly defining it, flask takes some default value, as explained by #Tiny.D, in the above answer.

Is there a better way to access my public api?

I am new to Flask.
I have a public api, call it api.example.com.
#app.route('/api')
def api():
name = request.args.get('name')
...
return jsonify({'address':'100 Main'})
I am building an app on top of my public api (call it www.coolapp.com), so in another app I have:
#app.route('/make_request')
def index():
params = {'name':'Fred'}
r = requests.get('http://api.example.com', params=params)
return render_template('really_cool.jinja2',address=r.text)
Both api.example.com and www.coolapp.com are hosted on the same server. It seems inefficient the way I have it (hitting the http server when I could access the api directly). Is there a more efficient way for coolapp to access the api and still be able to pass in the params that api needs?
Ultimately, with an API powered system, it's best to hit the API because:
It's user testing the API (even though you're the user, it's what others still access);
You can then scale easily - put a pool of API boxes behind a load balancer if you get big.
However, if you're developing on the same box you could make a virtual server that listens on localhost on a random port (1982) and then forwards all traffic to your api code.
To make this easier I'd abstract the API_URL into a setting in your settings.py (or whatever you are loading in to Flask) and use:
r = requests.get(app.config['API_URL'], params=params)
This will allow you to make a single change if you find using this localhost method isn't for you or you have to move off one box.
Edit
Looking at your comments you are hoping to hit the Python function directly. I don't recommend doing this (for the reasons above - using the API itself is better). I can also see an issue if you did want to do this.
First of all we have to make sure the api package is in your PYTHONPATH. Easy to do, especially if you're using virtualenvs.
We from api import views and replace our code to have r = views.api() so that it calls our api() function.
Our api() function will fail for a couple of reasons:
It uses the flask.request to extract the GET arg 'name'. Because we haven't made a request with the flask WSGI we will not have a request to use.
Even if we did manage to pass the request from the front end through to the API the second problem we have is using the jsonify({'address':'100 Main'}). This returns a Response object with an application type set for JSON (not just the JSON itself).
You would have to completely rewrite your function to take into account the Response object and handle it correctly. A real pain if you do decide to go back to an API system again...
Depending on how you structure your code, your database access, and your functions, you can simply turn the other app into package, import the relevant modules and call the functions directly.
You can find more information on modules and packages here.
Please note that, as Ewan mentioned, there's some advantages to using the API. I would advise you to use requests until you actually need faster requests (this is probably premature optimization).
Another idea that might be worth considering, depending on your particular code, is creating a library that is used by both applications.

Run code before url mapping on google app engine

I'd like to check the datastore first, to see if there is any data, and if not, then redirect to another page (most likely /admin). However, I don't want to rewrite the url mapping framework that is already there.
Is there some way to set a handler that will process all requests before they are mapped?
I'm using google app engine with Python 2.7 and webapp2.
Yes, you can override dispatch() with a custom class. In the example shown in the link, the new class name is MyHandler. This means that all of your request classes need to be derived from MyHandler instead of webapp2.RequestHandler. Since this is how you would implement Sessions, you can put your code in dispatch() before it calls webapp2.RequestHandler.dispatch(self). In other words, you probably want to replace webapp2.RequestHandler anyway.

Categories

Resources