This project is maintained by gloveboxes
Author | Dave Glover, Microsoft Cloud Developer Advocate |
---|---|
Documentation | README |
Platform | Azure Functions |
Documentation | Create Azure HTTP triggered Functions, Azure IoT Central, Azure Device Provisioning Service, Connection String Generator (dps_str) |
Date | As at April 2019 |
Thought I’d share a neat trick to convert a command line tool into a REST API using Azure HTTP Functions.
At a high level, you create an Azure HTTP Function, upload the command line tool, add code to pass in command line arguments, redirect standard output, start the command process, and return the standard output from the command line in the HTTP response.
I’m running an Azure IoT Central workshop and to minimize setup I wanted the workshop to be completely browser-based. Azure IoT Central uses the Azure Device Provisioning Service and you need to use the Connection String Generator (dps_str) command line tool to create a real device connection string.
#r "Newtonsoft.Json"
using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;
using System;
using System.Diagnostics;
public static async Task<IActionResult> Run(HttpRequest req, ILogger log)
{
string result;
string functionName = "ConnectionString";
string scope = req.Query["scope"];
string deviceid = req.Query["deviceid"];
string key = req.Query["key"];
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
scope = scope ?? data?.scope;
deviceid = deviceid ?? data?.deviceid;
key = key ?? data?.key;
if (String.IsNullOrEmpty(scope) ||
String.IsNullOrEmpty(deviceid) ||
String.IsNullOrEmpty(key) )
{
return new BadRequestObjectResult("Please pass a IoT Central device Scope, DeviceId and key (url encoded) on the query string or in the request body");
}
var workingDirectory = Path.Combine(@"d:\home\site\wwwroot", functionName);
Directory.SetCurrentDirectory(workingDirectory);
string arguments = $"\"{scope}\" \"{deviceid}\" \"{key}\"";
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = @"dps_cstr.exe";
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
start.Arguments = arguments;
using (Process process = Process.Start(start))
{
using (StreamReader reader = process.StandardOutput)
{
result = reader.ReadToEnd();
}
}
return result != null
? (ActionResult)new OkObjectResult($"{result}")
: new BadRequestObjectResult("Please pass a IoT Central device Scope, DeviceId and key (url encoded) on the query string or in the request body");
}
I wanted a web browser UI for the REST API so I wrote a simple HTML/JavaScript App and I call the REST API from JavaScript. Given no server-side processing is required the HTML page is hosted using Static website hosting in Azure Storage.
As you are calling the Azure HTTP Function REST API from Javascript you will need to adjust the CORS rules for the Azure HTTP Function.
From the Azure Function you created