title: Node Express API not accepting DELETE requests
body: <p>I've been on this for a while now, and I just can't understand it.</p>
  
  <p>Consider the following route:</p>
  
  <pre><code>app.delete('/users/:id', function(req, res) {
      console.log("Handling delete request...");
      return res.send(204);
  });
  </code></pre>
  
  <p>When I make a DELETE request it times out. GET, PUT and POST requests are all working fine.</p>
  
  <p>I am using EmberJS with ember-data making the requests via AJAX.</p>
  
  <p>I have tried curl from the terminal:</p>
  
  <pre><code>curl -i -X DELETE http://localhost:9000/users/12345 
  </code></pre>
  
  <p>for which I get the following response:</p>
  
  <pre><code>curl: (56) Recv failure: Operation timed out
  </code></pre>
  
  <p>I have also changed the route to:</p>
  
  <pre><code>app.del('/users/:id', function(req, res){ ... });
  </code></pre>
  
  <p>But express complains that I should be using app.delete...</p>
  
  <p>I have Access-Control-Allow-Methods set like so:</p>
  
  <pre><code>res.header("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE");
  </code></pre>
  
  <p>Any ideas?</p>
  
  <p><strong>UPDATE</strong></p>
  
  <p>Here's the server.js file to give some context:</p>
  
  <pre><code>var config = require("./config"),
      tokens = require("./tokens"),
      bcrypt = require("bcrypt"),
      nodemailer = require("nodemailer"),
      fs = require("fs"),
      zip = require("adm-zip"),
      path = require("path"),
      mongoose = require("mongoose"),
      express = require("express"),
      limit = require("limit"),
      bodyParser = require("body-parser"),
      winston = require("winston"),
      multer = require("multer"),
      img = require('easyimage'),
      app = express();
  
  //set up prerender
  app.use(require('prerender-node').set('prerenderToken', '*****')); // For google spiders
  
  //set up logging
  var logger = new (winston.Logger)({
      transports: [
          new (winston.transports.Console)({
              level: 'info',
              colorize: true,
              handleExceptions: true
          }),
          new (winston.transports.File)({ 
              filename: '../logs/node_api.log',
              colorize: false,
              json: false,
              handleExceptions: true
          })
      ]
  });
  
  //set up mailer
  var smtpTransport = nodemailer.createTransport("SMTP", {
      service: "Gmail",
      auth: {
          user: "*****",
          pass: "*****"
      }
  });
  
  //set up DB connection and pass to routes.
  console.log("connecting to db... ");
  mongoose.connect(config.mongodb.url);
  var db = mongoose.connection;
  
  db.on('error', function(err) {
      logger.error(err);
  });
  
  console.log("dependencies loaded...");
  
  db.on('open', function() {
      console.log("db connection opened...");
      //models...
      var user = require('./models/user')(app, mongoose),
          property = require('./models/property')(app, mongoose),
          viewing = require('./models/viewing')(app, mongoose),
          valuation = require('./models/valuation')(app, mongoose),
          page = require('./models/page')(app, mongoose),
          content_block = require('./models/content_block')(app, mongoose),
          area = require('./models/area')(app, mongoose, user, property);
  
      //routes...
      require('./routes/uploads')(app, img, fs, tokens, logger);
      require('./routes/auth')(app, user, bcrypt, tokens, logger);
      require('./routes/properties')(app, property, user, viewing, fs, tokens, smtpTransport, logger);
      require('./routes/users')(app, user, tokens, bcrypt, smtpTransport, logger);
      require('./routes/valuation')(app, valuation, user, smtpTransport, logger);
      require('./routes/pages')(app, page, tokens, logger);
      require('./routes/areas')(app, area, logger);
      require('./routes/content_blocks')(app, content_block, logger);
  
      //cron
      require('./cron')(property, fs, path, zip, logger);
  
      console.log("routes loaded...");
  
      //TODO: only needed locally
      app.get('/api/uploads/:filename', function(req, res) {
          var path = './uploads/' + req.params.filename;
  
          fs.readFile(path, function(err, data) {
              if(err) {
                  if(err.errno === 34) return res.send(404);
                  else return res.send(500, err);
              }
              return res.sendfile(path);
          });
      });
  
      console.log("static content server implemented...");
  });
  
  //TODO: Clean up tmp folder with BodyParser to avoid server attacks
  app.use(bodyParser({
      uploadDir: '/uploads/',
      keepExtensions: true
  }));
  
  console.log("body-parser started...");
  
  // app.use(limit('5mb'));
  app.all("/*", function(req, res, next) {
      res.header("Access-Control-Allow-Origin", "http://localhost:8000");
      res.header("Access-Control-Allow-Credentials", "true");
      res.header("Access-Control-Allow-Headers", "Cache-Control, Pragma, token, Origin, Accept, Authorization, Content-Type, X-Requested-With");
      res.header("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE");
      return next();
  });
  
  console.log("Access-Control-Allow headers set...");
  
  app.all("/*", function(req, res, next) {
  
      if (req.method.toLowerCase() !== "options") return next();
  
      return res.send(204);
  });
  
  console.log("catch all routes implemented...");
  
  // Setup image uploads without bodyParser
  app.use(multer({
      dest: 'uploads/',
      rename: function (fieldname, filename) {
          return filename.replace(/\W+/g, '-').toLowerCase();
      }
  }));
  
  console.log("multer started...");
  
  app.use(express.static(__dirname + '/static'));
  
  app.use(function(err, req, res, next) {
      if(err) logger.error(err);
  });
  
  app.listen(9000, function (error) {
      if (error) {
          logger.error("Unable to listen for connections", error);
          process.exit(10);
      }
      logger.info("Brik - Express is listening on localhost:9000");
  });
  </code></pre>