File: util_http.py

package info (click to toggle)
displaycal-py3 3.9.16-1
  • links: PTS
  • area: main
  • in suites: forky, sid, trixie
  • size: 29,120 kB
  • sloc: python: 115,777; javascript: 11,540; xml: 598; sh: 257; makefile: 173
file content (78 lines) | stat: -rw-r--r-- 2,638 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# -*- coding: utf-8 -*-

# http://code.activestate.com/recipes/146306-http-client-to-post-using-multipartform-data/

import http.client
import mimetypes
import uuid


def post_multipart(host, selector, fields, files, charset="UTF-8"):
    """Post fields and files to an http host as multipart/form-data.
    fields is a sequence of (name, value) elements for regular form fields.
    files is a sequence of (name, filename, value) elements for data to be uploaded as files
    Return the server's response page.
    """
    content_type, body = encode_multipart_formdata(fields, files, charset)
    h = http.client.HTTPConnection(host)
    h.putrequest("POST", selector)
    h.putheader("Content-Type", content_type)
    h.putheader("Content-Length", str(len(body)))
    h.endheaders()
    h.send(body)
    resp = h.getresponse()
    return resp.read()


def encode_multipart_formdata(fields, files, charset="UTF-8"):
    """fields is a sequence of (name, value) elements for regular form fields.
    files is a sequence of (name, filename, value) elements for data to be uploaded as files
    Return (content_type, body) ready for httplib.HTTP instance
    """
    BOUNDARY = b"----=_NextPart_" + uuid.uuid1().bytes
    CRLF = b"\r\n"
    L = []
    for key, value in fields:
        if isinstance(key, str):
            key = key.encode(charset)
        if isinstance(value, str):
            value = value.encode(charset)

        L.append(b"--" + BOUNDARY)
        L.append(b'Content-Disposition: form-data; name="' + key + b'"')
        L.append(b"Content-Type: text/plain; charset=" + charset.encode(charset))
        L.append(b"")
        L.append(value)

    for key, filename, value in files:
        if isinstance(key, str):
            key = key.encode(charset)
        if isinstance(filename, str):
            filename = filename.encode(charset)
        if isinstance(value, str):
            value = value.encode(charset)

        L.append(b"--" + BOUNDARY)
        L.append(
            b'Content-Disposition: form-data; name="'
            + key
            + b'"; filename="'
            + filename
            + b'"'
        )
        L.append(b"Content-Type: " + get_content_type(filename).encode(charset))
        L.append(b"")
        L.append(value)

    L.append(b"--" + BOUNDARY + b"--")
    L.append(b"")
    body = CRLF.join(L)
    content_type = b"multipart/form-data; boundary=" + BOUNDARY

    return content_type, body


def get_content_type(filename):
    if isinstance(filename, bytes):
        filename = filename.decode("utf-8")
    return mimetypes.guess_type(filename)[0] or "application/octet-stream"