Search code examples
pythonwsgi

How do I get the contents of the WSGI `environ` dictionary?


I'm just expanding on the WSGI def application... example that you can find anywhere. So far, I haven't figured out how to return the contents of the environ dictionary.

#import json

def application(environ, start_response):
  status = '200 OK'

  # The output must be a "sequence of byte string values," not a
  # string. See https://www.python.org/dev/peps/pep-3333/#a-note-on-string-types
  # and https://diveintopython3.net/strings.html#byte-arrays
  #output = b'Hello World!'          # Success!
  #output = str(environ)             # Nope
  #output = bytes(environ)           # Nope
  #output = bytes(str(environ))      # Nope
  #output = b'str(environ)'          # Nope, but eye-rollingly funny
  #
  #jsonEnviron = json.dumps(environ) # Nope - error says environ is of
  #output = bytes(jsonEnviron)       # Nope - type 'TextIOWrapper'

  response_headers = [('Content-type', 'text/plain'),
                      ('Content-Length', str(len(output))),
                      ('X-Clacks-Overhead', 'GNU Terry Pratchett')]

  start_response(status, response_headers)

  return [output]

If the solution is out there, my Duck Duck Go searches aren't finding it.


Solution

  • After playing with @AKX's answer for a while, I went to look for a way to get debug output of POST data and came across this page. That pretty much handled everything, with pretty printing thrown in for free! So, here's my final server test/debug script:

    from json import dumps
    from os import path
    from pprint import pformat
    from urllib import parse
    
    def application(environ, start_response):
      status = '200 OK'
    
      # show the environment:
      output = [b'<pre>']
      output.append(pformat(environ).encode('utf-8'))
    
      output.append(b'\n\nPATH_INFO: ' + environ['PATH_INFO'].encode('utf-8'))
      filepath, filename = path.split(environ['PATH_INFO'])
      filebase, fileext = path.splitext(filename)
      output.append(b'\nPath = ' + filepath.encode('utf-8'))
      output.append(b'\nFile = ' + filename.encode('utf-8'))
      output.append(b'\nFile Base = ' + filebase.encode('utf-8'))
      output.append(b'\nFile Ext = ' + fileext.encode('utf-8'))
    
      output.append(b'\n\nQUERY_STRING is\n' + environ['QUERY_STRING'].encode('utf-8'))
      queryDict = parse.parse_qs(environ['QUERY_STRING'])
      output.append(b'\n\nQUERY_STRING as a dict:\n')
      output.append(dumps(queryDict, sort_keys=True, indent=2).encode('utf-8'))
    
      output.append(b'</pre>')
    
      #create a simple form:
      output.append(b'\n\n<form method="post">')
      output.append(b'<input type="text" name="test">')
      output.append(b'<input type="submit">')
      output.append(b'</form>')
    
      if environ['REQUEST_METHOD'] == 'POST':
        # show form data as received by POST:
        output.append(b'\n\n<h1>FORM DATA</h1>')
        output.append(b'\n<pre>')
        output.append(pformat(environ['wsgi.input'].read()).encode('utf-8'))
        output.append(b'</pre>')
    
      # send results
      output_len = sum(len(line) for line in output)
    
      response_headers = [('Content-type', 'text/html'),
                          ('Content-Length', str(output_len)),
                          ('X-Clacks-Overhead', 'GNU Terry Pratchett')]
    
      start_response(status, response_headers)
    
      return output