@@ -21,6 +21,7 @@ namespace Microsoft.AspNetCore.NodeServices.HostingModels
21
21
/// <seealso cref="Microsoft.AspNetCore.NodeServices.HostingModels.OutOfProcessNodeInstance" />
22
22
internal class HttpNodeInstance : OutOfProcessNodeInstance
23
23
{
24
+ private readonly static int streamBufferSize = 16 * 1024 ;
24
25
private static readonly Regex PortMessageRegex =
25
26
new Regex ( @"^\[Microsoft.AspNetCore.NodeServices.HttpNodeHost:Listening on port (\d+)\]$" ) ;
26
27
@@ -67,8 +68,10 @@ protected override async Task<T> InvokeExportAsync<T>(
67
68
if ( ! response . IsSuccessStatusCode )
68
69
{
69
70
// 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 ) ;
72
75
}
73
76
74
77
var responseContentType = response . Content . Headers . ContentType ;
@@ -136,5 +139,35 @@ protected override void Dispose(bool disposing)
136
139
_disposed = true ;
137
140
}
138
141
}
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
139
172
}
140
173
}
0 commit comments