I am working on a CEFPython application that requires me to include some external files like JS or CSS libraries.However any external path (Referring to external libraries present in the same folder and the online resource URL both) mentioned in the HTML file seems to be unacceptable, I am sure am missing a flag to enable external files liking but am unable to figure out which. below is the code to my main function:
def main():
sys.excepthook = cef.ExceptHook # To shutdown all CEF processes on error
# To change user agent use either "product_version"
# or "user_agent" options. Explained in Tutorial in
# "Change user agent string" section.
settings = {
# "web_security_disabled": True,
# "user_agent": "MyAgent/20.00 MyProduct/10.00",
}
cef.Initialize(settings=settings)
browser = cef.CreateBrowserSync(url=html_to_data_uri(HTML_code),
window_title="Demo Program")
set_javascript_bindings(browser)
cef.MessageLoop()
cef.Shutdown()
the "web_security_disabled" setting must be passed in the browser creation, not in the cef initialization.
Example :
settings = {
"web_security_disabled": True,
}
def launcher(url):
sys.excepthook = cef.ExceptHook # To shutdown all CEF processes on error
cef.Initialize()
cef.CreateBrowserSync(url=url, window_title="my title", settings=settings)
cef.MessageLoop()
cef.Shutdown()
You cannot mix scripts from different origins, see:
https://en.wikipedia.org/wiki/Same-origin_policy
There is --disable-web-security switch that you can try.
If that doesn't work then use "http" url instead of data uri. You can run an internal web server using Python. You can also implement ResourceHandler and serve http content without the need to run a web server, however implementing ResourceHandler correctly is a complex task.
Related
I am trying to create a trivial python script that allows me to bulk add a list of youtube videos to a playlist of mine.
The problem I am having is getting this script to get authenticated to the google api with my apps credentials.
I am basically just using the sample authentication script at https://developers.google.com/google-apps/calendar/quickstart/python
and this stackoverflow question (Adding youtube video to playlist using Python)
The main stopping point is that I keep getting an Error: redirect_uri_mismatch. Since I am calling the script from the commandline on my laptop, the error is saying: The redirect URI in the request: http://localhost:8080/ did not match a registered redirect URI.
I have set http://localhost:8080 as the JavaScript origins and http://localhost:8080/oauth2callback as the Redirect URIs
And i am using the following (as run from the python shell):
from oauth2client.client import flow_from_clientsecrets
from oauth2client.file import Storage
from oauth2client import tools
from oauth2client.tools import argparser, run_flow
import argparse, sys, os
flow = flow_from_clientsecrets('path to my CLIENT_SECRETS.json file', scope='https://www.googleapis.com/auth/youtube')
store = Storage('config/%s-oauth2.json' % sys.argv[0])
parser = argparse.ArgumentParser(parents=[tools.argparser])
flags = parser.parse_args()
credentials = run_flow(flow, store, flags)
then the terminal opens my browser and in the browser I get the 400 error. The following gets printed to the terminal:
Your browser has been opened to visit:
https://accounts.google.com/o/oauth2/auth?scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyoutube&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2F&response_type=code&client_id=my-CLIENT-ID&access_type=offline
If your browser is on a different machine then exit and re-run this
application with the command-line parameter
--noauth_local_webserver
I am not sure what I am really supposed to be putting as the redirect URIs and javascript origins, but I don't intend to run this anywhere else other than as a python script from the terminal of my laptop. The documentation provides https://example.com/ and https://example.com/oauth2callback as pre populated values, but clearly that's not where I am running this "app" from and I know that's just placeholder stuff.
UPDATE: not sure why, but i realize that the url the app is sending me to has the redirect_uri parameter set to just http://localhost:8080/, if i add oauth2callback to the uri than i get sent to the screen where it asks me to accept management of the youtube account. so that's odd.
UPDATE 2: and if I change my redirect uris to just http://localhost:8080/ via the developer console, i can get my credentials, but I am sure this is not the best way to be going about this.
If you are just running this through you terminal than you can use the native host by creating a client ID as an installed app and then selecting other. If you are trying to do this using the web app client ID and only want it to be local then you would use these:
JavaScript origins: http://localhost:your_port_here/
Redirect URIs: http://localhost:your_port_here/url_path
where url_path is the place you want google to send you after authentication.
Edit: the tutorial code only works if you are using a native app. If you are indeed planning to create a web app there are separate instructions.
The redirect_uri parameter set to just http://localhost:8080/ is by design. When you call tools.run_flow() it is spinning up a server of it's own behind the scenes and initiating the oauth flow. It is then expecting the redirect_uri to redirect back to the server it spun up (which is listening on port 8080) so that it can use the access_token it receives to create the credentials and put them in storage.
I am currently working on an application that requires math expressions to be rendered (from latex) and needs to have some sort of native gui (even if it just uses gtk, then renders html in webkit).
I did some research and decided an easy way to do this would be to use webkit to load a web page and use a JavaScript library like MathJax to render the math.
Some other reasons why I chosen to do it this way over other solutions are I have had a fair amount of experience developing web apps in python (although a while ago), lack of experience with native guis and the portability it would provide.
For a web app framework I have chosen to use flask as it is one I am most familiar with.
The problem is this application needs to have it's own native GUI through preferably gtk (even if just renders html with webkit) and also preferably shouldn't have a http server that is attached to some socket.
So my question is, instead of running flask's server is there any way to do something like this:
import gtk
import webkit
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello_world():
return "<h1>Hello World!</h1>"
if __name__ == '__main__':
window = gtk.Window()
webview = webkit.WebView()
webview.load_string(
app.load_from_uri('/'),
"text/html",
"utf-8",
'/'
)
window.add(webview)
window.show_all()
Where app.load_from_uri('/') is just used as an example of a way to load the webpage for a given uri of a Flask app. But as this is just an example, how could app.load_from_uri('/') be done in real code?
Also is there anyway to override when the user clicks a link so it does something like this:
def link_clicked(uri):
webview.load_string(
app.load_from_uri(uri),
"text/html",
"utf-8",
uri
)
Thanks any help is greatly appreciated!
I've ended up finding a solution to this myself (but open to better ones).
The first thing, loading a page, was pretty easy. Flask provides a way to test apps which mainly just sets up all the things for WSGI to be able to process a request. This is just what I needed so I used this like so:
from flask import Flask
class WebViewFlask(Flask):
"""
Adds the ability to load a uri without the
need of a HTTP server.
"""
def load_from_uri(self, uri):
"""
Loads a uri without a running HTTP server.
"""
with self.test_client() as c:
response = c.get(uri)
return response.data, response.mimetype
The second part, overriding "when the user clicks a link", is a bit more trickier.
import os
import webkit
class FlaskAppView(webkit.WebView):
"""
Loads pages for flask apps into a WebView.
"""
def __init__(self, flask_app, *args, **kwargs):
# Protocol for flask app, by default file:// is used
# so a protocol is defined here to prevent that.
self.PROTOCOL = 'flask://'
super(webkit.WebView, self).__init__(*args, **kwargs)
self._flask_app = flask_app
# Register new navigation handler.
self.connect(
"navigation-policy-decision-requested",
self._nav_request
)
# For navigation handler.
self.prev_uri = None
# Redefine open like this as when using super
# an error like this occurs:
# AttributeError: 'super' object has no attribute 'open'
self._open = self.open
self.open = self.open_
def _nav_request(self, view, frame, net_req, nav_act, pol_dec):
"""
WebView navigation handler for Flask apps.
"""
# Get the uri
uri = net_req.get_uri()
# In order for flask apps to use relative links
# the protocol is removed and it is made into an absolute
# path.
if uri.startswith(self.PROTOCOL):
# In this case it is not relative but
# it needs to have it's protocol removed
uri = uri[len(self.PROTOCOL):]
elif not self.prev_uri.endswith(uri):
# It is relative and self.prev_uri needs to
# be appended.
uri = os.path.normpath(os.path.join(self.prev_uri, uri))
# This is used to prevent an infinite recursive loop due
# to view.load_string running this function with the same
# input.
if uri == self.prev_uri:
return False
self.prev_uri = uri
# Create response from Flask app.
response = app.load_from_uri(uri) + ('utf-8', uri)
# Load response.
view.load_string(*response)
# Return False to prevent additional
# handlers from running.
return False
def open_(self, uri):
"""
Prepends protocol to uri for webkit.WebView.open.
"""
self._open(self.PROTOCOL + uri)
Basically a new navigation event handler is registered with some code to allow for successful recursion and support for relative paths.
Anyway, with that code above by just replacing Flask with WebViewFlask and WebView with FlaskAppView everything pretty much just works.
And the result:
Which is a flask app being loaded in a webkit.WebView without any sort of server. The best thing about it is by just switching app back to an instance of Flask instead of WebViewFlask It's a plain webapp again.
I used to create web app in the same computer, but if the server and the client is not in the same computer, how can we access to the web page ?
I mean, for example I have an html form and a button "ok" :
If the server and the client are in the same computer, in action = " " we put localhost/file.py , but if the server and the client are not in the same computer how to do this ? Because the client can't to have localhost in his webbrower (url).
The "action" part of a form is an url, and If you don't specify the scheme://host:port part of the URL, the client will resolve it has the current page one. IOW: just put the path part of your script's URL and you'll be fine. FWIW hardcoding the scheme://host:port of your URLs is an antipattern, as you just found out.
Your script is supposed to be run as a CGI script by a web-server, which sets environment variables like REMOTE_ADDR, REQUEST_METHOD ...
You are running the script by yourself, and this environment variable are not available.
That's why you get the KeyError.
I am running a cherrypy application using python 2.7 on windows (and using the cherrypy version from pipi). The application is running in the intranet and basically structured like the code below.
To monitor this application with newrelic I tried to wrap it like explained in the newrelic documentation. But it did not appear in the newrelic backend when started that way, although the cherrypy application worked.
I also tried the manual method, inserting the newrelic agent just one line after def main():. This made the application appear in the newrelich backend but it monitored nothing. All diagrams empty.
I already searched the web for hours and asked some colleages without any progress.
From the newrelic documentation I suspect I have to choose a different structure or technology in my cherrypy application. They do not use quickstart. So my question is how do I convert my application that it fits the newrelic way of monitoring applications.
This is more or less the main file of the application:
# -*- coding: utf-8 -*-
def main():
import cherrypy
from auth import AuthController
from my_routes import RouteOne, RouteTwo
dispatcher = cherrypy.dispatch.RoutesDispatcher()
dispatcher.explicit = False
dc = dispatcher.connect
dc(u'd_home', u'/', RouteOne().index_home)
dc(u'd_content', u'/content/', RouteOne().index_content)
dc(u'd_search', u'/search/:find', RouteRoot().index_search)
conf = {
'/' : {
u'request.dispatch' : dispatcher,
u'tools.staticdir.root' : 'c:/app/src',
u'tools.sessions.on' : True,
u'tools.auth.on': True,
u'tools.sessions.storage_type' : "file",
u'tools.sessions.storage_path' : 'c:/app/sessions',
u'tools.sessions.timeout' : 60,
u'log.screen' : False,
u'log.error_file' : 'c:/app/log/error.txt',
u'log.access_file' : 'c:/app/log/access.txt',
},
u'/app/public' : {
u'tools.staticdir.debug' : True,
u'tools.staticdir.on' : True,
u'tools.staticdir.dir' : u"public",
},
}
# ... some additional initialisation left out ...
cherrypy.tree.mount(None, u"/", config=conf)
cherrypy.config.update({
'server.socket_host': myhost.test.com,
'server.socket_port': 8080,})
from auth import check_auth
cherrypy.tools.auth = cherrypy.Tool('before_handler', check_auth)
cherrypy.quickstart(None, config=conf)
if __name__ == "__main__":
main()
Please help me to construct in a newrelic compatible way, like wsgi, the different parts, like the config, the dispatch, the auth and the routes, so that I can monitor it.
I am ready to do things different where necessary, I know with python almost everything is possible.
So if this needs to be a wsgi application how do I change it? I would prefer this over other methods (like paste).
I hope this can also help many other people, because I was not able to find anything specific about this and I can imagine that many cherrypy applications out there are structured similar. I spent a lot of time in the cherrypy docs but somehow was not able to put the different parts together.
The newrelic-admin wrapper script can be used for a CherryPy WSGI application which uses cherrypy.quickstart(). Once you have generated your agent configuration file, all you need to do is run:
NEW_RELIC_CONFIG_FILE=newrelic.ini newrelic-admin run-python app.py
where app.py is your script.
A simple example of an app.py script which works, including a route dispatcher is:
import cherrypy
class EndPoint(object):
def index(self):
return 'INDEX RESPONSE'
dispatcher = cherrypy.dispatch.RoutesDispatcher()
dispatcher.connect(action='index', name='endpoint', route='/endpoint',
controller=EndPoint())
conf = { '/': { 'request.dispatch': dispatcher } }
cherrypy.quickstart(None, config=conf)
You might verify that things are working for your specific environment and package versions with that example.
My question is about how to serve multiple urls.py (like urls1.py, urls2.py and so on) files in a single Django project.
I am using Win7 x64, django 1.4.1, python 2.7.3 and as a server django dev-server tool.
I have decided to use a method which i found by google from
http://effbot.org/zone/django-multihost.htm
I have created a multihost.py file and put in to the django middleware folder:
C:\python27\Lib\site-packages\django\middleware\multihost.py
With the following code:
from django.conf import settings
from django.utils.cache import patch_vary_headers
class MultiHostMiddleware:
def process_request(self, request):
try:
host = request.META["HTTP_HOST"]
if host[-3:] == ":80":
host = host[:-3] # ignore default port number, if present
request.urlconf = settings.HOST_MIDDLEWARE_URLCONF_MAP[host]
except KeyError:
pass # use default urlconf (settings.ROOT_URLCONF)
def process_response(self, request, response):
if getattr(request, "urlconf", None):
patch_vary_headers(response, ('Host',))
return response
Also in my project setting.py file i have added a mapping dictionary like the link above shows:
# File: settings.py
HOST_MIDDLEWARE_URLCONF_MAP = {
"mysite1.com": "urls1",
#"mysite2.com": "urls2"
}
I did not yet implemented the error handling like described by the link above.
My hosts file includes the follwoing:
127.0.0.1 mysite1.com
Project structure is the following:
effbot django project folder:
+ effbot
--- settings.py
--- view.py
--- wsgi.py
--- urls.py
--- urls1.py
+ objex
--- models.py
--- views.py
+ static
--- css
--- images
There is no templates folder, because i dont serve html items from files, they are coming from databsse (i doubt that my problem is in this).
Now the problem is: when i go for the adress
mysite1.com
in my browser with django dev-server launched i get code 301 from the server. And browser shows "cannot display page" message.
Could you please explain me how to use mentioned method? I'm new to django and haven't done any real projects yet. Just have read the docs and launched a couple of sites at home to learn how it works.
I expect that urlconfs will be called in dependance from incoming
request.META["HTTP_HOST"]
The target is to serve different urlconfs for mysite1.com and mysite2.com
in a single django project.
I think this should to work some how.
Thank you for any feedback.
EDIT:
After some research attempts i found that i plugged my multyhost.py incorrectly in settings.
Fixed now. But the same result still.
Also i found out that my django dev-server tool is not reflecting anyhow that it handles any requests from the browser (IE9) except when i do "http://127.0.0.1".
May be i have to try some production server for my task, like nginx?
Your ROOT_URLCONF should be effbot.urls without .pyas you can see in the example in the documentation.
Also, HOST_MIDDLEWARE_URLCONF_MAP should reflect the ROOT_URLCONF so add `effbot. like this:
HOST_MIDDLEWARE_URLCONF_MAP = {
"mysite1.com": "effbot.urls1",
#"mysite2.com": "effbot.urls2"
}
One more thing, please try with another browser (Chrome, Firefox), sometimes I had problems accessing dev server with IE.