You’re building a Vapor app and want to be able to respond to SMS messages? Let’s walk through how to add Twilio SMS to the barebones Vapor “Hello World” app.
Swift Package Manager
For this project we’re going to use Swift Package Manager to set everything up and install dependencies. Make sure you have Swift 4.0 or greater installed before moving on. You can check your Swift version by running the following in your terminal:
swift --version
Vapor has a convenient command line tool which can be used to generate templates for projects. Installing this will also take care of other necessary dependencies.
You can install it using Homebrew with the following command:
brew tap vapor/homebrew-tap brew install vapor
Now initiate a new Swift project with the following terminal command in the directory where you want your code to live:
swift package init --type executable
This will generate a directory structure for your Swift project. By default it will name your project after the directory you ran the previous command in. My project was named Hello
, so you may need to replace that in any of the commands or code further in this post that refer to your Swift project.
Next let’s get our dependencies set up. Open the file Package.swift
and add the Vapor package to the code Swift Package Manager generated. My Package.swift
looks like this:
// swift-tools-version:4.0 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription let package = Package( name: "Hello", dependencies: [ // Dependencies declare other packages that this package depends on. // .package(url: /* package url */, from: "1.0.0"), .package(url: "https://github.com/vapor/vapor.git", from: "3.0.0-rc") ], targets: [ // Targets are the basic building blocks of a package. A target can define a module or a test suite. // Targets can depend on other targets in this package, and on products in packages which this package depends on. .target( name: "Hello", dependencies: ["Vapor"]), ] )
Getting started with Vapor
We’re now ready to move on to writing some Swift code. From the base directory of your project, open the file Sources/Hello/main.swift
and add the following code to it:
import Vapor let app = try Application() let router = try app.make(Router.self) router.get("/") { req in return "Hello, world." } try app.run()
This is the bare bones “Hello World” Vapor application. It has one route that takes a GET
request and responds with a simple string. With your Package.swift
configured and your Vapor code written, run the following commands in the terminal to build and run the project:
swift build ./.build/debug/Hello
This will install Vapor and all of its dependencies and will run your web application. Once it is running, visit http://localhost:8080/ to see a basic “Hello World” webpage.
Setting up your Twilio account
Before being able to respond to messages, you’ll need a Twilio phone number. You can buy a phone number here (you can get one for free).
Your Vapor app will need to be visible from the Internet in order for Twilio to send requests to it. We will use ngrok for this, which you’ll need to install if you don’t have it. In your terminal run the following command:
ngrok http 8080
If you’ve just installed ngrok and that previous command didn’t work, you might have to run it like ./ngrok http 8080
from the directory that the ngrok executable is in.
This provides us with a publicly accessible URL to the Vapor application. Configure your phone number as seen in this image by adding your ngrok URL with /sms
appended to it to the “Messaging” section:
You are now ready to receive a text message to your new Twilio number.
Adding SMS to your Vapor app
Now that you have a Twilio number you want to allow users to send a text message to it and get a response. The next step is to handle the POST
request Twilio will send when your number receives a text.
We only need one route on this app: /sms
to handle incoming text messages. Let’s add another route. Replace all of the code in main.swift
with the following:
import Vapor let app = try Application() let router = try app.make(Router.self) router.post("sms") { req -> HTTPResponse in // Declare a multi-line string literal of some TwiML to respond with. let twiml = """ <?xml version="1.0" encoding="UTF-8"?> <Response> <Message> <Body>Check out this cool programmatically sent text message!</Body> </Message> </Response> """ // Create an HTTP Response with the twiml as the body. var response = HTTPResponse(status: .ok, body: twiml) response.contentType = .xml return response } try app.run()
In the new sms
route we’re creating a string for the TwiML, and then putting it in an HTTPResponse
object with a content type of XML. The Body
tag in the XML string contains the text of the message we are responding with.
Build and run your server code again and try sending a message to your Twilio number!
What just happened?
With Vapor running on port 8080, sitting behind a public ngrok URL, Twilio can see your application. Upon receiving a text message:
-
Twilio will send a POST request to
/sms
. - The function associated with the
sms
route will be called. - This function responds to Twilio’s request with TwiML telling Twilio to send a message back in response.
If you have any questions or other cool ideas, feel free to reach out and let me know:
- Email: Sagnew@twilio.com
- Twitter: @Sagnewshreds
- Github: Sagnew
- Twitch (streaming live code): Sagnewshreds
Receiving and Responding to Text Messages with Server Side Swift, Vapor and Twilio