Python Web Server and File Download - python

I've made this simple HTTP server in Python:
import SimpleHTTPServer
import SocketServer
PORT = 8000
Handler = SimpleHTTPServer.SimpleHTTPRequestHandler
httpd = SocketServer.TCPServer(("", PORT), Handler)
print "serving at port", PORT
httpd.serve_forever()
What I want to do now, but I don't know how, is the following:
When I visit http://localhost:8000/my/path/download?documentID=100 , a document (particularly a PDF file) will start being downloaded automatically. Of course, I have more documents but I want them to be identified by the get paramater documentID
What is the easiest way to achieve this? thanks

You have to write a new handle. http://fragments.turtlemeat.com/pythonwebserver.php shows a simple example.
You have to:
determinate the PDF-File out of the ID
read the pdf file
send the right content-flag
send the pdf file
alternative:
write a script saving the pdfs with the ids like 1.pdf, 2.pdf
use your example code
and simple use links like http://localhost:8000/my/path/1.pdf
Greets Kuishi
PS: English isn't my native language, sorry

Related

python 2 web server local host error. The server responded with a non-JavaScript MIME type of "text/plain"

(First time)
I used python -m SimpleHTTPServer 8000 using python 2.7.15 to generate a web server for my simple JavaScript game (still learning), but it seems that it has some error, which makes the canvas of my HTML file wont show.
The JavaScript works totally fine in my GitHub page, but it won't show in local web server. https://jcloh98.github.io/jsgame/simplegame2.html
All the codes are exactly the same as the website. That's all the code I used.
This is the error showed in the console log.
Failed to load module script: The server responded with a non-JavaScript MIME type of "text/plain". Strict MIME type checking is enforced for module scripts per HTML spec.
https://jcloh98.github.io/jsgame/simplegame2.html
It is expected to show a black canvas with a aqua paddle at the bottom of the canvas, like https://jcloh98.github.io/jsgame/simplegame2.html
Instead of using python -m SimpleHTTPServer 8000, create a .py file named "localhost.py" and run the .py file in the same directory of the webpage.
localhost.py force the file with extension ".js" has "application/javascript" as the content type.
localhost.py
#Use to create local host
import SimpleHTTPServer
import SocketServer
PORT = 8000
Handler = SimpleHTTPServer.SimpleHTTPRequestHandler
Handler.extensions_map.update({
".js": "application/javascript",
});
httpd = SocketServer.TCPServer(("", PORT), Handler)
print "Serving at port", PORT
print(Handler.extensions_map[".js"])
httpd.serve_forever()
Thanks Bergi for helping me to solve this problem out.

Pass hostname of unix server to a .py file and .html file

I need to get the hostname of the unix server on which the application is running(maybe store in a properties file) and then fetch that hostname value in .py file and .html file.
I need the hostname for a url which is hardcoded in the code.
url should look something like this : http://{hostname value}.nam.net/
You can get the UNIX servers hostname by using the socket module:
import socket
socket.gethostname()
you can then write this to your configuration file if you need it to be static, or otherwise just re-use the code in your python files when generating the hostname.
I think that you will have a problem with what you want to do - the http://{hostname...}.nam.net will only work if you have a DNS services and something that will translate it from IP address to name.
maybe you want something like this:
import socket
def get_ip_address():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
return s.getsockname()[0]
this will open a socket to google server and you will get back your external ip address to be used as url

How to write a message in SimpleHTTPServer

I'm relatively new to Python. I am trying to run a simple server using python. I successfully did this, but I want to have a message such as "Hello World" when I run the server from my browser.
It posts my directory when I run the program and says "Directory listing for/" at the top. Is there a way to add more text on this page?
How would I do this?
import sys
import BaseHTTPServer
from SimpleHTTPServer import SimpleHTTPRequestHandler
HandlerClass = SimpleHTTPRequestHandler
ServerClass = BaseHTTPServer.HTTPServer
Protocol = "HTTP/1.0"
if sys.argv[1:]:
port = int(sys.argv[1])
else:
port = 8000
server_address = ('127.0.0.1', port)
HandlerClass.protocol_version = Protocol
httpd = ServerClass(server_address, HandlerClass)
sa = httpd.socket.getsockname()
print "Serving HTTP on", sa[0], "port", sa[1], "..."
httpd.serve_forever()
When you implement such a httpserver and browse it, the do_GET method of the SimpleHTTPRequestHandler is called. And by default it will searches the directory your script is in for index.html or index.htm. If there is no such file, the directory will be displayed.
So if you want to display contents rather than the directory. You should add a file index.html or index.htm in your directory. And writes the contents you want to display in the file.
For more please refer the doc.
You are using SimpleHTTPServer, and while its great, you would have to use CGI for interaction. This answer does not answer your exact question, but I believe it will allow you to do the same with, with ease.
In Python, we use WSGI servers to interact with websites. The reason we do this, is because WSGI scales and can handle a lot more than CGI or Common Gateway Interface. You can take a look # WSGI, here.
Armin Ronacher wrote this, and he is the author of two popular Python frameworks, Flask and Werkzueg. If you intend to continue learning Python web development, you will meet these frameworks soon.
I realize that this does not answer your question per-se. But, it will allow you to get the same thing, and will give you a foundation that can help you with popular frameworks.

Listening for HTTP responses

I am trying to write a python application that will listen for HTTP responses on a socket. I am using http-parser for this. Here is my code:
#!/usr/bin/env python
import socket
from http_parser.http import HttpStream
from http_parser.reader import SocketReader
from http_parser.util import b
def main():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostname(), 7000))
s.listen(5)
try:
while True:
p = HttpStream(SocketReader(s))
finally:
s.close()
if __name__ == "__main__":
main()
I have two questions:
Is this the best way to do this? Note that I do not want to send a request and then listen for a response. I want to have a redirection mechanism that redirects all responses to the box running this script.
How should I test this? Is there a tool that can mock HTTP responses?
EDIT
What I am trying to do is this: I have three boxes, once runs Apache, one runs this script and one is the client. When the client connects to Apache and it sends back a response, I am diverting the response to this box. So in this script, I am trying to listen for HTTP responses.
Topology
Here is my topology:
Server <----> Switch one <-----> Switch two <-----> Box one and two
Initially, box one connects to the server and sends a request. When the second switch receives responses from the server, it forks it to both box one and box two.
That is a perfectly fine implementation if you really want to operate at the level of TCP sockets. If you want more abstraction, there are lots and lots of HTTP server packages for python, including the standard library's BaseHttpServer, and external libraries/frameworks like tornado and cherrypy.
To test your HTTP listener there are lots of options. You could write full-on HTTP client test code in Python (using an HTTP client library like urllib), or you could:
Point your web browser to http://localhost:7000
telnet to port 7000 on localhost and type in raw HTTP requests.
Automate the above by using nc, e.g.:
echo -e 'GET / HTTP/1.1\n\n' | nc localhost 7000
A note on terminology: What you are listening for on your bound socket is an HTTP request, in the HTTP parlance; what you send back to the connecting client is a response.
1. Is there is a better way?
Yes, there is
2. How should I test this?
common practice is to put a test.py in the same folder, and run python test.py to test. Sample code:
#!python
# -*- coding: utf-8 -*-
import optparse
import urllib2
from django.utils import unittest
# just a sample of settings
HOST = 'localhost'
class GIOPTest(unittest.TestCase):
def test_basic(self):
#TEST GOES HERE
if __name__ == '__main__':
# This part is to accept command line parameters
option_list = ( # check optparse help for more options
make_option("--host",
action = 'store',
type = 'string',
dest = 'host',
default = 'localhost',
help = 'Server host (localhost by default)'
),
)
parser = OptionParser(option_list=option_list)
options, args = parser.parse_args()
HOST = options.host
# run the test
unittest.main()
I ended up using a raw socket and directly reading packets from it.
if you're using apache as the server you're redirecting the data to you could use apache benchmark (ab - you must be superuser though to use it as far as I know) to test it... will also help evaluate the performance impact your application has on the whole thing, example
ab -n 500 -c 20 http://localhost:7000/
where after -n is the total number of connections made to the server during the test and after -c you have the number of concurrent connections apache benchmark will make, experiment with different values of these, also read it's manual, you might find more useful options for whatever your specific purpose might be

how to handle non http request in pywsgi

I have a web server using gevent.pywsgi.WSGIServer (http://www.gevent.org/gevent.pywsgi.html)and I need to handle a non-http request as well as normal http requests.
Server:
web_server = gevent.pywsgi.WSGIServer(('', 8080), web_server);
web_server.serve_forever();
Handler:
def viewer_command_server(env, start_response):
if env['REQUEST_METHOD'].upper() == "PUT":
path = env["PATH_INFO"]
start_response("200 OK", [("Content-Type", "text/html"), ("Cache-Control", "no-cache"), ("Connection","keep-alive")])
return [ ""]
This handles normal PUT requests, but I would like also server the crossdomain.xml file used by a flash application. But the problem is I get this when the flash application tries to retrieve its crossdomain.xml file.
"socket fileno=13 sock=66.228.55.170:9090 peer=96.54.202.251:63380: Invalid HTTP method: '<policy-file-request/>\x00'
96.54.202.251 - - [2012-05-21 22:58:53] "<policy-file-request/>" 400 0 2.940527
"
Is there any way to handle this request as well?
Adobe recommends running a separate tcp server on port 843 to serve this file.
I would like to keep everything on port 8080.
The protocol spoken on port 843 is not HTTP. See http://www.adobe.com/devnet/flashplayer/articles/socket_policy_files.html.
A valid HTTP request looks like
GET /path HTTP/1.0
(See e.g. http://www.jmarshall.com/easy/http/#sample for more examples.)
If there's a way to tell the Flash Player client to look for the policy file on some port other than 843, then maybe there's a way to tell it to use HTTP instead of this custom XML-ish "" message, and then and only then could you handle this from your HTTP server.
Anything is possible but I don't think it sounds like a good idea at all to handle non-HTTP requests as part of your WSGI server on the same port 8080 that it uses for HTTP.
I managed to peel this one back a bit further today. Buried in the adobe documentation is a note that if you are using a raw socket then fit will go looking for your cross domain file using their raw XML query. It does appear to work if you specify 'http' and it does go and get the cross domain file via http. The problem for me was that I was using a raw tcp socket in my flash script. So it went off to try to get the cross domain file from that server.
So to keep things simple I will change the network calls to use http. That is what they are doing anyway (I was using a sample I found that does streaming using http multipart response)

Categories

Resources