sigil
sigil

Reputation: 9546

Getting Heroku H12 timeout request when I try to make an outbound call with Twilio

My goal is to have Twilio make a call in response to an SMS, and speak the contents of the SMS. Here's my code:

const express = require('express');
const app=express();
const VoiceResponse=require('twilio').twiml.VoiceResponse;
//const MessagingResponse=require('twilio').twiml.MessagingResponse;
const bodyParser = require('body-parser');
const client=require('twilio')(
    process.env.TWILIO_ACCOUNT_SID,
    process.env.TWILIO_AUTH_TOKEN
);

var https=require("https");

app.use(bodyParser.urlencoded({extended: false}));

const port=process.env.PORT;
app.listen(port,()=>{
    console.log('live on port '+port);
});

app.get('/',function(req,res){
    res.send('this is the homepage GET response');
    var url=textforspeechURL("abcde");
    https.get(url,res=>{
      res.on('data', (chunk) => {
        console.log(`BODY: ${chunk}`);
      });
    });
    //res.end();
});

function textforspeechURL(textforspeech){
    return "https://myapp.herokuapp.com/getVoiceTwiml?textforspeech="+encodeURIComponent(textforspeech);
}       


app.post('/sms',(req,res)=>{
    var body=req.body.Body;
    var fromObj=req.body.From;
    var toObj=req.body.To;
    url=textforspeechURL(body);
    console.log("url to send: "+url);
    client.calls.create({
        url:url,
        to: toObj,
        from: fromObj,
        method: 'GET'
    });
});

app.get('/getVoiceTwiml',(req,res)=>{
    const response=new VoiceResponse();
    response.say(req.query.textforspeech);
    responseTwiml=response.toString();
    console.log("responseTwiml: "+responseTwiml);
    res.send(responseTwiml);
});

When I go to the app's homepage, the console displays:

app[web.1]: BODY: <?xml version="1.0" encoding="UTF-8"?><Response><Say>abcde</Say></Response>

so /getVoiceTwiml is executing as expected. But when I send an SMS to the app's Twilio number, the console displays:

app[web.1]: url to send: https://myapp.herokuapp.com/getVoiceTwiml?textforspeech=some%20text2018-01-07T21:21:09.875589+00:00 

heroku[router]: at=error code=H12 desc="Request timeout" method=POST path="/sms/" host=myapp.herokuapp.com request_id=ac8176bb-3a1f-4752-9685-1cd8e017fdce fwd="54.208.34.131" dyno=web.1 connect=1ms service=30000ms status=503 bytes=0 protocol=https

So in the /sms endpoint, it's successfully constructing the URL, but the client.calls.create() call is timing out. What's wrong with how I'm creating the call?

Upvotes: 0

Views: 334

Answers (3)

philnash
philnash

Reputation: 73057

Twilio developer evangelist here.

I'm glad you discovered your problem with the To and From numbers. Perhaps I can give some further guidance so that this sort of problem won't be discovered through H12 request timeouts though.

The issue is that your /sms endpoint never made a response to the incoming request, so Node just hung there waiting, eventually timing out.

Since you're not responding to the SMS with another message, you can just respond with an empty <Response> TwiML. You probably also want to log or throw an error if something goes wrong. You can update your /sms endpoint to something like this instead:

app.post('/sms',(req,res)=>{
  var body=req.body.Body;
  var fromObj=req.body.From;
  var toObj=req.body.To;
  url=textforspeechURL(body);
  console.log("url to send: "+url);
  client.calls.create({
    url:url,
    to: toObj,
    from: fromObj,
    method: 'GET'
  }, (err, apiResponse) => {
    if (err) { console.error("There was an error making the call: ", err); }
    res.set('Content-Type', 'application/xml');
    res.send('<Response/>')
  });
});

This will always respond with an empty <Response> and let Twilio know that you got the message successfully. If there is an error in making the call, that will be logged too.

Upvotes: 1

sigil
sigil

Reputation: 9546

The problem was that I was using a From number that was the number from the inbound SMS, and my Twilio number as the To number. Reversing them resolved the problem.

Upvotes: 0

pdoherty926
pdoherty926

Reputation: 10359

From Heroku's Error code documentation:

H12 - Request timeout

An HTTP request took longer than 30 seconds to complete.

Your incoming request is taking longer than the allotted 30 seconds because of the outbound call to Twilio, which will take an indeterminate amount of time.

One way to rectify this would be to create a worker dyno and use something like node-resque to create/schedule the task.

So, the request comes in, you create/schedule a background job, return any relevant information to the caller (e.g. a job id which would allow them to check on the status of their "request") and the job is then processed "in the background" without any time constraints.

Upvotes: 0

Related Questions