Last active
January 15, 2021 13:51
-
-
Save jimmyjames/85a1a46fbd7fc077dee78f6ae1d865c0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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" | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is an example SmartApp that will show using the async http APIs in various ways.
Instructions
initialize()
method, uncomment the method you'd like to test, then install the SmartApp in the simulator, and observe Live Logging.Notes
path
option on the request parameters. Instructions are found in the source code.initialize()
, but be prepared to have a flood of Live Logging to go through!