Unable to view files in a browser with python http server
Asked Answered
H

2

10

I am creating a python httpserver for a folder on remote machine using command :

python -m SimpleHTTPServer 9999

But I am unable to view a file in the browser using this. As soon as click on the link the file gets downloaded. Is there a way to create a server so that i can view the files in my browser only.

Honor answered 2/6, 2016 at 7:19 Comment(7)
What kind of file is it? PDF, image, MS Office, ...?Phoenician
.sh .config etc extensions but the content inside is ascii. I am able to see .txt files although but i want to see other files as wellHonor
Check two things: 1) Can your browser display these files inline? 2) What is the Content-Type header of the HTTP response?Phoenician
For .sh file , Content-type: application/x-shHonor
What OS are you running this server on?Phoenician
chrome browser on mac os x. the httpserver is on linux machineHonor
To force the browser to open non-html documents inline you can set the Content-Disposition response header to inline. You have to write your own HttpRequestHandler to do that.Zimmer
L
8

To make the browser open files inline instead of downloading them, you have to serve the files with the appropriate http Content headers.

What makes the content load inline in the browser tab, instead of as a download, is the header Content-Disposition: inline.

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition

To add these headers, you you can subclass the default SimpleHTTPRequestHandler with a custom one.

This is how it can be done using python 3. You have to modify the imports and maybe some other parts if you have to use python 2.

Put it in a executable script file which you can call myserver.py and run it like so: ./myserver.py 9999

#!/usr/bin/env python3

from http.server import SimpleHTTPRequestHandler, test
import argparse


class InlineHandler(SimpleHTTPRequestHandler):

    def end_headers(self):
        mimetype = self.guess_type(self.path)
        is_file = not self.path.endswith('/')
        # This part adds extra headers for some file types.
        if is_file and mimetype in ['text/plain', 'application/octet-stream']:
            self.send_header('Content-Type', 'text/plain')
            self.send_header('Content-Disposition', 'inline')
        super().end_headers()

# The following is based on the standard library implementation 
# https://github.com/python/cpython/blob/3.6/Lib/http/server.py#L1195
if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--bind', '-b', default='', metavar='ADDRESS',
                        help='Specify alternate bind address '
                             '[default: all interfaces]')
    parser.add_argument('port', action='store',
                        default=8000, type=int,
                        nargs='?',
                        help='Specify alternate port [default: 8000]')
    args = parser.parse_args()
    test(InlineHandler, port=args.port, bind=args.bind)
Lisalisabet answered 2/6, 2016 at 9:1 Comment(2)
I was having trouble serving html content without .htm/.html extension using python3's http.server. Using method above I replaced self.send_header('Content-Type', 'text/plain') with self.send_header('Content-Type', 'text/html') and now it works. Really useful snippet.Tallou
Couldn't view mhtml files after changing it to its content type multipart/related .Hyams
P
0

Serving files like foo.sh should work fine using the SimpleHTTPServer. Using curl as the client, I get a HTTP response like this:

$ curl -v http://localhost:9999/so.sh
* Hostname was NOT found in DNS cache
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 9999 (#0)
> GET /so.sh HTTP/1.1
> User-Agent: curl/7.35.0
> Host: localhost:9999
> Accept: */*
> 
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Server: SimpleHTTP/0.6 Python/2.7.6
< Date: Thu, 02 Jun 2016 07:28:57 GMT
< Content-type: text/x-sh
< Content-Length: 11
< Last-Modified: Thu, 02 Jun 2016 07:27:41 GMT
< 
echo "foo"
* Closing connection 0

You see the header line

Content-type: text/x-sh

which is correct for the file foo.sh. The mapping from the file extensions sh to text/x-sh happens in /etc/mime.types on GNU/Linux systems. My browser

Chromium 50.0.2661.102

is able to display the file inline.

Summary: As long as you serve known files and your browser can display them inline, everything should work.

Phoenician answered 2/6, 2016 at 7:31 Comment(3)
Content-type: application/x-sh is returned in my caseHonor
This probably depends on the configuration of your OS. Does your OS have a file /etc/mime.types? On my Ubuntu this includes a mapping from sh to text/x-sh. Python probaly reads this configuration to set the Content-Type header.Phoenician
yes i found this file and corresponding entry is application/x-sh sh for me. thanksHonor

© 2022 - 2024 — McMap. All rights reserved.