It's common for Bixby capsules to communicate with an external web service to perform actions that can't be completed on the device: fetching the weather report for a given location, getting a list of nearby Italian restaurants, booking a hotel room, and so on. To use web APIs, your JavaScript action implementation (endpoints) can take advantage of Bixby's HTTP library, and can even call them directly as remote endpoints. This small sample capsule, an adaptation of the larger "Shoe Store" simple search sample capsule, demonstrates both the HTTP library and remote endpoints.
Because you cannot submit a capsule with the example
namespace, in order to test a sample capsule on a device, you must change the id
in the capsule.bxb
file from example
to your organization's namespace before making a private submission.
For example, if your namespace is acme
, change example.http
to acme.http
.
Since this capsule demonstrates an HTTP API, it requires an API server to communicate with. The capsule is set up to use a simple Node.js-based server that we have set up for you at AppSpot, so you don't need to run the demonstration server yourself.
The server URL is set as the property remote.url
in the capsule properties file. To use our already set up test server, keep it at the default value (https://bixby-http-demo.appspot.com
).
Note that servers for Bixby remote endpoints must be publicly accessible.
This capsule demonstrates the following API calls. You can enter the training entry as an utternace in the Simulator listed under each section.
Training entry: "Find shoes"
This uses the models/actions/FindShoe.model.bxb
model, whose action is implemented in code/FindShoe.js
:
var http = require('http')
var console = require('console')
var config = require('config')
module.exports.function = function findShoe () {
// Instead of hard coding the URL, you can read the remote.url value
// from capsule.properties, this would look like this
// var response = http.getUrl(config.get('remote.url') + '/shoes', { format: 'json' });
var response = http.getUrl('https://my-json-server.typicode.com/bixbydevelopers/capsule-samples-collection/shoes', { format: 'json' });
console.log ("response = " + response)
return response;
}
This simple function uses http.getUrl()
to call the API at /shoes
.
Training Entry: "Find formal shoes"
This also uses the FindShoe
model described above, but its action is implemented in code/FindShoeFiltering.js
, which is similar to the JavaScript implementation above but adds a type
input which is turned into an HTTP query parameter:
var http = require('http')
var console = require('console')
module.exports.function = function findShoe (type) {
console.log("FindShoe filter by a specific type")
var options = {
format: 'json',
query: {
type: type
}
};
// makes a GET call to /shoes?type=Formal
var response = http.getUrl('https://my-json-server.typicode.com/bixbydevelopers/capsule-samples-collection/shoes', options);
return response;
}
This also demonstrates that the same action can have different JavaScript implementations based on the defining action-endpoint
blocks for different accepted-inputs
in the resources/base/endpoints.bxb
file:
endpoints {
action-endpoints {
action-endpoint (FindShoe) {
accepted-inputs ()
local-endpoint (FindShoe.js)
}
action-endpoint (FindShoeFiltering) {
accepted-inputs (type)
local-endpoint (FindShoeFiltering.js)
}
The FindShoe.js
implementation is called when there are no inputs; the code/FindShoeFiltering.js
endpoint is called when the input is type
.
Training entry: "Find shoes error"
The code/FindShoeError.js
implementation calls a non-existent API endpoint, which returns an HTTP 404 error. This is used to throw a halt
effect.
Training Entry: "Find shoes and show headers"
This demonstrates how to achieve more fine-grained control over the result of HTTP calls. The code/FindShoeReturnHeaders.js
implementation also calls the /error
API endpoint, but calls http.getUrl()
with the returnHeaders
option set to true
; an error is now thrown, instead logging the error response to the console. Then it calls the /shoes
API, again with returnHeaders
set to true
. The HTTP response is sent to the console before parsing.
Training entry: "Create shoe"
Instead of making an HTTP GET, CreateShoe.js
defines a new shoe object and sends it in an HTTP POST to the /shoes
API. As with the previous example, this call is made with returnHeaders
set to true
, and the HTTP response is sent to the console before parsing.
Training entry: "Find shoes with remote endpoint"
This action duplicates the Simple HTTP Get Call described above, but handles it with a remote endpoint. The /shoes
API call already returns JSON formatted in the way actions need to map between JavaScript functions and Bixby models, so it can be called directly by defining a remote endpoint in the action-endpoint
block:
action-endpoint (FindShoeRemoteEndpoint) {
accepted-inputs ()
remote-endpoint ("https://my-json-server.typicode.com/bixbydevelopers/capsule-samples-collection/shoes") {
method (GET)
}
}
Because this is a remote endpoint, there is no local JavaScript implementation for the FindShoeRemoteEndpoint
action needed.
The following video shows how to make basic API calls in your capsule with this sample capsule.