public static void CheckResponse(this HttpResponseMessage response, InvokeUpstreamParameters parameters, ILogger logger, Func <HttpResponseMessage, bool> expectedEvaluator) { if (response.StatusCode == HttpStatusCode.InternalServerError) { // already logged inside return; } var operationName = parameters.ToString(); if (expectedEvaluator.Invoke(response)) { logger.LogInformation($"Upstream successfully sent message for {operationName}."); } else { logger.LogError($"The response for {operationName} is unexpected: {response.StatusCode}."); } }
public async Task AddClientConnectionAsync(HubConnectionContext connectionContext, CancellationToken token = default) { var parameters = new InvokeUpstreamParameters(_hubName, ServerlessProtocol.Constants.Categories.ConnectionCategory, ServerlessProtocol.Constants.Events.ConnectedEvent); if (!_httpUpstreamTrigger.TryGetMatchedUpstreamContext(parameters, out var context)) { // Upstream for this event is not set, ignore the event return; } using (var response = await _httpUpstreamTrigger.TriggerAsync( context, connectionContext, parameters, request => { request.Content = new ByteArrayContent(OpenConnectionPayload); request.Content.Headers.ContentType = JsonMediaType; }, token)) { response.CheckResponse(parameters, _logger, IsExpectedResponse); } }
public async Task <ReadOnlySequence <byte> > WriteMessageAsync(HubConnectionContext connectionContext, ServerlessProtocol.InvocationMessage message, CancellationToken token) { var parameters = new InvokeUpstreamParameters(_hubName, ServerlessProtocol.Constants.Categories.MessageCategory, message.Target); if (!_httpUpstreamTrigger.TryGetMatchedUpstreamContext(parameters, out var context)) { // Upstream for this event is not set, ignore the event return(ReadOnlySequence <byte> .Empty); } var mediaType = connectionContext.Protocol.Name.Equals("json", StringComparison.OrdinalIgnoreCase) ? JsonMediaType : MessagePackMediaType; using (var response = await _httpUpstreamTrigger.GetResponseAsync( context, connectionContext, message, parameters, mediaType, token)) { response.CheckResponse(parameters, _logger, IsExpectedResponse); if (!string.IsNullOrEmpty(message.InvocationId)) { if (response.StatusCode == HttpStatusCode.OK) { return(message.Payload); } else if (response.StatusCode == HttpStatusCode.NoContent) { await connectionContext.WriteAsync(CompletionMessage.Empty(message.InvocationId)); } else { await connectionContext.WriteAsync(CompletionMessage.WithError(message.InvocationId, $"Invocation failed, status code {(int)response.StatusCode}")); } } } return(ReadOnlySequence <byte> .Empty); }
public async Task <ReadOnlySequence <byte> > WriteMessageAsync(HubConnectionContext connectionContext, ServerlessProtocol.InvocationMessage message, CancellationToken token) { var parameters = new InvokeUpstreamParameters(_hubName, ServerlessProtocol.Constants.Categories.MessageCategory, message.Target); if (!_httpUpstreamTrigger.TryGetMatchedUpstreamContext(parameters, out var context)) { // Upstream for this event is not set, ignore the event return(ReadOnlySequence <byte> .Empty); } var mediaType = connectionContext.Protocol.Name.Equals("json", StringComparison.OrdinalIgnoreCase) ? JsonMediaType : MessagePackMediaType; using (var response = await _httpUpstreamTrigger.GetResponseAsync( context, connectionContext, message, parameters, mediaType, token)) { response.CheckResponse(parameters, _logger, IsExpectedResponse); if (!string.IsNullOrEmpty(message.InvocationId)) { if (response.StatusCode == HttpStatusCode.OK) { var contentLength = response.Content.Headers.ContentLength; if (contentLength == 0) { // same as no content. await connectionContext.WriteAsync(CompletionMessage.Empty(message.InvocationId)); } else if (contentLength > MaxAllowedResponseLength) { // We don't support response large than 16M, fast fail. await connectionContext.WriteAsync(CompletionMessage.WithError(message.InvocationId, $"Invocation failed, response too large.")); } else { var ls = new LimitedStream(MaxAllowedResponseLength); try { await response.Content.CopyToAsync(ls); return(new ReadOnlySequence <byte>(ls.ToMemory())); } catch (InvalidDataException) { await connectionContext.WriteAsync(CompletionMessage.WithError(message.InvocationId, $"Invocation failed, response too large.")); } catch (OperationCanceledException) { await connectionContext.WriteAsync(CompletionMessage.WithError(message.InvocationId, $"Invocation failed, response cancelled.")); } catch (Exception ex) { await connectionContext.WriteAsync(CompletionMessage.WithError(message.InvocationId, $"Invocation failed, error: {ex.Message}.")); } } } else if (response.StatusCode == HttpStatusCode.NoContent) { await connectionContext.WriteAsync(CompletionMessage.Empty(message.InvocationId)); } else { await connectionContext.WriteAsync(CompletionMessage.WithError(message.InvocationId, $"Invocation failed, status code {(int)response.StatusCode}")); } } } return(ReadOnlySequence <byte> .Empty); }