Last active
July 6, 2016 20:24
-
-
Save Leigh-/b1739cc464b81c356d084755fc65ebc1 to your computer and use it in GitHub Desktop.
Initial version of CreateArticle Example for Apple News API. Tested under CF11
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
<cfscript> | |
/* | |
IMPORTANT: Make sure fileGetMimeType("c:/path/article.json") returns the | |
correct mime type in your environment: | |
ie: Should return: "application/json" | |
... and not : "text/plain" | |
*/ | |
// Modify these variables for your environment | |
channelID = "63aFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF"; | |
apiKeyID = "379FFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF"; | |
apiKeySecret = "miJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; | |
targetURL = "https://news-api.apple.com/channels/#channelID#/articles"; | |
articlePath = ExpandPath("/apple/article/article.json"); | |
resourcesFolder = ExpandPath("/apple/resources"); | |
// metadata | |
metadata = { "data":{ | |
"isPreview":true, | |
"links":{ | |
"sections":[ | |
"https://news-api.apple.com/sections/9e7bfbf2-ed0c-38a2-8c74-2da17348f4e6" | |
] | |
} | |
} | |
}; | |
// Build properties for article and metadata | |
requestData = [ { "name" = "article.json" | |
, "type" = "application/json" | |
, "path" = articlePath | |
, "filename" = "article.json" | |
} | |
, { "name" = "metadata" | |
, "type" = "application/json" | |
, "value" = serializeJSON(metadata) | |
} | |
]; | |
// Append resources | |
// note: file name handling should be more robust | |
resourceFiles = DirectoryList( resourcesFolder, false ); | |
ArrayEach(resourceFiles, function( path, index ){ | |
arrayAppend(requestData | |
, { "name" = "file"& arguments.index-1 | |
, "type" = fileGetMimeType(arguments.path) | |
, "path" = arguments.path | |
, "filename" = listFirst(listLast(arguments.path, "\/"), ".") | |
} | |
); | |
} | |
); | |
writeDump( requestData ); | |
// Initialize variables | |
utcDateTime = dateConvert( "local2UTC", now() ); | |
dateValue = dateFormat( utcDateTime, "yyyy-mm-dd")&"T"& timeFormat(utcDateTime, "HH:nn:ss")&"Z"; | |
boundary = replace(createUUID(), "-", "", "all"); | |
contentType = "multipart/form-data; boundary="& boundary; | |
methodName = "POST"; | |
// Generate request body (as binary) | |
requestBinary = buildRequestBody(boundary, requestData ); | |
canonicalString = methodName & targetURL & dateValue & contentType; | |
// Note: CF11 workaround for ArrayAppend, which does not merge binary arrays | |
ArrayUtils = createObject("java", "org.apache.commons.lang.ArrayUtils"); | |
canonicalBinary = ArrayUtils.addAll( charsetDecode(canonicalString, "utf-8"), requestBinary ); | |
writeOutput("<br>canonicalString (minus body) ="& canonicalString ); | |
// Generate signature and authorization header | |
signatureHash = hmac(canonicalBinary, binaryDecode(apiKeySecret, "base64"), "HMACSHA256"); | |
signatureBase64 = binaryEncode(binaryDecode(signatureHash, "hex"), "base64"); | |
authorization = "HHMAC; key=""#apiKeyID#""; signature=""#signatureBase64#""; date=""#dateValue#"""; | |
// Initialize connection | |
urlObject = createObject("java", "java.net.URL").init( targetURL ); | |
connection = urlObject.openConnection(); | |
connection.setConnectTimeout( 15000 ); | |
connection.setReadTimeout( 15000 ); | |
connection.setDoOutput( true ); | |
// Add headers Note: timeouts are in milliseconds (0 == infinite timeout) | |
connection.setRequestMethod( methodName ); | |
connection.setRequestProperty("Content-type", contentType ); | |
connection.setRequestProperty("Authorization", authorization); | |
// Copy body into request | |
outStream = connection.getOutputStream(); | |
outStream.write( requestBinary, 0, arrayLen(requestBinary)); | |
outStream.flush(); | |
outStream.close(); | |
// Get response | |
response.code = connection.getResponseCode(); | |
response.message = connection.getResponseMessage(); | |
// Read response | |
stream = (response.code == connection.HTTP_OK) ? connection.getInputStream() : connection.getErrorStream(); | |
ioUtil = createObject("java", "org.apache.commons.io.IOUtils"); | |
response.text = ioUtil.toString( stream, "utf-8" ); | |
// Cleanup | |
stream.close(); | |
connection.disconnect(); | |
WriteOutput( "<br>authorization ="& authorization ); | |
writeDump( response ); | |
public array function buildRequestBody ( string boundaryMarker, array requestData, string encoding="UTF-8") { | |
Local.newLine = chr(13) & chr(10); | |
// Build streams for storing request body | |
Local.byteStream = createObject("java", "java.io.ByteArrayOutputStream").init(); | |
Local.outStream = createObject("java", "java.io.OutputStreamWriter").init( byteStream, arguments.encoding ); | |
Local.writer = createObject("java", "java.io.PrintWriter").init(Local.outStream, true); | |
Local.ioUtil = createObject("java", "org.apache.commons.io.IOUtils"); | |
// Write data to request stream | |
for (Local.requestElem in arguments.requestData) { | |
// Write headers for new field | |
Local.writer.write( "--"& arguments.boundaryMarker ); | |
Local.writer.write( Local.newLine ); | |
Local.writer.write( "Content-Type: "& Local.requestElem.type ); | |
Local.writer.write( Local.newLine ); | |
Local.writer.write( "Content-Disposition: form-data"); | |
// Append physical file | |
if (structKeyExists(Local.requestElem, "path")) { | |
Local.writer.write("; filename="& Local.requestElem.fileName ); | |
Local.writer.write("; name=" & Local.requestElem.name ); | |
Local.writer.write("; size="& GetFileInfo(Local.requestElem.path).size ); | |
Local.writer.write( Local.newLine ); | |
Local.writer.write( Local.newLine ); | |
Local.writer.flush(); | |
Local.inputStream = createObject("java", "java.io.FileInputStream").init( Local.requestElem.path ); | |
Local.ioUtil.copy( Local.inputStream, Local.byteStream ); | |
} | |
// Otherwise, assume this is a simple string | |
else { | |
Local.valueBinary = charsetDecode(Local.requestElem.value, arguments.encoding ); | |
Local.writer.write("; name=" & Local.requestElem.name); | |
Local.writer.write("; size="& arrayLen(Local.valueBinary) ); | |
Local.writer.write( Local.newLine ); | |
Local.writer.write( Local.newLine ); | |
Local.writer.flush(); | |
Local.byteStream.write( Local.valueBinary ); | |
} | |
// Prepare to move to next field | |
Local.byteStream.flush(); | |
Local.ioUtil.closeQuietly( Local.inputStream ); | |
Local.writer.write( Local.newLine ); | |
} | |
// Generate closing boundary | |
Local.writer.write( "--"& boundary &"--" ); | |
Local.writer.write( Local.newLine ); | |
// Cleanup | |
Local.ioUtil.closeQuietly( Local.writer ); | |
Local.ioUtil.closeQuietly( Local.byteStream ); | |
// Return request binary | |
return Local.byteStream.toByteArray(); | |
} | |
</cfscript> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment