Repository: certbot/certbot

Issue:
HTTP responses logged as hard-to-read bytes repr in Python 3
If you're having trouble using Certbot and aren't sure you've found a bug or
request for a new feature, please first try asking for help at
https://community.letsencrypt.org/. There is a much larger community there of
people familiar with the project who will be able to more quickly answer your
questions.

## My operating system is (include version):
Ubuntu 16.04 (x86-64)

## I installed Certbot with (certbot-auto, OS package manager, pip, etc):
certbot-auto (Python 2) and the PPA (0.22.2, Python 3) on different systems.

## I ran this command and it produced this output:


## Certbot's behavior differed from what I expected because:
Under Python 2, Certbot logs HTTP responses as easy-to-read text, e.g.:

    2018-05-02 13:41:58,328:DEBUG:acme.client:Received response:
    HTTP 200
    Server: nginx
    Content-Type: application/json
    Content-Length: 724
    X-Frame-Options: DENY
    Strict-Transport-Security: max-age=604800
    Expires: Wed, 02 May 2018 13:41:58 GMT
    Cache-Control: max-age=0, no-cache, no-store
    Pragma: no-cache
    Date: Wed, 02 May 2018 13:41:58 GMT
    Connection: keep-alive

    {
      "6ELa2lV28v0": "https://community.letsencrypt.org/t/adding-random-entries-to-the-directory/33417",
      "keyChange": "https://acme-staging-v02.api.letsencrypt.org/acme/key-change",
      "meta": {
        "caaIdentities": [
          "letsencrypt.org"
        ],
        "termsOfService": "https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf",
        "website": "https://letsencrypt.org/docs/staging-environment/"
      },
      "newAccount": "https://acme-staging-v02.api.letsencrypt.org/acme/new-acct",
      "newNonce": "https://acme-staging-v02.api.letsencrypt.org/acme/new-nonce",
      "newOrder": "https://acme-staging-v02.api.letsencrypt.org/acme/new-order",
      "revokeCert": "https://acme-staging-v02.api.letsencrypt.org/acme/revoke-cert"
    }

Under Python 3, it logs the `repr()` of the bytes:

    2018-05-02 13:44:24,936:DEBUG:acme.client:Received response:
    HTTP 200
    Server: nginx
    Content-Type: application/json
    Content-Length: 724
    X-Frame-Options: DENY
    Strict-Transport-Security: max-age=604800
    Expires: Wed, 02 May 2018 13:44:24 GMT
    Cache-Control: max-age=0, no-cache, no-store
    Pragma: no-cache
    Date: Wed, 02 May 2018 13:44:24 GMT
    Connection: keep-alive
    
    b'{\n  "keyChange": "https://acme-staging-v02.api.letsencrypt.org/acme/key-change",\n  "meta": {\n    "caaIdentities": [\n      "letsencrypt.org"\n    ],\n    "termsOfService": "https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf",\n    "website": "https://letsencrypt.org/docs/staging-environment/"\n  },\n  "newAccount": "https://acme-staging-v02.api.letsencrypt.org/acme/new-acct",\n  "newNonce": "https://acme-staging-v02.api.letsencrypt.org/acme/new-nonce",\n  "newOrder": "https://acme-staging-v02.api.letsencrypt.org/acme/new-order",\n  "revokeCert": "https://acme-staging-v02.api.letsencrypt.org/acme/revoke-cert",\n  "uog1GW6DtvQ": "https://community.letsencrypt.org/t/adding-random-entries-to-the-directory/33417"\n}'

It makes log files more difficult to read.

Ideally Certbot would try to decode the HTTP response and log it normally. (Or perhaps dump the raw bytes straight to the log file.)

This affects JSON responses and certificates, but a certificate's worth of base64 isn't human readable anyway.

## Here is a Certbot log showing the issue (if available):
###### Logs are stored in `/var/log/letsencrypt` by default. Feel free to redact domains, e-mail and IP addresses as you see fit.

## Here is the relevant nginx server block or Apache virtualhost for the domain I am configuring:


Discussion:
@bmw this looks like it might be a good first issue for someone to tackle at Pycon?
@bmw @jgillula  Hi can i work on this issue if not one is assigned/working on ?

@R3DDY97, please do!

Resolving patch:
diff --git a/acme/acme/client.py b/acme/acme/client.py
--- a/acme/acme/client.py
+++ b/acme/acme/client.py
@@ -1018,7 +1018,7 @@ def _send_request(self, method, url, *args, **kwargs):
         if response.headers.get("Content-Type") == DER_CONTENT_TYPE:
             debug_content = base64.b64encode(response.content)
         else:
-            debug_content = response.content
+            debug_content = response.content.decode("utf-8")
         logger.debug('Received response:\nHTTP %d\n%s\n\n%s',
                      response.status_code,
                      "\n".join(["{0}: {1}".format(k, v)


Test patch: