1

I'm using BaseHTTPServer.BaseHTTPRequestHandler in order to implement my server.

currently I repsonse to get request with merely binary data file.

self.send_response(200)
self.send_header("Content-Type", 'application/octet-stream')
self.send_header("Content-Disposition", 'attachment; filename="{}"'.format(os.path.basename(FILEPATH)))
fs = os.fstat(f.fileno())
self.send_header("Content-Length", str(fs.st_size))
self.end_headers()

Now it's requested to add another section which include some short json formatted configuration data (i.e. {'status': 'ok', 'type': 'keepalive'}) and i'd rather pass this information on the same response separated by unique http header or by the http body.

What is the best way to do so ? I'd like to know how to extend my code to support this.

Thanks

1 Answer 1

1

There's lots of ways to do this, I think the best choice is going to depend on what your receiving side is capable of understanding most easily.

The most literal interpretation would be to use content-type multipart/mixed https://www.w3.org/Protocols/rfc1341/7_2_Multipart.html but you're probably going to have to write your own parsing on the receiving end. I don't know if this is exactly to spec, but it gets the idea across:

from http.server import BaseHTTPRequestHandler
import http.server
import socketserver
import string
import random
import io

PORT = 8000

class ResponsePart:
    def __init__(self, content, content_type):
        self.content = content.encode('utf-8')
        self.content_type = content_type.encode('utf-8')

class Mine(http.server.BaseHTTPRequestHandler):
    def get_separator(self, parts):
        while True:
            boundary = []
            for i in range(32):
                boundary.append(random.choice(string.digits + string.ascii_letters))
            boundary = ''.join(boundary).encode('ascii')
            for part in parts:
                if boundary in part:
                    break
            else:
                return boundary

    def do_GET(self):
        responses = [
                ResponsePart('abc123', 'Content-type: application/octet-stream'),
                ResponsePart('{"a":"b"}', 'Content-type: application/json'),
        ]
        boundary = self.get_separator([r.content for r in responses])
        self.send_response(200)
        self.send_header("Content-Type", 'multipart/mixed; boundary=' + boundary.decode('ascii'))
        self.end_headers()

        for piece in responses:
            self.wfile.write(b'--')
            self.wfile.write(boundary)
            self.wfile.write(b'\r\n')
            self.wfile.write(piece.content_type)
            self.wfile.write(b'\r\n')
            self.wfile.write(piece.content)
            self.wfile.write(b'\r\n')

Handler = Mine

with socketserver.TCPServer(("", PORT), Handler) as httpd:
    httpd.serve_forever()

With that out of the way, I'd do this probably using JSON or something so that you're returning a single consistent content-type:

from http.server import BaseHTTPRequestHandler
import http.server
import socketserver
import string
import random
import io
import json

PORT = 8000

class Mine(http.server.BaseHTTPRequestHandler):
    def do_GET(self):
        response = {
                'filedata': 'abc123',
                'status': {"a":"b"},
        }
        output_data = json.dumps(response).encode('utf-8')

        self.send_response(200)
        self.send_header("Content-Type", 'application/octet-stream')
        self.send_header("Content-Length", str(len(output_data)))
        self.end_headers()

        self.wfile.write(output_data)

Handler = Mine

with socketserver.TCPServer(("", PORT), Handler) as httpd:
    httpd.serve_forever()

This is going to be far easier to handle on the receiving end, one json decode and you're done.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.