Skip to content

Instantly share code, notes, and snippets.

@jimmyjames
Last active January 15, 2021 13:51
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jimmyjames/85a1a46fbd7fc077dee78f6ae1d865c0 to your computer and use it in GitHub Desktop.
Save jimmyjames/85a1a46fbd7fc077dee78f6ae1d865c0 to your computer and use it in GitHub Desktop.
/**
* Async HTTP Examples
*
* Copyright 2016 SmartThings
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
* for the specific language governing permissions and limitations under the License.
*
*/
definition(
name: "Async HTTP Examples",
namespace: "smartthings",
author: "SmartThings",
description: "Examples of using the new async http apis",
category: "",
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png",
iconX3Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png")
// Must include the asynchttp API to use async http api!
include 'asynchttp_v1'
preferences {
section("Title") {}
}
def installed() {
initialize()
}
def updated() {
initialize()
}
def initialize() {
// to avoid digging through lots of logging, you may wish to comment out
// calls you're not interested in seeing
basicGetRequest()
//getWithQuery()
//getXMLResults()
//requestWithError()
//requestWithData()
//showAsyncNature()
// See the postWithJson and postWithXml method definitions for instructions
// on how to test these APIs.
//postWithJson()
//postWithXml()
}
/**
* Basic GET request
*/
def basicGetRequest() {
def params = [
uri: 'https://api.github.com'
]
asynchttp_v1.get('basicGetHandler', params)
}
/**
* Response handler for basic GET request
*/
def basicGetHandler(response, data) {
// get raw data from response
log.debug "basic GET request raw data: $response.data"
// GitHub returns json body
log.debug "basic GET request json: $response.json"
// show the http status code (e.g., 200, 304, 401)
log.debug "response status: $response.status"
// all response headers are available as a map of key->value pairs
def headers = response.headers
headers.each { header, value ->
log.debug "$header: $value"
}
}
/**
* Searches the SmartThingsPublic GitHub repository for the usages of httpGet
*
* Makes a GET request to api.github.com/search/code with query string
* q=httpGet+repo:SmartThingsCommunity/SmartThingsPublic
**/
def getWithQuery() {
def params = [
uri: 'https://api.github.com',
path: '/search/code',
query: [q: "httpGet+repo:SmartThingsCommunity/SmartThingsPublic"],
requestContentType: 'application/json'
]
asynchttp_v1.get(getWithQueryHandler, params)
}
/**
* Response handler for GitHub search of httpGet in SmartThingsPublic repo
**/
def getWithQueryHandler(response, data) {
// result is json
def results = response.json
log.debug "total found results of httpGet in SmartThingsPublic: ${results?.total_count}"
// log all file names returned
results?.items.each { item ->
log.debug "File $item.name uses httpGet"
}
}
/**
* Makes a GET request to httpbin.org/xml with requestContentType: application/xml
*/
def getXMLResults() {
def params = [
uri: 'https://httpbin.org',
path: '/xml',
requestContentType: 'application/xml'
]
asynchttp_v1.get('xmlResultsHandler', params)
}
/**
* Response handler for XML response. Shows how to use the parsed XML response
*/
def xmlResultsHandler(response, data) {
log.debug "raw xml response: $response.data"
def root = response.xml
log.debug "title: ${root?.slide[0]?.title?.text()}"
}
/**
* POSTs to requstb.in
*
* You need to create your own bin at requestb.in and use that as the path below
* for this to work!
**/
def postWithJson() {
def params = [
uri: 'https://requestb.in',
path: '<ADD YOUR BIN HERE!>',
// using a map for the body will be serialized to json on the request
body: [key1: [nestedKey: "nested value 1", nestedKey2: 42]],
requestContentType: "application/json"
]
asynchttp_v1.post('postWithJsonHandler', params)
}
/**
* Nothing interesting on this response; the interesting thing is to look at what data
* was posted to requestb.in
**/
def postWithJsonHandler(response, data) {
log.debug "response data for post with JSON: $response.json"
}
/**
* POSTs to requstb.in with requestContentType of application/xml
*
* You need to create your own bin at requestb.in and use that as the path below
* for this to work!
**/
def postWithXml() {
def params = [
uri: 'https://requestb.in',
path: '<ADD YOUR BIN HERE!>',
// passing XML in the body
body: "<entity><name>test</name></entity>",
contentType: "application/xml"
]
asynchttp_v1.post('postWithXmlHandler', params)
}
/**
* Nothing interesting on this response; the interesting thing is to look at what data
* was posted to requestb.in
**/
def postWithXmlHandler(response, data) {
log.debug "response data for post with XML: $response.data"
}
/**
* Makes a request to the GitHub API that will return a non-successful response (anything not 2XX
* is considered an error)
**/
def requestWithError() {
def params = [
uri: 'https://api.github.com',
// GitHub API does not support xml and will return an error
requestContentType: 'application/xml'
]
asynchttp_v1.get('requestWithErrorHandler', params)
}
/**
* The response handler for a request that will not be successful
* (anything that is not a 2XX response code is considered a failure)
*/
def requestWithErrorHandler(response, data) {
if (response.hasError()) {
// we expect an error here (HTTP 415)
log.debug "requesting XML from GitHub failed; error message: $response.errorMessage"
} else {
log.debug "Expected to get an error!"
}
}
/**
* Makes a request and passes a map of data to be sent to the response handler
**/
def requestWithData() {
def params = [
uri: 'https://api.github.com'
]
def data = [foo: 'bar', baz: 'boo']
// pass a map as the (optional) final arugument to any async http methods
// this map will then be sent to the response handler.
// This is useful for sharing data between request and response, and avoids
// potential race conditions of using state
asynchttp_v1.get('requestWithDataHandler', params, data)
}
/**
* Shows how the data map is passed on to the response handler
**/
def requestWithDataHandler(response, data) {
log.debug "was passed data from the request handler: $data"
}
/**
* Makes 20 async http requests to the GitHub API.
**/
def showAsyncNature() {
def requestOrder = []
(1..20).each {
def params = [uri: 'https://api.github.com']
log.debug "will make request number $it"
// pass the request number to the response handler so we can
// see the order they are called
requestOrder << it
asynchttp_v1.get('asyncResponseHandler', params, [requestNumber: it])
}
}
/**
* Logs the requst number to illustrate how the requests may execute in a different
* order than called!
**/
def asyncResponseHandler(response, data) {
log.debug "in response handler for request $data.requestNumber"
}
@jimmyjames
Copy link
Author

This is an example SmartApp that will show using the async http APIs in various ways.

Instructions

  1. Click the "Raw" button at the top of the file, then copy the entire SmartApp to the clipboard.
  2. Navigate to the SmartApps page in the SmartThings IDE, and click "New SmartApp".
  3. Select the "From Code" option in the New SmartApp form, and paste the code from the clipboard.
  4. Click Create.
  5. In the initialize() method, uncomment the method you'd like to test, then install the SmartApp in the simulator, and observe Live Logging.

Notes

  • The request method examples that POST data require you to create your own bin in http://postb.in and use that as the path option on the request parameters. Instructions are found in the source code.
  • You can uncomment multiple (or all) method calls in initialize(), but be prepared to have a flood of Live Logging to go through!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment