my http server got post request including file, how to forward to external URL using POST method too

875 views Asked by At

I have a problem, and I searched a lot but none of codes here do my request

I'm running python local server using http.server - BaseHTTPRequestHandler

here is my code

def run_http():
    port=80
    server_address = ('', port)
    httpd = ThreadingHTTPServer(server_address, serverClass)

    # print('HTTP server running on port %s'% port)
    httpd.serve_forever()

class serverClass(BaseHTTPRequestHandler):
    def _set_headers(self):
        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()

    def do_GET(self):
        self._set_headers()

        if self.path == '/':
            with open("static\\index.html", 'r') as f:
                res = f.read()
            self.wfile.write(res.encode('utf-8'))

        elif self.path == '/favicon.ico':
            with open("static\\favicon.ico", 'rb') as f:
                res = f.read()
            self.wfile.write(res)
        
        else:
            ...


    def do_HEAD(self):
        self._set_headers()
        
    def do_POST(self):
        # content_length = int(self.headers['Content-Length'])
        # post_data = self.rfile.read(content_length)
        # <= here I need to forward the post request to another URL _POST_URL
        # The post request I received may include file and may be not, so I need to forward the post request as it is

I tried some codes for example:

ctype, pdict = cgi.parse_header(self.headers['content-type'])
pdict['boundary'] = bytes(pdict['boundary'], "utf-8")
if ctype == 'multipart/form-data':
    fields = cgi.parse_multipart(self.rfile, pdict)
    field_file = {'file':(fields.get('file'), "multipart/form-data")}
    fields.pop('file')
    r = requests.post(_POST_URL+'/in.php', files = field_file, data = fields)

note: I know that the file will be with post name file That code works, but the problem is I don't sent the file type or the file name, and I cannot got it really. Am I in the right way, or I should use more efficient codes

1

There are 1 answers

0
Bassem Shahin On BEST ANSWER

Ok I used cgi.FieldStorage

and here is the code if somebody may interesed;

def do_POST(self):
    form = cgi.FieldStorage( fp=self.rfile, headers=self.headers, environ={'REQUEST_METHOD':'POST', 'CONTENT_TYPE':self.headers['Content-Type'] })
    
    post_data = {}
    for field in form:
        if field != 'file':
            post_data[field] = form.getvalue(field)

    # print(post_data)
    try:
        fileitem = form['file']
        if fileitem.filename:
            fn = os.path.basename(fileitem.filename)
            open('./tmp/' + fn, 'wb').write(fileitem.file.read())
            data_files = {'file' : open('./tmp/' + fn, 'rb')}
        # print(data_files)
        r = requests.post(_POST_URL, data = post_data, files = data_files)
    except:
        r = requests.post(_POST_URL, data = post_data)
    
    res = r.text

    try:
        data_files = None
        os.remove('./tmp/' + fn)
    except:
        pass
    self._set_headers()
    self.wfile.write(res.encode('utf-8'))

This code is working for me, I don't know if there is a better way to do that!