Support streamed response from HttpNodeInstance

This commit is contained in:
SteveSandersonMS
2016-06-07 16:49:40 +01:00
parent 3440aa4344
commit 967edd2b2a
4 changed files with 52 additions and 20 deletions

View File

@@ -1,4 +1,5 @@
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
@@ -36,10 +37,10 @@ namespace NodeServicesExamples.Controllers
return NotFound();
}
// Invoke Node and convert the base64 result back to bytes
// Invoke Node and pipe the result to the response
var mimeType = GetContentType(imagePath);
var resizedImage = await _nodeServices.Invoke<ResizeImageResult>("./Node/resizeImage", fileInfo.PhysicalPath, mimeType, maxWidth, maxHeight);
return File(Convert.FromBase64String(resizedImage.Base64), mimeType);
var imageStream = await _nodeServices.Invoke<Stream>("./Node/resizeImage", fileInfo.PhysicalPath, mimeType, maxWidth, maxHeight);
return File(imageStream, mimeType);
}
private string GetContentType(string path)

View File

@@ -1,9 +1,7 @@
var sharp = require('sharp');
module.exports = function(cb, physicalPath, mimeType, maxWidth, maxHeight) {
module.exports = function(result, physicalPath, mimeType, maxWidth, maxHeight) {
sharp(physicalPath)
.resize(maxWidth > 0 ? maxWidth : null, maxHeight > 0 ? maxHeight : null)
.toBuffer(function (err, buffer) {
cb(err, { base64: buffer && buffer.toString('base64') });
});
.pipe(result.stream);
}

View File

@@ -42,6 +42,19 @@ var server = http.createServer(function(req, res) {
}
};
// Support streamed responses
Object.defineProperty(callback, 'stream', {
enumerable: true,
get: function() {
if (!hasSentResult) {
hasSentResult = true;
res.setHeader('Content-Type', 'application/octet-stream');
}
return res;
}
});
try {
func.apply(null, [callback].concat(bodyJson.args));
} catch (synchronousException) {

View File

@@ -1,4 +1,5 @@
using System;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Text.RegularExpressions;
@@ -52,27 +53,46 @@ namespace Microsoft.AspNetCore.NodeServices
var payloadJson = JsonConvert.SerializeObject(invocationInfo, JsonSerializerSettings);
var payload = new StringContent(payloadJson, Encoding.UTF8, "application/json");
var response = await _client.PostAsync("http://localhost:" + _portNumber, payload);
var responseString = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
{
throw new Exception("Call to Node module failed with error: " + responseString);
var responseErrorString = await response.Content.ReadAsStringAsync();
throw new Exception("Call to Node module failed with error: " + responseErrorString);
}
var responseIsJson = response.Content.Headers.ContentType.MediaType == "application/json";
if (responseIsJson)
var responseContentType = response.Content.Headers.ContentType;
switch (responseContentType.MediaType)
{
return JsonConvert.DeserializeObject<T>(responseString);
}
case "text/plain":
// String responses can skip JSON encoding/decoding
if (typeof(T) != typeof(string))
{
throw new ArgumentException(
"Node module responded with non-JSON string. This cannot be converted to the requested generic type: " +
typeof(T).FullName);
}
if (typeof(T) != typeof(string))
{
throw new ArgumentException(
"Node module responded with non-JSON string. This cannot be converted to the requested generic type: " +
typeof(T).FullName);
}
var responseString = await response.Content.ReadAsStringAsync();
return (T)(object)responseString;
return (T)(object)responseString;
case "application/json":
var responseJson = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(responseJson);
case "application/octet-stream":
// Streamed responses have to be received as System.IO.Stream instances
if (typeof(T) != typeof(Stream))
{
throw new ArgumentException(
"Node module responded with binary stream. This cannot be converted to the requested generic type: " +
typeof(T).FullName + ". Instead you must use the generic type System.IO.Stream.");
}
return (T)(object)(await response.Content.ReadAsStreamAsync());
default:
throw new InvalidOperationException("Unexpected response content type: " + responseContentType.MediaType);
}
}
protected override void OnOutputDataReceived(string outputData)