Disclaimer
Create an API that accepts SMS messages submitted via a POST request containing a JSON object as request body.
- Example:
{
"recipient": 31612345678,
"originator":"MessageBird",
"message":"This is a test message."
}
- Send the received message to the MessageBird REST API using one of our REST API libraries: https://github.com/messagebird/
- When an incoming message content/body is longer than 160 chars, split it into multiple parts (known as concatenated SMS)
- Make sure no empty or incorrect parameter values are send to MessageBird (input validation)
- The (theoretical/imaginary) throughput to MessageBird is one API request per second. Make sure the outgoing messages won’t exceed that limit, also when multiple incoming requests are received at the API or concatenated messages need to be send.
API
/message
POST Description
Forwards message to MessageBird API
Required
recipient
: valid recipient MSISDN,
originator
: valid originator accordingly to MessageBird documentation (MSISDN or alphanumeric value not longer than 11 symbols),
message
: message content
Response
200
Success Returns the submitted object as a confirmation for valid message
Example
{
"recipient": 31612345678,
"originator":"MessageBird",
"message":"This is a test message."
}
422
Unprocessable entity Returned in case if not valid message was submitted
Example
{
"body": "must have a value",
"originator": "use valid MSISDN or alphanumeric value (max. 11 symbols long)",
"recipient": "should be a valid MSISDN"
}
400
Bad Request Returned in case of invalid JSON submitted
Example
{
"message": "Syntax error: offset=20, error=invalid character '\"' after object key:value pair"
}
How does it work
A - Message is submitted to the project's API, validated, converted, gets generated UDH (if needed), splitted and pushed to the queue. Splitted up to 9 parts - rest of the message is discarded and not sent (taken from MessageBird documentation, however GSM documentation says there could be up to 255 parts with low probability of having them all delivered). Depending on the encoding, messages have different limit and it splits using next rules:
-
plain encoding (message contains only symbols from GSM 03.38 table):
- First message is 160 symbols (some special symbols are counted as 2 symbols. Read more: https://en.wikipedia.org/wiki/GSM_03.38).
- If message is longer than 160 symbols then it would be splitted by 153 symbols parts. 1 part - 1 SMS
-
unicode encoding (symbols not only from GSM 03.38 table):
- First message is 70 symbols
- If message is longer than 70 symbols it would be splitted by 67 symbols parts. 1 part - 1 SMS (for some reason splitting doesn't work for MessageBird API)
B - Queue retrieves the collection (cart) of pushed messages. Meanwhile queue is not locked but working collection is replaced with new collection on a fly every 1 second if needed (working cart is not empty). The retrieved collection is analyzed for identical messages but with different recipients so we could send more messages at once. Identical messages with the same recipient are considered to be the same message submitted twice so it's need to be delivered twice.
It is easier to imagine as pipe from which message items are falling and you're just swaping the carts on a fly every second, so pipe is not blocked. The reason why this approach is taken instead of working with regular channels is quite simple: channels are actually quite slow comparing to regular arrays. Check out source code for more details.
C - The message with the biggest amount of recipients would be sent first. The rest of the messages are sent back to the queue. If an error was returned by MessageBird API - the message is also sent back to the queue.
Development
Please, do not put the project into the $GOPATH/src/github.com/kostkobv/birdfeeder
. Use GVM to control your package sets and put the project straight into the $GOPATH/src
of your package set.
You can find more information about installing and configuring GVM below.
Step 1: Install GVM
First install GVM
bash < <(curl -s -S -L https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)
Or if you are using zsh
just change bash
with zsh
The project is based on Go 1.9.1
gvm install go1.9.1
If you're getting an error with installing the Go version try to use --binary
flag
gvm install go1.9.1 --binary
Checkout to the required version
gvm use go1.9.1 --default
Step 2: Utilities
Dependencies are represented by Glide package manager. Please install it first.
curl https://glide.sh/get | sh
You would also need to install linter (optional).
go get -u gopkg.in/alecthomas/gometalinter.v1
Then install linters itself
gometalinter.v1 --install
To run linter
make lint
Please notice that CI build would fail if changes wouldn't pass linter
Step 3: GVM pkgset
You need to link project to the pkgset
gvm pkgset create birdfeeder
gvm pkgset use birdfeeder
Now you need to link the project to GOPATH
rm -rf ~/.gvm/pkgsets/go1.9.1/birdfeeder/src
ln -s $PWD ~/.gvm/pkgsets/go1.9.1/birdfeeder/src
Step 4: Vendor
After you can install the vendor dependencies:
glide install
Step 5: Configuration
You need to copy file ./config/settings.go.example
to ./config/settings.go
and place configuration you would like to use.
To run tests
make test
To build binaries
make build