File: curl.py

package info (click to toggle)
nsscache 0.49-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 19,664 kB
  • sloc: python: 8,661; xml: 584; sh: 304; makefile: 19
file content (100 lines) | stat: -rw-r--r-- 2,816 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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# Copyright 2010 Google Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
"""Minor curl methods."""

__author__ = "blaedd@google.com (David MacKinnon)"

import logging
import pycurl
from io import BytesIO

from nss_cache import error


def CurlFetch(url, conn=None, logger=None):
    if not logger:
        logger = logging

    if not conn:
        conn = pycurl.Curl()

    conn.setopt(pycurl.URL, url)
    conn.body = BytesIO()
    conn.headers = BytesIO()
    conn.setopt(pycurl.WRITEFUNCTION, conn.body.write)
    conn.setopt(pycurl.HEADERFUNCTION, conn.headers.write)
    try:
        conn.perform()
    except pycurl.error as e:
        HandleCurlError(e, logger)
        raise error.Error(e)
    resp_code = conn.getinfo(pycurl.RESPONSE_CODE)
    return (resp_code, conn.headers.getvalue().decode("utf-8"), conn.body.getvalue())


def HandleCurlError(e, logger=None):
    """Handle a curl exception.

    See http://curl.haxx.se/libcurl/c/libcurl-errors.html for a list of codes.

    Args:
      e: pycurl.error
      logger: logger object

    Raises:
      ConfigurationError:
      PermissionDenied:
      SourceUnavailable:
      Error:
    """
    if not logger:
        logger = logging

    code = e.args[0]
    msg = e.args[1]

    # Config errors
    if code in (
        pycurl.E_UNSUPPORTED_PROTOCOL,
        pycurl.E_URL_MALFORMAT,
        pycurl.E_SSL_ENGINE_NOTFOUND,
        pycurl.E_SSL_ENGINE_SETFAILED,
        pycurl.E_SSL_CACERT_BADFILE,
    ):
        raise error.ConfigurationError(msg)

    # Possibly transient errors, try again
    if code in (
        pycurl.E_FAILED_INIT,
        pycurl.E_COULDNT_CONNECT,
        pycurl.E_PARTIAL_FILE,
        pycurl.E_WRITE_ERROR,
        pycurl.E_READ_ERROR,
        pycurl.E_OPERATION_TIMEOUTED,
        pycurl.E_SSL_CONNECT_ERROR,
        pycurl.E_COULDNT_RESOLVE_PROXY,
        pycurl.E_COULDNT_RESOLVE_HOST,
        pycurl.E_GOT_NOTHING,
    ):
        logger.debug("Possibly transient error: %s", msg)
        return

    # SSL issues
    if code in (pycurl.E_SSL_PEER_CERTIFICATE,):
        raise error.SourceUnavailable(msg)

    # Anything else
    raise error.Error(msg)