diff -r 7fe960f1a101 Lib/http/client.py --- a/Lib/http/client.py Fri Jan 08 01:01:56 2016 -0800 +++ b/Lib/http/client.py Fri Jan 08 08:37:42 2016 -0800 @@ -146,6 +146,21 @@ _METHODS_EXPECTING_BODY = {'PATCH', 'POST', 'PUT'} +def _encode(data, encoding, name='data'): + """Call data.encode(encoding) but show a better error message.""" + try: + return data.encode(encoding) + except UnicodeEncodeError as err: + raise UnicodeEncodeError( + err.encoding, + err.object, + err.start, + err.end, + "%s (%.20r) is not valid Latin-1. Use %s.encode('utf-8') " + "if you want to send it encoded in UTF-8." % + (name.title(), data[err.start:err.end], name)) from None + + class HTTPMessage(email.message.Message): # XXX The only usage of this method is in # http.server.CGIHTTPRequestHandler. Maybe move the code there so @@ -796,7 +811,7 @@ self.send(connect_bytes) for header, value in self._tunnel_headers.items(): header_str = "%s: %s\r\n" % (header, value) - header_bytes = header_str.encode("latin-1") + header_bytes = _encode(header_str, "latin-1", 'header') self.send(header_bytes) self.send(b'\r\n') @@ -878,7 +893,7 @@ if not datablock: break if encode: - datablock = datablock.encode("iso-8859-1") + datablock = _encode(datablock, "iso-8859-1") self.sock.sendall(datablock) return try: @@ -1044,7 +1059,7 @@ raise CannotSendHeader() if hasattr(header, 'encode'): - header = header.encode('ascii') + header = _encode(header, 'ascii', 'header') if not _is_legal_header_name(header): raise ValueError('Invalid header name %r' % (header,)) @@ -1052,7 +1067,7 @@ values = list(values) for i, one_value in enumerate(values): if hasattr(one_value, 'encode'): - values[i] = one_value.encode('latin-1') + values[i] = _encode(one_value, 'latin-1', 'value') elif isinstance(one_value, int): values[i] = str(one_value).encode('ascii') @@ -1124,7 +1139,7 @@ if isinstance(body, str): # RFC 2616 Section 3.7.1 says that text default has a # default charset of iso-8859-1. - body = body.encode('iso-8859-1') + body = _encode(body, 'iso-8859-1', 'body') self.endheaders(body) def getresponse(self):