Cannot route non-ascii URLs Flask - python

I have a problem with the routing my URL adress to Flask, precisely with running it in web-browser. All I want is to transfer the sharp symbol "#" and some Russian words (as like "#привет" or "#ПомогитеМнеПожалуйста") together.
The screenshot of error: enter image description here
My programming code at the moment looks like this:
# -*- coding: utf-8 -*-
from flask import Flask, jsonify
app = Flask(__name__)
#app.route('/hashtags/<names>', methods=['GET'])
def get_hashtags(names):
return jsonify({'Segmentation Hashtags': names})
if __name__ == '__main__':
app.run(port=9876)
So, basically, <names> is a parameter from function get_hashtag that is used for transfering my future hashtag to the web-browser using jsonify. I need to find the way of transfering any hashtag I want with sharp symbol "#" plus Russian letters. As far as I know, there is an ASCII-coding methods (something like .**decode(utf-8)**), but I have no idea how to use it properly.
Thanks in advance!

The hashtags are causing the error. You can try to remove them on the client side, and just request this link instead:
/hashtags/привет
Hashtags in the url are often used to tell the browser which element on a page to jump to. For instance, on https://en.wikipedia.org/wiki/Stack_Overflow#Technology
the #Technology means jump to the technology section of the page.

try unidecode:
from unidecode import unidecode
#app.route('/hashtags/<names:string>', methods=['GET'])
def get_hashtags(names):
return jsonify({'Segmentation Hashtags': unidecode(names)})

Related

Flask URL encoding mis [duplicate]

My application frequently takes URL encoded strings as a URL parameter. Often these strings look like paths with a leading slash. IE /file/foo. In flask, I have an endpoint that takes a path parameter that I send a URL encoded path to. So I have something that looks like:
import flask
app = flask.Flask("Hello World")
#app.route("/blah/<path:argument>", methods=["GET"])
def foo(argument):
return "GOT: %s" % argument
if __name__ == "__main__":
app.run(debug=True)
This works great if I visit this URL:
http://localhost:5000/blah/cats%2F
returns:
GOT: cats/
But a leading slash with %2F fails with 404 in the case of GET and 405 in the case of POST. In other words, this 404s:
http://localhost:5000/blah/%2Fcats
In my research on this problem, I was lead to believe here that URL encoding was sufficient to sole the problem. However that doesn't appear to be the case.
This is because of how Werkzeug parses urls. It decodes the encoded slashes before parsing the route, so they still appear as leading slashes. There are bug reports about this:
https://github.com/mitsuhiko/flask/issues/900
https://github.com/mitsuhiko/werkzeug/pull/478
The second link provides a patch to perform this decoding after routing, but it is not merged.
It looks like the best solution at this point is to follow Martijn's answer here.
One way to get around this without defining your own PathConverter is having two route filters:
import flask
app = flask.Flask("Hello World")
#app.route("/blah/<path:argument>", methods=["GET"])
#app.route("/blah//<path:argument>", methods=["GET"])
def foo(argument):
return "GOT: %s" % argument
if __name__ == "__main__":
app.run(debug=True)
Hitting this with:
http://localhost:5000/blah/%2Fcats
Gives me:
GOT: cats
And with:
http://localhost:5000/blah//cats
Gives me:
GOT: cats
But a better (cleaner) solution is probably the one described in this SO answer: Flask route using path with leading slash

How can I connect to a website using twill inside of google app engine's python sandbox?

this allows me to connect to a website with python on my computer:
from twill.commands import go, show, showforms, formclear, fv, submit
from bs4 import BeautifulSoup as bs
go('http://www.pge.com')
showforms()
this gets me to hello world on google app engine, with the twill and beautiful soup imports working:
import webapp2
import sys
sys.path.insert(0, 'libs')
from twill.commands import go, show, showforms, formclear, fv, submit
from bs4 import BeautifulSoup as bs
class MainPage(webapp2.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.write('Hello, World! I love dog food.')
application = webapp2.WSGIApplication([
('/', MainPage),
], debug=True)
now after this i try to connect to a website using twill and fail:
where can i call go() to connect to a website?
if I add it before class MainPage(webapp2.RequestHandler): it hangs and I don't get to hello world.
If I add it inside the MainPage class on the first line as either getit = go('http://www.pge.com'), or just go('http://www.pge.com'), it also hangs and I don't get to hello world.
If I add it inside def: get(self):, I get:
Internal Server Error
The server has either erred or is incapable of performing the
requested operation.
and a bunch of stuff about twill and mechanize.py, followed by
File "..../twill/utils.py", line 275, in run_tidy
process = subprocess.Popen(_tidy_cmd, stdin=subprocess.PIPE,
AttributeError: 'module' object has no attribute 'Popen'
am i somehow missing some other dependencies, like mechanize.py? or is there something else i need to be doing?
This helped partially solve my issue, but other problems cropped up later, particularly in filling forms, submitting them, and migrating further in the website.
import webapp2
import sys
sys.path.insert(0, 'libs')
from twill.commands import go, show, showforms, formclear, fv, submit, config
from twill.browser import *
from bs4 import BeautifulSoup as bs
class MainPage(webapp2.RequestHandler):
config('use_tidy', '0')
def get(self):
go('http://www.pge.com')
self.response.headers['Content-Type'] = 'text/plain'
self.response.write('Hello, World! I love dog food.')
self.response.write(show())
tidy is disabled in this way (tidy does not play well with the google sandbox), and I am able to show() the webpage via self.response.write(show()).
As a side note: be careful about using TextEdit to edit .py files when working with google app engine. I was getting all sorts of weird non-ascii character errors. I added # -- coding: utf-8 -- to the first line of the python file, which sort-of helped, and switched to using pycharm's ide which really helped.
twill is giving me all sorts of issues inside google app engine's sandbox that i am not getting on my system. i can get finally the html for one webpage, but can't submit forms in the way i was doing so simply on my system. showforms() isn't even showing the forms, maybe because i disabled tidy and the html is not being parsed properly?
i think one way to move forward here is to get tidy to work inside twill. obviously roadblocks are being hit "under the hood", and they are hard for me to see.
it seems like twill is a high level abstraction and maybe is not a good idea right now for using on google app engine. next i will try to switch to mechanize.py, or look for another sandbox, maybe amazon?

python django soaplib response with classmodel issue

I run a soap server in django.
Is it possible to create a soap method that returns a soaplib classmodel instance without <{method name}Response><{method name}Result> tags?
For example, here is a part of my soap server code:
# -*- coding: cp1254 -*-
from soaplib.core.service import rpc, DefinitionBase, soap
from soaplib.core.model.primitive import String, Integer, Boolean
from soaplib.core.model.clazz import Array, ClassModel
from soaplib.core import Application
from soaplib.core.server.wsgi import Application as WSGIApplication
from soaplib.core.model.binary import Attachment
class documentResponse(ClassModel):
__namespace__ = ""
msg = String
hash = String
class MyService(DefinitionBase):
__service_interface__ = "MyService"
__port_types__ = ["MyServicePortType"]
#soap(String, Attachment, String ,_returns=documentResponse,_faults=(MyServiceFaultMessage,) , _port_type="MyServicePortType" )
def sendDocument(self, fileName, binaryData, hash ):
binaryData.file_name = fileName
binaryData.save_to_file()
resp = documentResponse()
resp.msg = "Saved"
resp.hash = hash
return resp
and it responses like that:
<senv:Body>
<tns:sendDocumentResponse>
<tns:sendDocumentResult>
<hash>14a95636ddcf022fa2593c69af1a02f6</hash>
<msg>Saved</msg>
</tns:sendDocumentResult>
</tns:sendDocumentResponse>
</senv:Body>
But i need a response like this:
<senv:Body>
<ns3:documentResponse>
<hash>A694EFB083E81568A66B96FC90EEBACE</hash>
<msg>Saved</msg>
</ns3:documentResponse>
</senv:Body>
What kind of configurations should i make in order to get that second response i mentioned above ?
Thanks in advance.
I haven't used Python's SoapLib yet, but had the same problem while using .NET soap libs. Just for reference, in .NET this is done using the following decorator:
[SoapDocumentMethod(ParameterStyle=SoapParameterStyle.Bare)]
I've looked in the soaplib source, but it seems it doesn't have a similar decorator. The closest thing I've found is the _style property. As seen from the code https://github.com/soaplib/soaplib/blob/master/src/soaplib/core/service.py#L124 - when using
#soap(..., _style='document')
it doesn't append the %sResult tag, but I haven't tested this. Just try it and see if this works in the way you want it.
If it doesn't work, but you still want to get this kind of response, look at Spyne:
http://spyne.io/docs/2.10/reference/decorator.html
It is a fork from soaplib(I think) and has the _soap_body_style='bare' decorator, which I believe is what you want.

Flask Redirect New Tab

Does anyone know if flask redirect is able to open a link / URL in a new tab?
#app.route('/test')
def my_page():
return redirect('http://mylink.com', 301)
I would like if the mylink website opened in a new tab, any insights?
As far as I know that would not be a flask issue. You have to open a new tab within your html code or with Javascript.
example:
Link
The server has no power over what the browser does in this case.
You could also use Python's webbrowser module to open a page, if you'd like to avoid getting into the HTML
import webbrowser
#app.route('/test')
def my_page():
return webbrowser.open_new_tab('http://mylink.com')
If you're dealing with a form you can set target="_blank"
A slight adjustment to #garettmd that fixes #John Jiang's issue:
import webbrowser
from flask import Flask, redirect, url_for
#app.route("/test/")
def test():
webbrowser.open("https://google.com")
return redirect(url_for("index"))
This way we get to return a redirect (which we should probably do anyway) and we also get our new tab without "The view function did not return a valid response" error.

How to display a page in my browser with python code that is run locally on my computer with "GAE" SDK?

When I run this code on my computer with the help of "Google App Engine SDK", it displays (in my browser) the HTML code of the Google home page:
from google.appengine.api import urlfetch
url = "http://www.google.com/"
result = urlfetch.fetch(url)
print result.content
How can I make it display the page itself? I mean I want to see that page in my browser the way it would normally be seen by any user of the internet.
Update 1:
I see I have received a few questions that look a bit complicated to me, although I definitely remember I was able to do it, and it was very simple, except i don't remember what exactly i changed then in this code.
Perhaps, I didn't give You all enough details on how I run this code and where I found it. So, let me tell You what I did. I only installed Python 2.5 on my computer and then downloaded "Google App Engine SDK" and installed it, too. Following the instructions on "GAE" page (http://code.google.com/appengine/docs/python/gettingstarted/helloworld.html) I created a directory and named it “My_test”, then I created a “my_test.py” in it containing that small piece of the code that I mentioned in my question.
Then, continuing to follow on the said instructions, I created an “app.yaml” file in it, in which my “my_test.py” file was mentioned. After that in “Google App Engine Launcher” I found “My_test” directory and clicked on Run button, and then on Browse. Then, having visited this URL http://localhost:8080/ in my web browser, I saw the results.
I definitely remember I was able to display any page in my browser in this way, and it was very simple, except I don’t remember what exactly I changed in the code (it was a slight change). Now, all I can see is a raw HTML code of a page, but not a page itself.
Update 2:
(this update is my response to wescpy)
Hello, wescpy!!! I've tried Your updated code and something didn't work well there. Perhaps, it's because I am not using a certain framework that I am supposed to use for this code. Please, take a look at this screen shot (I guess You'll need to right-click this image to see it in better resolution):
(source: narod.ru)
Is not that easy, you have to parse content and adjust relative to absolute paths for images and javascripts.
Anyway, give it a try adding the correct Content-Type:
from google.appengine.api import urlfetch
url = "http://www.google.com/"
result = urlfetch.fetch(url)
print 'Content-Type: text/html'
print ''
print result.content
a more complete example would look something like this:
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.api import urlfetch
class MainHandler(webapp.RequestHandler):
def get(self):
url = "http://www.google.com/"
result = urlfetch.fetch(url)
self.response.out.write(result.content)
application = webapp.WSGIApplication([
('/', MainHandler),
], debug=True)
def main():
run_wsgi_app(application)
if __name__ == '__main__':
main()
but as others' have said, it's not that easy to do because you're not in the server's domain, meaning the pages will likely not look correct due to missing static content (JS, CSS, and/or images)... unless full pathnames are used or everything that's needed is embedded into the page itself.
UPDATE 1:
as mentioned before, you cannot just download the HTML source and expect things to render correctly because you don't necessarily have access to the static data. if you really want to render it as it was meant to be seen, you have to just redirect... here's the modified piece of code:
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.api import urlfetch
class MainHandler(webapp.RequestHandler):
def get(self):
url = "http://www.google.com/"
self.redirect(url)
application = webapp.WSGIApplication([
('/', MainHandler),
], debug=True)
def main():
run_wsgi_app(application)
if __name__ == '__main__':
main()
UPDATE 2:
sorry! it was a cut-n-paste error. now try it.
special characters such as <> etc are likely encoded, you'd have to decode them again for the browser to interpet it as code.

Categories