I created simplest html page
<html lang="en">
<head>
<meta charset="utf-8">
<title>App</title>
</head>
<body>
Hello, world.
</body>
</html>
and run python -m SimpleHTTPServe 8000 in the page's folder.
Problem: When I go to localhost:8000 I see the text of my page. Means the http server instead of interpreting it as html page wraps each string of my page into <p> tag.
If I open sources I get:
<html>
........
<body>
<p class="p1"><span class="s1"><</span><b>html</b><span class="s2"> </span><span class="s3">lang</span><span class="s1">=</span><span class="s4">"en"</span><span class="s1">></span></p>
<p class="p2"> <span class="s1"><</span><span class="s5"><b>head</b></span><span class="s1">></span></p>
<p class="p2"> <span class="s1"><</span><span class="s5"><b>meta</b></span> <span class="s3">charset</span><span class="s1">=</span><span class="s4">"utf-8"</span><span class="s1">></span></p>
<p class="p3"><span class="s2"> </span><<span class="s5"><b>title</b></span>>Backbone.js Todo App</<span class="s5"><b>title</b></span>></p>
<p class="p2"> <span class="s1"></</span><span class="s5"><b>head</b></span><span class="s1">></span></p>
<p class="p2"> <span class="s1"><</span><span class="s5"><b>body</b></span><span class="s1">></span></p>
<p class="p3"><span class="s2"> </span>Hello, world.</p>
<p class="p3"><span class="Apple-converted-space"> </span></<span class="s5"><b>body</b></span>></p>
<p class="p1"><span class="s1"></</span><b>html</b><span class="s1">></span></p>
</body>
</html>
If you're editing your page in TextEdit, make sure you open the Format menu and choose "Make Plain Text."
If you saved as HTML without this option, TextEdit would have added those tags to keep your text file's formatting.
I just tried on my mac and I don't observe similar behaviour: I start server slightly differently:
python -mSimpleHTTPServer 8000 : no space between m and SimpleHTTPServer (checked with space, same behaviour)
I have 2 files : a.out and a.html with same content : it looks like a.out gets downloaded while a.html gets displayed (with chrome)
My guess is that your file has no extension .html and that your browser itself is adding the tags to display it.
You can try downloading the file with curl to make sure : curl http://localhost:8000/a.out from a terminal
Note : I'm running MacOS 10.9.4 on a McBook air with python 2.7.5
If your page show up as text just as you are describing then that most likely means that the server does not use the correct content-type in its HTTP headers. SimpleHTTPServer uses the module mimetypes to determine what content-type to use for most file types.
You can check it yourself:
>>> import mimetypes
>>> mimetypes.init()
>>> print mimetypes.types_map
...
or more specifically
>>> print mimetypes.types_map['.html']
text/html
Make sure your file extension matches with what mimetypes expects.
Related
I'm currently trying to create a simple login in page to my actual local webpage that I'm running with on a virtual machine with Ubuntu.
I created the LoginPage.html at the location /var/www/html.
The HTML file then calls the login.cgi file in the /usr/lib/cgi-bin/login.cgi.
I get an Internal Server Error. The logs basically only shows this:
"POST /cgi-bin/login.cgi HTTP/1.1" 500 799
"http://localhost/LoginPage.html" "Mozialla/5.0 (X11; Ubtuntu; Linux
x86_64; rv:84.0) Geck/201000101 Firefox/84.0
The HTML file seems to be working as intended, but when I press login and get redirected to the CGI file, I get the error on the CGI file. I have tried to remove everything the in the CGI file to leave only a couple of lines but still get the error.
My other project-files in the cgi-bin folder still work without an error.
<HTML>
<HEAD><TITLE>Login Page</TITLE></HEAD>
<BODY>
<CENTER>
<FORM method="POST" action="/cgi-bin/login.cgi">
<paragraph> Enter your login name: <input type="text" name="login">
<paragraph> Enter your password: <input type=password name="password">
<paragraph> <input type="submit" value="Connect">
</FORM>
</CENTER>
<HR>
</form>
</BODY>
</HTML>
#!/usr/bin/python3
import sys
import cgi
import os
import cgitb
sys.path.insert(0,'/usr/lib/project_name')
def header():
#print "Content-type: text/html\n"
print("<HEAD>")
print("<TITLE> title </TITLE>")
print("</HEAD>")
def Log():
print("<!DOCTYPE html>")
print("<HTML>")
print("<html lang=\"en\" xmlns=\"http://www.w3.org/1999/xhtml\">")
print(" <meta charset=\"utf-8\" />")
header()
print("BODY")
form = cgi.FieldStorage()
login = "login"
password = "test123"
if not (form):
header("Login Response")
print("<BODY>")
elsif (form.has_key("login") and form["login"].value == login and form.has_key("password") and form["password"].value == password):
header("Connected ...")
print("<BODY>")
print("<center><hr><H3>Welcome back,\" , form[\"login\"].value, \".</H3><hr></center>")
print("r\"\"\"<form><input type=\"hidden\" name=\"session\" value=\"%s\"></form>\"\"\" % (form[\"login\"].value)")
print("<H3>Click here to start browsing</H3>")
else:
header("No success!")
print("<BODY>")
print("<H3>Please go back and enter a valid login.</H3>")
def footer():
print("</BODY>")
print("</HTML>")
print("Content-type:text/html\r\n\r\n")
cgitb.enable()
Log()
footer()
Edit:
Here is the content of error.log after resolving the Internal Server Error:
[Tue Feb 02 08:40:41.199152 2021] [cgi:error] [pid 10292:tid
140490049578752] [client 127.0.0.1:38888] AH01215: (2)No such file or
directory: exec of '/usr/lib/cgi-bin/login.cgi' failed:
/usr/lib/cgi-bin/login.cgi, referer: http://localhost/LoginPage.html
[Tue Feb 02 08:40:41.199411 2021] [cgi:error] [pid 10292:tid
140490049578752] [client 127.0.0.1:38888] End of script output before
headers: login.cgi, referer: http://localhost/LoginPage.html
Correcting the setup:
No such file or directory: exec of '/usr/lib/cgi-bin/login.cgi' failed: /usr/lib/cgi-bin/login.cgi, referer: http://localhost/LoginPage.html
Make sure the CGI script and its parent directory have the right permissions:
chmod 755 /usr/lib/cgi-bin/ /usr/lib/cgi-bin/login.cgi
Also, it appears the CGI script may have windows line endings, so make sure you remove those as well, e.g. by running dos2unix login.cgi (see this post for more details).
Resolving the Internal Server Error:
First, make at least the following changes to correct your syntax (which is what's causing the Internal Server Error):
elsif should be elif
Your header function should take in an argument, i.e. def header(title)
Where you have form.has_key, change it to use in since has_key is now deprecated, e.g. "password" in form instead of form.has_key("password")
The corrected condition would look like this:
elif "login" in form and form["login"].value == login and "password" in form and form["password"].value == password:
As an aside, stick to HTML5, which is supported by all the latest browsers, and the center tag is now deprecated (its gone the way of the marquee tag). Use CSS instead.
Also, as a complete side note, these days, its uncommon to see ALL CAPS used for HTML tags. You have used that style in some places, but I suggest dropping it in favor of lowercase tag names.
Simplfying the HTML generation:
In addition to the above, I recommend using f-strings for string formatting and also multi-line strings to simplify the logic a bit.
Below are some examples of how you can enhance your code.
Your header function may look like this using f-strings and multi-line strings as suggested. The title argument is optional.
def header(title=""):
print(f"""
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title> {title} </title>
</head>
<body>
""")
Your footer function could look like this:
def footer():
print("""
</body>
</html>
""")
Finally, your HTML form could look like this, using text-align: center; for the centering:
print(f"""
<hr>
<h3 style="text-align: center;">Welcome back { form["login"].value }</h3>
<hr>
<form>
<input type="hidden" name="session" value="{ form["login"].value }">
</form>
<h3>
Click here to start browsing
</h3>
""")
Beautifying the HTML:
To beautify the HTML further, you can import textwrap and then use textwrap.dedent() to remove the common leading spaces from the HTML (due to the indentation in Python), e.g.
print(textwrap.dedent(f"""
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title> {title} </title>
</head>
<body>
"""))
This gives two advantages:
It removes the unnecessary leading spaces before sending it over the network -- so you send less data, saving bandwidth
The HTML source is prettier when you inspect it using a client browser -- useful for debugging
Alternatively, use HTML templating:
A further enhancement is to make use of a HTML templating framework, such as Jinja2. This will allow you to store the HTML into files and then render the HTML files by passing variables.
Then, your Python code would become a lot simpler. You would just render the template and pass the variables you want. For example, for you header, it could be like this:
template = env.get_template('header.html')
print(template.render(title='Connected ...'))
You will need to set up the Environment like this first:
from jinja2 import Environment
env = Environment(
loader=PackageLoader('package', 'templates')
autoescape=select_autoescape(['html'])
)
And place your header.html file in a directory called templates.
You may also want to read about the seperation of concerns principle and the MVC architecture. Using templates like this is just one step closer to achieving MVC.
Final point on security:
It looks like you are using a HTML hidden field to store the username, and treating that as a session token. This is highly insecure and won't scale. Though, it may be sufficient for your purposes. A simple way to improve on it is to store it as a cookie using the Set-cookie header, and make it HttpOnly, e.g.
Set-cookie: session=value; HttpOnly
where value could be some unique token (e.g. a uuid).
This is much better than your current approach.
But, even better yet, you could implement security using a library like PyJWT instead.
I wish to import my own library in Brython. This page of the documentation purports to show how, by adding the appropriate directory to the python path, but I can't make it work because I can't make Brython import sys.
Here's the simplest example code from the first page of the Brython documentation:
<html>
<head>
<script src="../src/Brython3.2.8/brython.js"></script>
</head>
<body onload="brython()">
<script type="text/python">
from browser import document, alert
def echo(ev):
alert(document["zone"].value)
document['mybutton'].bind('click', echo)
</script>
<input id="zone"><button id="mybutton">click !</button>
</body>
</html>
And that works fine.
But if I try to import sys:
<html>
<head>
<script src="../src/Brython3.2.8/brython.js"></script>
</head>
<body onload="brython()">
<script type="text/python">
import sys
from browser import document, alert
def echo(ev):
alert(document["zone"].value)
document['mybutton'].bind('click', echo)
</script>
<input id="zone"><button id="mybutton">click !</button>
</body>
</html>
Then the html will display but the button will not do anything.
The Console on Chrome shows the following error:
brython.js:6929 XMLHttpRequest cannot load file:///C:/Users/XXXXXXXXX/XXXXXX/src/Brython3.2.8/Lib/sys.py?v=1476283159509. Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https, chrome-extension-resource.
$download_module # brython.js.6929
import_py # brython.js.6929
exec_module # brython.js.6929
etc etc
So, how can I import sys in brython, and/or how can I import my own library in python?
Thanks.
You need to include brython_stdlib.js in your html code. So your html should look like this:
<html>
<head>
<script src="../src/Brython3.2.8/brython.js"></script>
<script src="../src/Brython3.2.8/brython_stdlib.js"></script>
</head>
<body onload="brython()">
<script type="text/python">
import sys
from browser import document, alert
def echo(ev):
alert(document["zone"].value)
document['mybutton'].bind('click', echo)
</script>
<input id="zone"><button id="mybutton">click !</button>
</body>
</html>
Source Code : https://github.com/imvickykumar999/Brython/blob/master/index.html#L36
Deployed Code : https://imvickykumar999.github.io/Brython/
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Brython</title>
<script
type="text/javascript"
src="https://cdn.jsdelivr.net/npm/brython#3.8.9/brython.min.js">
</script>
<script
type="text/javascript"
src="https://cdn.jsdelivr.net/npm/brython#3.8.9/brython_stdlib.js">
</script>
<link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css"
integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk"
crossorigin="anonymous">
</head>
<body onload="brython()">
<style>
body {
/* background-color: yellow; */
background-image: url(https://images.unsplash.com/photo-1573196872258-41425124bf5d?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1050&q=80);
/* background-repeat: no-repeat; */
}
</style>
<script type="text/python">
from browser import document
def calc(a, b, o):
d = { '+' : a+b,
'-' : a-b,
'*' : a*b,
'/' : a/b,
'%' : a%b
}
return f"({a}{o}{b})=({d[o]})"
a = float(input('Enter first number : '))
b = float(input('Enter second number : '))
o = input('Enter the Operator (+,-,*,/,%) : ')
document <= calc(a, b, o)
</script>
</body>
</html>
Brython cannot import from any Python package that is part of any Python installation on the user's computer. It works by transpiling to JavaScript and running in the browser's Javascript engine. It has no knowledge of any local Python installations, and does not require any such installations to exist.
To use Python's standard library
Add a script tag to include brython_stdlib.js as well as the base brython.js. Several CDNs provide this already.
The Brython implementation of the Python standard library does not match the reference implementation exactly. See the documentation for details on what is included and how it is organized.
Importing your own code from within the document
For organizational purposes, Python code within the HTML document can be split across multiple <script> tags. The id attribute for the tag gives a "module name" that can be used in import statements in other scripts, as long as that script has already executed. The documentation includes an example:
<script type="text/python" id="module">
def hello():
return "world"
</script>
<script type="text/python">
from browser import document
import module
document.body <= module.hello()
</script>
The browser will have loaded the first <script> tag first, creating a (JavaScript representation of) a Python module named module that contains the hello function. The second script tag will be able to import that module and use the function as usual in Python.
Importing your own code from the server
Make the files available in the appropriate place as described in the documentation. Brython's implementation of the import statement (equivalently, __import__ builtin function) will attempt to find the code on the server using AJAX.
Importing your own code as a compiled Brython package
As explained in the documentation, use the Brython package (pip install brython) to create a JavaScript file that represents the Python code. (For third-party libraries, also check if such a JavaScript file is already available from a CDN.)
Suppose we have a project that creates a package named example. Navigate to the folder that contains that package (either src or the project folder, according to how the project is organized), then run brython-cli make_package example.
This should generate a example.brython.js file. Put it somewhere on the server, and configure the server to host that file at a specific URL. Then add the corresponding tag to the client page source (or the template that generates that page).
After that it should be possible to import example, from example import ... etc. in the Brython code.
Alternately, use brython-cli modules, as described in the 'Optimization' section, to create a combined library JavaScript file representing the entire server-side part of the project.
I'm a newbie in Python. I would like create a python script which checks(maybe parsing) every commited xml-file for the availablity of a special tag (e.g. status="Needs Review").
If the xml-file consists of this tag then send an email with a link to the topic. If not continue commit without sending any email.
Does anybody have a code sample how to realize this as a python script.
xml-file-sample:
<topic template="Default" status="Needs Review" lasteditedby="user1">
<title translate="true">Sample Title</title>
<body>
<header>
<para styleclass="Heading1"><text styleclass="Heading1" translate="true">Statistische Messungen</text></para>
</header>
<para styleclass="Normal"><text styleclass="Font Style" style="font-family:'Optima LT'; font-size:10pt; font-weight:normal; font-style:normal; text-decoration:none; text-transform:none; vertical-align:baseline; color:#000000; background-color:transparent; letter-spacing:normal; letter-scaling:100%;" translate="true">This is a sample Text</text></para>
</body>
</topic>
I guess there are different ways to do this and I know there some python codings for post-commits, but I can't find codings for this issue.
This code snippet from Andres is a good basis. I just need to grep the contents of commited xml files, such like "svn look changed" (for xml-files) and for each xml-file "svn look cat.
from lxml import html
from mailer import Mailer
from mailer import Message
import sys, os
xml = """<topic template="Default" status="Needs Review" lasteditedby="user1">
<title translate="true">Sample Title</title>
<body>
<header>
<para styleclass="Heading1"><text styleclass="Heading1" translate="true">Statistische Messungen</text></para>
</header>
<para styleclass="Normal"><text styleclass="Font Style" style="font-family:'Optima LT'; font-size:10pt; font-weight:normal; font-style:normal; text-decoration:none; text-transform:none; vertical-align:baseline; color:#000000; background-color:transparent; letter-spacing:normal; letter-scaling:100%;" translate="true">This is a sample Text</text></para>
</body>
</topic>"""
tree = html.fromstring(xml)
if tree.xpath('//topic/#status')[0] == "Needs Review":
print "This topic needs review"
print "Sending e-mail"
# Call email function here...
else:
print "This topic doesn't need review"
print "Continuing commit without sending e-mail"
# Continue with commit
I'm trying to use the built-in SimpleHTTPServer in Python to serve a static page locally. I start it with python -m SimpleHTTPServer.
At the moment, the HTML is just
<html>
<head>
<title>Test</title>
</head>
<body>
Hi
</body>
</html>
The server returns the page with status 200 but the browser console says ERR_CONTENT_LENGTH_MISMATCH and won't render anything. If I change the content to single line of text it shows up fine. Adding another line breaks it again. Per the comments, it seems like the problem is with newlines. I'm writing this in Sublime Text (on Windows) and using Chrome to view, if that helps.
It turned out to be a Sublime Text issue. Just had to change the line endings in View > Line Endings to Unix.
Big ups to this post:
Fixing Sublime Text 2 line endings?
I'm currently in the proccess of editing the html in the Python 3.3 http server code. I am doing this so I can access my media files from anywhere in my LAN. The default interface is quite boring, so I wanted to spruce it up a bit with Twitter Bootstrap buttons. The below code is from my edited server.py file, starting on line 740 (please excuse the lack of editing or elegance):
title = 'Media Listing on Computer'
r.append('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" '
'"http://www.w3.org/TR/html4/strict.dtd">')
r.append('<html>\n<head>')
r.append('<meta http-equiv="Content-Type" '
'content="text/html; charset=%s">' % enc)
r.append('<title>%s</title>\n<link href="file:///C:/Server/bootstrap.css" rel="stylesheet">\n<style type="text/css">a:link {color:grey; text-decoration: none;}</style>\n</head>' % title)
r.append('<body>\n<FONT FACE="arial" COLOR="grey">\n<h1>%s</h1>' % title)
#<body style="background-color:#B4F200;>
#<FONT FACE="courier" COLOR="grey">
r.append('<ul class="nav nav-pills nav-stacked">')
for name in list:
fullname = os.path.join(path, name)
displayname = linkname = name
# Append / for directories or # for symbolic links
if os.path.isdir(fullname):
displayname = name
linkname = name + "/"
if os.path.islink(fullname):
displayname = name + "#"
# Note: a link to a directory displays with # and links with /
r.append('<li class="active">%s</li>'
% (urllib.parse.quote(linkname), html.escape(displayname)))
r.append('</ul>\n</body>\n</html>\n')
encoded = '\n'.join(r).encode(enc)
f = io.BytesIO()
f.write(encoded)
f.seek(0)
self.send_response(200)
self.send_header("Content-type", "text/html; charset=%s" % enc)
self.send_header("Content-Length", str(len(encoded)))
self.end_headers()
return f
This generates a page with the following html:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=mbcs">
<title>Media Listing on Computer</title>
<link href="file:///C:/Server/bootstrap.css" rel="stylesheet">
<style type="text/css">a:link {color:grey; text-decoration: none;}</style>
</head>
<body>
<FONT FACE="arial" COLOR="grey">
<h1>Media Listing on Computer</h1>
<ul class="nav nav-pills nav-stacked">
<li class="active">FRAPS</li>
<li class="active">iTunes</li>
<li class="active">Misc videos</li>
<li class="active">Movies</li>
<li class="active">TV</li>
</ul>
</FONT>
</body>
</html>
Now when I open the html in a web browser it works fine, in that it loads the Twitter Bootstrap UI, however, when I run the python server, the UI doesn't load. I would really like to know how I can fix this, so if someone could give me a hand in sorting this out, that would be appreciated.
Does your browser know you are using the correct stylesheet? Maybe try using a relative path for bootstrap instead of an absolute file:///C:/Server/bootstrap.css?
UPDATE (from comments)
You placed bootstrap in a directory outside of the server root directory, so your browser wasn't able to access the css and render it. Move bootstrap into the server directory (e.g. C:\Server\lib\http\bootstrap\) and update the stylesheet path accordingly (e.g. <link href="/bootstrap/bootstrap.css" rel="stylesheet">)