Skip to content

Commit 6d85e75

Browse files
rosieksSteveSandersonMS
authored andcommitted
Throwing HttpInvocationException instead of generic Exception
1 parent 460f202 commit 6d85e75

File tree

2 files changed

+39
-3
lines changed

2 files changed

+39
-3
lines changed

src/Microsoft.AspNetCore.NodeServices/HostingModels/HttpNodeInstance.cs

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels
2121
/// <seealso cref="Microsoft.AspNetCore.NodeServices.HostingModels.OutOfProcessNodeInstance" />
2222
internal class HttpNodeInstance : OutOfProcessNodeInstance
2323
{
24+
private readonly static int streamBufferSize = 16 * 1024;
2425
private static readonly Regex PortMessageRegex =
2526
new Regex(@"^\[Microsoft.AspNetCore.NodeServices.HttpNodeHost:Listening on port (\d+)\]$");
2627

@@ -67,8 +68,10 @@ protected override async Task<T> InvokeExportAsync<T>(
6768
if (!response.IsSuccessStatusCode)
6869
{
6970
// Unfortunately there's no true way to cancel ReadAsStringAsync calls, hence AbandonIfCancelled
70-
var responseErrorString = await response.Content.ReadAsStringAsync().OrThrowOnCancellation(cancellationToken);
71-
throw new Exception("Call to Node module failed with error: " + responseErrorString);
71+
var responseJson = await response.Content.ReadAsStringAsync().OrThrowOnCancellation(cancellationToken);
72+
var responseError = JsonConvert.DeserializeObject<RpcJsonResponse>(responseJson, jsonSerializerSettings);
73+
74+
throw new NodeInvocationException(responseError.ErrorMessage, responseError.ErrorDetails);
7275
}
7376

7477
var responseContentType = response.Content.Headers.ContentType;
@@ -136,5 +139,35 @@ protected override void Dispose(bool disposing)
136139
_disposed = true;
137140
}
138141
}
142+
143+
private static async Task<T> ReadJsonAsync<T>(Stream stream, CancellationToken cancellationToken)
144+
{
145+
var json = Encoding.UTF8.GetString(await ReadAllBytesAsync(stream, cancellationToken));
146+
return JsonConvert.DeserializeObject<T>(json, jsonSerializerSettings);
147+
}
148+
149+
private static async Task<byte[]> ReadAllBytesAsync(Stream input, CancellationToken cancellationToken)
150+
{
151+
byte[] buffer = new byte[streamBufferSize];
152+
153+
using (var ms = new MemoryStream())
154+
{
155+
int read;
156+
while ((read = await input.ReadAsync(buffer, 0, buffer.Length, cancellationToken)) > 0)
157+
{
158+
ms.Write(buffer, 0, read);
159+
}
160+
161+
return ms.ToArray();
162+
}
163+
}
164+
165+
#pragma warning disable 649 // These properties are populated via JSON deserialization
166+
private class RpcJsonResponse
167+
{
168+
public string ErrorMessage { get; set; }
169+
public string ErrorDetails { get; set; }
170+
}
171+
#pragma warning restore 649
139172
}
140173
}

src/Microsoft.AspNetCore.NodeServices/TypeScript/HttpNodeInstanceEntryPoint.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,5 +86,8 @@ function readRequestBodyAsJson(request, callback) {
8686

8787
function respondWithError(res: http.ServerResponse, errorValue: any) {
8888
res.statusCode = 500;
89-
res.end(errorValue.stack || errorValue.toString());
89+
res.end(JSON.stringify({
90+
errorMessage: errorValue.message || errorValue,
91+
errorDetails: errorValue.stack || null
92+
}));
9093
}

0 commit comments

Comments
 (0)