How to change SimpleHTTPServer code to an equivalent production server - python

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

Related

Request over https using R shiny and a python server

I have a python server that runs using an ssl wrapped socket. I am trying to send an https GET and POST request from an R-shiny client to the python server, yet I get the following error:
Listening on http://127.0.0.1:6565
Warning: Error in curl::curl_fetch_memory: schannel: Failed to get certificate location for >c/cygwin64/home/user/Documents/server/cert.pem
My overarching goal is to type a text into the shiny R text input, send this text to the python server in the form of a POST request over a secure channel. The python server I will run the interpreter() function on the string I just sent and return to the R-shiny client the appropriate response.
This setup has worked when not using ssl-certificates, however, after implementing the python ssl wrapped socket, I have been getting this error.
I hope some of you might be able to illuminate me on this matter.
This is my python server
import ssl
from http.server import HTTPServer, BaseHTTPRequestHandler
from io import BytesIO
def interpreter(val):
if val == "Search":
return "Searched"
elif val == "Add":
return "Added"
else:
return "Invalid statement"
class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header("Content-type", "text/csv")
self.end_headers()
self.wfile.write(bytes(
"<html><body><h1>HELLO world!</h1></body></html>", "utf-8"))
def do_POST(self):
content_length = int(self.headers['Content-Length'])
body = self.rfile.read(content_length)
print(body.decode())
modified_body = interpreter(body.decode())
print(modified_body)
self.send_response(200)
self.end_headers()
response = BytesIO()
response.write(b'Received: ')
response.write(body)
response.write(b' End of request')
self.wfile.write(response.getvalue())
httpd = HTTPServer(('localhost', 8000), SimpleHTTPRequestHandler)
httpd.socket = ssl.wrap_socket(httpd.socket, keyfile="key.pem",
certfile="cert.pem", server_side=True)
print("Server Running Now...")
httpd.serve_forever()
httpd.server_close()
print("Server Stopped")
And my shiny-R application is as follows
library(shiny)
library(httr)
ui <- fluidPage(
titlePanel("Request Module"),
fluidRow(
column(3,
textInput(inputId = "request", label="Enter Request Term"),
actionButton(inputId = "getRequest", label="Get"),
actionButton(inputId = "postRequest", label="Post")
)
),
fluidRow(
wellPanel(
htmlOutput(outputId = "resultOutput")
)
)
)
server <- function(input, output) {
url <- "http://127.0.0.1:8000"
s_url <- "https://127.0.0.1:8000"
httr::set_config(config(ssl_verifypeer = 0L))
certfile="c/cygwin64/home/user/Documents/server/cert.pem"
keyfile="c/cygwin64/home/user/Documents/server/key.pem"
observeEvent(input$getRequest,{
getResponse <- GET(url = s_url,
config(sslcert=certfile, sslkey=keyfile))
output$resultOutput <- renderPrint({
getResponse$content
})
})
observeEvent(input$postRequest,{
reqMessage <- input$request
postResult <- POST(url = s_url,
body = reqMessage,
content_type("text/csv"),
encoding = "UTF-8",
config(sslcert=certfile, sslkey=keyfile))
processedResponse <- content(postResult, as="text", encoding = "UTF-8")
output$resultOutput <- renderPrint({
processedResponse
})
})
}
shinyApp(ui = ui, server = server)

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()

I am having issues serving a web page with 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() '''

How do I shutdown an HTTPServer from inside a request handler in Python?

How do I shutdown this server when I receive the StopIteration exception? sys.exit() does not work.
#!/usr/bin/env python
from BaseHTTPServer import BaseHTTPRequestHandler,HTTPServer
PORT_NUMBER = 2000
from itertools import islice
filename = 'data/all.txt'
file = open(filename, 'r')
lines_gen = islice(file, None)
class MyHandler(BaseHTTPRequestHandler):
def do_GET(self):
global lines_gen
self.send_response(200)
self.send_header('Content-type','text/plain')
self.end_headers()
try:
for i in range(10):
next_line = lines_gen.next()
self.wfile.write(next_line)
except StopIteration:
# return response and shutdown the server
# ?????
return
try:
server = HTTPServer(('', PORT_NUMBER), MyHandler)
print('Started httpserver on port ' , PORT_NUMBER)
server.serve_forever()
except KeyboardInterrupt:
print('^C received, shutting down the web server')
server.socket.close()
Just call shutdown() in a second thread.
# return response and shutdown the server
import threading
assassin = threading.Thread(target=server.shutdown)
assassin.daemon = True
assassin.start()

Categories