0

I am trying to create a demo webserver that returns a TwiML Say block with custom text inside it based on parameters provided with the URL (Yes, POSTing would be better, but I'm not quite sure how to do that). It would work a lot like https://www.twilio.com/labs/twimlets/message except I want to write my own code so I can add more customizations.

I have started by building off of the Weather by Phone demo because it contains customized text inside of xml.

I have created my own google appengine called gracklevoice, and I got the weatherbyphone example working. Now, I'm having trouble when I try to simplify it. My code looks like this:

import os
import wsgiref.handlers

from google.appengine.ext.webapp import template
from google.appengine.ext import webapp

BASE_URL = "http://gracklevoice.appspot.com/"


def xml_response(handler, page, templatevalues=None):
    """                                                                                          
    Renders an XML response using a provided template page and values                            
    """
    path = os.path.join(os.path.dirname(__file__), page)
    handler.response.headers["Content-Type"] = "text/xml"
    handler.response.out.write(template.render(path, templatevalues))

class GracklePage(webapp.RequestHandler):

    def get(self):
        self.post()

    def post(self):
        xml_response(self, 'notification.xml')

def main():
    application = webapp.WSGIApplication([ \
        ('/', GracklePage)],
        debug=True)
    wsgiref.handlers.CGIHandler().run(application)

if __name__ == "__main__":
    main()

There is the yaml file too:

application: gracklevoice
version: 1
runtime: python27
api_version: 1
threadsafe: no

handlers:
- url: /.*
  script: gracklevoice.py

And notification.xml

<?xml version="1.0" encoding="UTF-8"?>
<Response>
     <Say voice="alice" language="en-US">                                                             
     This is a message from Grackle.                                                                  
     </Say>
</Response>

This seems it should be really simple, but when my client app sets the call url to http://gracklevoice.appspot.com/ I get an error instead of the voice message: "We are sorry. an application error has occurred. Goodbye." What am I missing?

Looking in the appEngine logs (which are limited in length, welp), I see:

2013-11-18 14:45:09.781
Traceback (most recent call last):
E 2013-11-18 14:45:09.781
  File "/base/data/home/runtimes/python27/python27_dist/lib/python2.7/wsgiref/handlers.py", line 86, in run
E 2013-11-18 14:45:09.781
    self.finish_response()
E 2013-11-18 14:45:09.781
  File "/base/data/home/runtimes/python27/python27_dist/lib/python2.7/wsgiref/handlers.py", line 128, in finish_response
E 2013-11-18 14:45:09.781
    self.write(data)
E 2013-11-18 14:45:09.781
  File "/base/data/home/runtimes/python27/python27_dist/lib/python2.7/wsgiref/handlers.py", line 204, in write
E 2013-11-18 14:45:09.781
    assert type(data) is StringType,"write() argument must be string"
E 2013-11-18 14:45:09.781
AssertionError: write() argument must be string
Ann Kilzer
  • 1,266
  • 3
  • 16
  • 39
  • It works if I change runtime to 'python', but python2.5 is deprecated in appEngine. This is not how I want to solve this. – Ann Kilzer Nov 18 '13 at 22:58
  • 1
    Have you checked twilio's logs? They're not length constrained – g3rv4 Nov 19 '13 at 13:10
  • The twilio logs show the following: `Status: 500 Internal Server Error Content-Type: text/plain Content-Length: 59 A server error occurred. Please contact the administrator.` – Ann Kilzer Nov 19 '13 at 21:43
  • That seems to be the response that your server is returning... You can probably emulate the request twilio did using fiddler and debug on the server. But that's the reason of why twilio is giving you that message, because it receives that response from your application – g3rv4 Nov 19 '13 at 21:51
  • Right, it's just frustrating appEngine doesn't give the full trace. I'll see how fiddler works on my mac... – Ann Kilzer Nov 19 '13 at 23:50
  • I also tried replacing webapp with webapp2 because that's supposed to work with python2.7. No dice. Right now I have my demo working in python2.5 with webapp. – Ann Kilzer Nov 19 '13 at 23:51
  • Hi Ann, Any luck here? I believe we chatted in IRC a couple of days ago... – Kevin Burke Nov 20 '13 at 17:00
  • I haven't figured it out yet, but I have a demo app working in python2.5. – Ann Kilzer Nov 21 '13 at 17:52

1 Answers1

0

Twilio Developer Evangelist here. Cast the output of template.render(path, templatevalues) with the unicode() function. Your new line of code will end up as

handler.response.out.write(unicode(template.render(path, templatevalues)))

The output of the template.render function is a StringType, instead of a str type, which is what the write function needs. Casting with the unicode function converts the output to the input format you require.

There is additional information in this question about issues with StringType and unicode.

Community
  • 1
  • 1
Matt
  • 111
  • 1
  • 4