How to Provide Number Lookup Information
Warning: Beta software This API is in beta stage and may be subject to change. Therefore, we do not recommend using this in production.
Interested in this feature? Please reach out to mobility-services-developer@cisco.com
This guide will show you how to become a Number Lookup Provider.
You should have an understanding of how this works before continuing, see How Does Number Lookup Work?.
Prerequisites
Required Scope
lookup.number:read
Limitations
Limitations for display name
The display name returned must be max 60 characters, and may only contain the following:
- alphanumeric (
a-z
,A-Z
,0-9
) -
,_
.
,!
,%
,*
,'
,+
,~
,`
Characters not matching the above will be stripped.
Code Dependencies
<dependency>
<groupId>com.wgtwo.api.v0.grpc</groupId>
<artifactId>lookup</artifactId>
<version>0.3.0</version>
</dependency>
Code
#!/usr/bin/env bash
# We send data to grpcurl via a PIPE, and receive data via stdout.
PIPE="/tmp/provider-PIPE-$RANDOM"
mkfifo $PIPE
exec 3<> $PIPE
cleanup() {
echo "Cleaning up..."
rm -f $PIPE
exec 3>&-
exit
}
trap cleanup INT TERM EXIT
grpcurl \
-d @ \
sandbox.api.shamrock.wgtwo.com:443 \
wgtwo.lookup.v0.NumberLookupService/NumberLookup <&3 \
| while IFS= read -r LINE; do
# grpcurl sends output line by line, so we buffer until we have a valid JSON object.
BUFFER+="$LINE"
if ! jq . >/dev/null 2>&1 <<<"$BUFFER"; then continue; fi
# Create a JSON response that includes the request and a dummy result.
RESPONSE_JSON=$(jq -c -n --argjson incoming_content "$BUFFER" \
'{
number_lookup_request: $incoming_content,
result: {
name: "John Doe"
}
}'
)
# Send the response to grpcurl via the PIPE.
echo "$RESPONSE_JSON" > $PIPE
echo "Sent response:"
echo "$RESPONSE_JSON" | jq .
echo ""
# Clear the buffer.
BUFFER=""
done
package com.example.numberlookup
import com.google.protobuf.util.Durations
import com.wgtwo.api.v0.lookup.NumberLookupProto.NumberLookupRequest
import com.wgtwo.api.v0.lookup.NumberLookupProto.NumberLookupResponse
import com.wgtwo.api.v0.lookup.NumberLookupServiceGrpcKt
import com.wgtwo.api.v0.lookup.cacheControl
import com.wgtwo.api.v0.lookup.numberLookupResponse
import com.wgtwo.api.v0.lookup.result
import io.grpc.ManagedChannelBuilder
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.runBlocking
import java.util.concurrent.TimeUnit
import kotlin.time.Duration.Companion.seconds
suspend fun startStream() {
val grpcChannel = ManagedChannelBuilder.forTarget("sandbox.api.shamrock.wgtwo.com:443")
.keepAliveWithoutCalls(true)
.keepAliveTime(1, TimeUnit.MINUTES)
.keepAliveTimeout(10, TimeUnit.SECONDS)
.idleTimeout(1, TimeUnit.HOURS)
.build()
val stub = NumberLookupServiceGrpcKt.NumberLookupServiceCoroutineStub(grpcChannel)
val phonebook = mapOf(
"+4799999999" to "John Doe",
"+4799990000" to "Jane Doe",
"+4799990001" to "Alice Doe",
"+4799990002" to "Bob Doe",
)
val responseQueue = Channel<NumberLookupResponse>()
// Check queue to see if we have any responses and send them over the wire
val responseFlow = flow {
for (response in responseQueue) {
emit(response)
}
}
stub.numberLookup(responseFlow)
.onStart { println("Starting new stream") }
.onEach { request: NumberLookupRequest ->
println("Got request for ${request.number.e164}")
val displayName = phonebook[request.number.e164] ?: ""
val response = numberLookupResponse {
numberLookupRequest = request
result = result {
name = displayName
}
cacheControl = cacheControl {
maxAge = Durations.fromMinutes(60)
}
}
println("Sending response for ${response.numberLookupRequest.number.e164}: \"${response.result.name}\"")
responseQueue.send(response)
}
.catch { e ->
println("Got error: ${e.message} - Will reconnect in 1s")
delay(1.seconds)
}
.collect()
}
fun main() = runBlocking {
// Run forever - if the stream fails we will reconnect
while (true) {
startStream()
}
}
Example Result
{
"number_lookup_request": {
"id": "c996a774-0c8b-482d-8fe2-880978ff44db",
"number": {
"e164": "+4799990000"
}
},
"result": {
"name": "John Doe"
}
}
Sent response:
{
"number_lookup_request": {
"id": "defdbc17-d2a1-4f85-91f3-1cc2a14a2087",
"number": {
"e164": "+4799990005"
}
},
"result": {
"name": "John Doe"
}
}
Starting new stream
Got request for +4799990005
Sending response for +4799990005: ""
Got request for +4799990000
Sending response for +4799990000: "Jane Doe"
Got request for +4799990001
Sending response for +4799990001: "Alice Doe"
Cache
As part of the response, the provider can include a cache TTL.
This is the time in seconds that the display name should be cached in the core. If not set, a default cache TTL documented in the proto file will be used.
NumberLookupResponse {
number_lookup_request { } # Fields omitted for brevity
result {
name: "John Doe"
}
# Optional, set to default if not set
cache_control {
max_age {
seconds: 3600 # 1 hour, google.protobuf.Duration
}
}
}
Recommended gRPC Connection Settings
Setting | Value | Description |
---|---|---|
keep-alive period | 1 minute | Must be ≥ 1 minute and ≤ 5 minutes |
keep-alive timeout | 10 seconds | |
permit keep-alive without calls | true |
Keep-Alive
The API Gateway hosting api.{region}.wgtwo.com (see environments for a list of regions) will silently drop connections if they have been idle for 350 seconds (5m 50s).
To avoid this, the provider should send a keep-alive message every minute.
Local Testing
For local testing, you can use our sandbox environment hosted at sandbox.api.shamrock.wgtwo.com
.
In addition to that, we do provide a test application that can be used for testing which may be useful to see how your provider behaves under heavy load.
The test application is hosted at github.com/working-group-two/number-lookup-provider-tester.
By setting up a stream to this application, it will send number lookup requests at the configured rate. It will not do any flow control, but show number of in-flight messages (requests sent - responses received).
Docker
The test application is also available as a pre-built docker image. Usage:
docker run --network=host ghcr.io/working-group-two/number-lookup-provider-tester:latest \
--address :8118 \
--rps 5 \
--numbers 4799990001,4799990002,4799990003 \
--print-progress \
--print-requests \
--print-responses