I am having issues serving a web page with python - python

I am trying to serve a basic webpage in python.
If I cd to the dir and then run "python -m http.server 80" The page is displayed without issues, all formatting is correct. The issue is that I require some degree of security, so I have written a basic authentication python script which i run from the same directory. Unfortunately I get a badly rendered page with no formatting. Can anybody help me? All i need do is once fully authenticated, launch this web site in current directory.
Code is :-
import http.server
import socketserver
from http.server import BaseHTTPRequestHandler, HTTPServer
class CustomHandler(BaseHTTPRequestHandler):
''' Main class to present webpages and authentication. '''
def do_HEAD(self):
self.send_response(200)
self.send_header('Content-type', 'text/html')
print ('all authenticated')
self.end_headers()
def do_AUTHHEAD(self):
self.send_response(401)
self.send_header('WWW-Authenticate', 'Basic realm=\"SmarterADM\"')
self.send_header('Content-type', 'text/html')
self.end_headers()
def do_GET(self):
''' Present frontpage with user authentication. '''
if self.headers['Authorization'] == None:
self.do_AUTHHEAD()
self.wfile.write(bytes('no auth header received', 'UTF-8'))
pass
elif self.headers['Authorization'] == 'Basic c21hcnRlcmFkbTpwYXNzdzByZA==':
self.do_HEAD()
self.wfile.write(bytes(self.headers['Authorization'], 'UTF-8'))
self.wfile.write(bytes(' authenticated!', 'UTF-8'))
rootdir = 'c:/Team/main/START/index.html' #file location
f = open(rootdir,'rb') #open requested file
self.wfile.write(f.read())
return render.rootdir
pass
else:
self.do_AUTHHEAD()
self.wfile.write(bytes(self.headers['Authorization'], 'UTF-8'))
self.wfile.write(bytes(' not authenticated Mark says NO!', 'UTF-8'))
pass
httpd = HTTPServer(('', 80), CustomHandler)
print ('started httpd...')
httpd.serve_forever()
if __name__ == '__main__':
main()
'''' rootdir = 'c:/RTS_Team/STAR2/STAR2/index.html' #file location
f = open(rootdir,'rb') #open requested file
self.wfile.write(f.read())
f.close() '''

Related

How do I configure a python server for POST?

I'm trying out some PHP on my pc and made a little python server to host the files, one problem:
It can't do POST, I always get the error 501. I've heard that you can implement POST in these servers, but I didn't find how to do this, can someone help?
Here's my current server:
import http.server
import socketserver
PORT = 8080
Handler = http.server.SimpleHTTPRequestHandler
with socketserver.TCPServer(("", PORT), Handler) as httpd:
print("serving at port", PORT)
httpd.serve_forever()
This is the script I personally use for when I need this kind of functionality:
#!/usr/env python3
import http.server
import os
import logging
try:
import http.server as server
except ImportError:
# Handle Python 2.x
import SimpleHTTPServer as server
class HTTPRequestHandler(server.SimpleHTTPRequestHandler):
"""
SimpleHTTPServer with added bonus of:
- handle PUT requests
- log headers in GET request
"""
def do_GET(self):
server.SimpleHTTPRequestHandler.do_GET(self)
logging.warning(self.headers)
def do_PUT(self):
"""Save a file following a HTTP PUT request"""
filename = os.path.basename(self.path)
# Don't overwrite files
if os.path.exists(filename):
self.send_response(409, 'Conflict')
self.end_headers()
reply_body = '"%s" already exists\n' % filename
self.wfile.write(reply_body.encode('utf-8'))
return
file_length = int(self.headers['Content-Length'])
with open(filename, 'wb') as output_file:
output_file.write(self.rfile.read(file_length))
self.send_response(201, 'Created')
self.end_headers()
reply_body = 'Saved "%s"\n' % filename
self.wfile.write(reply_body.encode('utf-8'))
if __name__ == '__main__':
server.test(HandlerClass=HTTPRequestHandler)
But perhaps a more fitting, and simpler script would be the following, as found on Flavio Copes' blog:
from http.server import BaseHTTPRequestHandler, HTTPServer
class handler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header('Content-type','text/html')
self.end_headers()
message = "Hello, World! Here is a GET response"
self.wfile.write(bytes(message, "utf8"))
def do_POST(self):
self.send_response(200)
self.send_header('Content-type','text/html')
self.end_headers()
message = "Hello, World! Here is a POST response"
self.wfile.write(bytes(message, "utf8"))
with HTTPServer(('', 8000), handler) as server:
server.serve_forever()

Python BaseHTTPRequestHandler server works for first GET request only

I'm working on trying create a super basic python webserver based on BaseHTTPRequestHandler. When I perform the GET request to the address 127.0.0.1/a for the first time, everything works well and I recover an image on my browser.
However, when I repeat this GET request a second time, I do not get anything. Tracing the code, I can see that the code itself is running through the entire do_GET(self) segment.
I'm really confused as to why the webserver would work the first time and not the next.
Any and all help is much appreciated.
from http.server import BaseHTTPRequestHandler, HTTPServer
from os import curdir, sep
imagefile = "a.jpg"
imagepage =open(curdir+sep+imagefile, 'rb')
notfound = "File not found"
class webserverHandler(BaseHTTPRequestHandler):
def do_OPTIONS(self):
self.send_response(200)
self.send_header('Access-Control-Allow-Origin', '*')
self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
self.send_header("Access-Control-Allow-Headers", "X-Requested-With")
def do_GET(self):
if self.path == "/a":
print("getting thg jpg file")
self.send_response(200)
self.send_header("Content-type","image/png")
self.end_headers()
self.wfile.write(imagepage.read())
else:
self.send_error(404, notfound)
def main():
try:
port = 1234
server = HTTPServer(('127.0.0.1', port), webserverHandler)
print("Web server is running on port {}".format(port))
server.serve_forever()
except KeyboardInterrupt:
print("^C entered, stopping web server...")
finally:
if server:
print("closing server")
server.socket.close()
if __name__ == '__main__':
main()
Thank you!
def do_GET(self):
notfound = "File not found"
if self.path == "/a":
print("getting thg jpg file")
self.send_response(200)
self.send_header("Content-type","image/png")
self.end_headers()
imagefile = "fig1.png"
imagepage =open(curdir+sep+imagefile, 'rb')
self.wfile.write(imagepage.read())
else:
self.send_error(404, notfound)
Please read file in each request.
Why:
imagepage.read() make file seek to end of the image file, So, we cannot read any data with next imagepage.read() from second request.
Or
We can use imageContent = imagepage.read() at first,
and we can send imageContent every request
from http.server import BaseHTTPRequestHandler, HTTPServer
from os import curdir, sep
imagefile = "fig1.png"
imagepage =open(curdir+sep+imagefile, 'rb')
imageContent = imagepage.read() # Read Image here
notfound = "File not found"
class webserverHandler(BaseHTTPRequestHandler):
def do_OPTIONS(self):
self.send_response(200)
self.send_header('Access-Control-Allow-Origin', '*')
self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
self.send_header("Access-Control-Allow-Headers", "X-Requested-With")
def do_GET(self):
if self.path == "/a":
print("getting thg jpg file")
self.send_response(200)
self.send_header("Content-type","image/png")
self.end_headers()
self.wfile.write(imageContent)
else:
self.send_error(404, notfound)
def main():
try:
port = 1234
server = HTTPServer(('127.0.0.1', port), webserverHandler)
print("Web server is running on port {}".format(port))
server.serve_forever()
except KeyboardInterrupt:
print("^C entered, stopping web server...")
finally:
if server:
print("closing server")
server.socket.close()
if __name__ == '__main__':
main()

How to change SimpleHTTPServer code to an equivalent production server

I wrote the following code to accept a HTTP POST and then write out a temp file that includes the POST data and then send that temp file to a printer using subprocess and the UNIX lp command.
from http.server import HTTPServer, BaseHTTPRequestHandler
class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.end_headers()
self.wfile.write(b'Hello, world!')
def do_POST(self):
content_length = int(self.headers['Content-Length'])
body = self.rfile.read(content_length)
try:
result = json.loads(body, encoding='utf-8')
# Do other stuff with result
p = subprocess.Popen(['/usr/bin/env', 'lp', '-d', printer_queue, temp.name], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
self.send_response(200)
self.end_headers()
response = BytesIO()
response.write(b'POST Received: ')
response.write(body)
self.wfile.write(response.getvalue())
except Exception as err:
tb = traceback.format_exc()
print(tb)
self.send_response(500) # 500 Internal Server Error
self.end_headers()
response = BytesIO()
response.write(b'ERROR: Blah')
self.wfile.write(response.getvalue())
httpd = HTTPServer(('localhost', 8000), SimpleHTTPRequestHandler)
and everything was awesome. Then I read that HTTPServer shouldn't be used in Production and everything was no longer awesome.
So how can I write the equivalent code that can be used as a production server? I have a Apache web server, but I'm not sure how to add the above Python code to it (preferrably without changing the above code too much since there is a lot of it).
I found out a way to connect your code with nginx server. At first add some code with your function add create socket and after that write a nginx conf file. it will work
Step 1 :
add main() function in your function
from http.server import HTTPServer, BaseHTTPRequestHandler
class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.end_headers()
self.wfile.write(b'Hello, world!')
def do_POST(self):
content_length = int(self.headers['Content-Length'])
body = self.rfile.read(content_length)
try:
result = json.loads(body, encoding='utf-8')
# Do other stuff with result
p = subprocess.Popen(['/usr/bin/env', 'lp', '-d', printer_queue, temp.name], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
self.send_response(200)
self.end_headers()
response = BytesIO()
response.write(b'POST Received: ')
response.write(body)
self.wfile.write(response.getvalue())
except Exception as err:
tb = traceback.format_exc()
print(tb)
self.send_response(500) # 500 Internal Server Error
self.end_headers()
response = BytesIO()
response.write(b'ERROR: Blah')
self.wfile.write(response.getvalue())
def main():
try:
server = HTTPServer(('localhost', 8000), SimpleHTTPRequestHandler)
print ('Starting BaseServer.')
server.serve_forever ()
except KeyboardInterrupt:
print ('Interrupt recieved; closing server socket')
server.socket.close()
if __name__ == '__main__':
main()
Step 2 :
nginx.conf file should be like this
server {
location / {
root /data/www;
}
location / {
proxy_pass http://localhost:8000;
}
}
If face any issue comment below

How do I map incoming "path" requests when using HTTPServer?

I'm fairly new to coding in python. I created a local web server that says "Hello World" and displays the current time.
Is there a way to create a path, without creating a file, on the server program so that when I type in "/time" after 127.0.0.1 in the browser bar, it will display the current time? Likewise if I type "/date" it will give me the current date.
This is what I have so far:
from BaseHTTPServer import BaseHTTPRequestHandler,HTTPServer
import datetime
port = 80
class myHandler(BaseHTTPRequestHandler):
#Handler for the GET requests
def do_GET(self):
self.send_response(200)
self.send_header('Content-type','text/html')
self.end_headers()
# Send the html message
self.wfile.write("<b> Hello World !</b>"
+ "<br><br>Current time and date: " + str(datetime.datetime.now()))
server = HTTPServer(('', port), myHandler)
print 'Started httpserver on port ', port
#Wait forever for incoming http requests
server.serve_forever()
Very simple URL handler:
def do_GET(self):
if self.path == '/time':
do_time(self)
elif self.path == '/date':
do_date(self)
def do_time(self):
self.send_response(200)
self.send_header('Content-type','text/html')
self.end_headers()
# Send the html message
self.wfile.write("<b> Hello World !</b>"
+ "<br><br>Current time: " + str(datetime.datetime.now()))

Fetching HTTP GET variables in Python

I'm trying to set up a HTTP server in a Python script. So far I got the server it self to work, with a code similar to the below, from here.
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
class MyHandler(BaseHTTPRequestHandler):
def do_GET(self):
print("Just received a GET request")
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
self.wfile.write('Hello world')
return
def log_request(self, code=None, size=None):
print('Request')
def log_message(self, format, *args):
print('Message')
if __name__ == "__main__":
try:
server = HTTPServer(('localhost', 80), MyHandler)
print('Started http server')
server.serve_forever()
except KeyboardInterrupt:
print('^C received, shutting down server')
server.socket.close()
However, I need to get variables from the GET request, so if server.py?var1=hi is requested, I need the Python code to put var1 into a Python variable and process it (like print it). How would I go about this? Might be a simple question to you Python pros, but this Python beginner doesn't know what to do! Thanks in advance!
Import urlparse and do:
def do_GET(self):
qs = {}
path = self.path
if '?' in path:
path, tmp = path.split('?', 1)
qs = urlparse.parse_qs(tmp)
print path, qs
urlparse.parse_qs()
print urlparse.parse_qs(os.environ['QUERY_STRING'])
Or if you care about order or duplicates, urlparse.parse_qsl().
Import in Python 3: from urllib.parse import urlparse

Categories