예제 #1
0
 /// <summary>
 /// Initializes a new instance of the <see cref="GraphQLHttpResponseWriter" /> class.
 /// </summary>
 /// <param name="result">The graphql result to serialize.</param>
 /// <param name="documentWriter">The document writer to perform the serailization.</param>
 /// <param name="exposeMetrics">if set to <c>true</c> any metrics contained on the result will be exposed and sent to the requestor.</param>
 /// <param name="exposeExceptions">if set to <c>true</c> exceptions will be writen to the response stream; otherwise false.</param>
 public GraphQLHttpResponseWriter(IGraphOperationResult result, IGraphQueryResponseWriter documentWriter, bool exposeMetrics, bool exposeExceptions)
 {
     _result         = result;
     _documentWriter = documentWriter;
     _options        = new GraphQLResponseOptions()
     {
         ExposeExceptions = exposeExceptions,
         ExposeMetrics    = exposeMetrics,
     };
 }
예제 #2
0
        /// <summary>
        /// Renders the provided operation result through the response writer and generates a JSON based string output.
        /// </summary>
        /// <param name="result">The result of a previously completed operation.</param>
        /// <returns>Task&lt;System.String&gt;.</returns>
        private async Task <string> RenderResult(IGraphOperationResult result)
        {
            var options = new GraphQLResponseOptions()
            {
                ExposeExceptions = this.Schema.Configuration.ResponseOptions.ExposeExceptions,
                ExposeMetrics    = this.Schema.Configuration.ResponseOptions.ExposeMetrics,
            };

            var writer = this.ServiceProvider.GetService <IGraphResponseWriter <TSchema> >();

            using (var memStream = new MemoryStream())
            {
                await writer.WriteAsync(memStream, result, options).ConfigureAwait(false);

                memStream.Seek(0, SeekOrigin.Begin);
                using (var reader = new StreamReader(memStream))
                {
                    return(reader.ReadToEnd());
                }
            }
        }
        private async Task <string> WriteResponse(IGraphQueryResponseWriter writer, IGraphOperationResult result, GraphQLResponseOptions options = null)
        {
            var stream = new MemoryStream();

            options = options ?? new GraphQLResponseOptions()
            {
                ExposeExceptions = true,
                ExposeMetrics    = true,
            };

            await writer.WriteAsync(stream, result, options);

            stream.Seek(0, SeekOrigin.Begin);

            using (var reader = new StreamReader(stream))
                return(reader.ReadToEnd());
        }
 /// <summary>
 /// Writes the single message to the provided writer.
 /// </summary>
 /// <param name="writer">The writer.</param>
 /// <param name="message">The message to serialize.</param>
 /// <param name="options">The options to use to govern the exposure of message level
 /// metadata.</param>
 public void WriteSingleMessage(Utf8JsonWriter writer, IGraphMessage message, GraphQLResponseOptions options)
 {
     this.WriteMessage(writer, message, options);
 }
예제 #5
0
        /// <summary>
        /// Converts the operation reslt into a dictionary map of the required fields for a graphql response.
        /// Spec: https://graphql.github.io/graphql-spec/June2018/#sec-Response .
        /// </summary>
        /// <param name="writer">The json writer to output the reslts to.</param>
        /// <param name="resultToWrite">The operation result to write.</param>
        /// <param name="options">A set options to customize how the response is serialized to the stream.</param>
        private void WriteResult(Utf8JsonWriter writer, IGraphOperationResult resultToWrite, GraphQLResponseOptions options)
        {
            writer.WriteStartObject();

            if (resultToWrite.Messages.Severity >= _minSeverityLevel)
            {
                writer.WriteStartArray("errors");
                foreach (var message in resultToWrite.Messages.Where(x => x.Severity >= _minSeverityLevel))
                {
                    this.WriteMessage(writer, message, options);
                }

                writer.WriteEndArray();
            }

            if (resultToWrite.Data != null || resultToWrite.Messages.Count == 0)
            {
                writer.WritePropertyName("data");
                this.WriteObjectCollection(writer, resultToWrite.Data);
            }

            if (options.ExposeMetrics && resultToWrite.Metrics != null)
            {
                var result = resultToWrite.Metrics.GenerateResult();
                writer.WritePropertyName("extensions");
                this.WriteObjectCollection(writer, result);
            }

            writer.WriteEndObject(); // {document}
        }
예제 #6
0
        /// <summary>
        /// Attempts to write the provided <see cref="IGraphOperationResult" /> to the stream. Generally this stream
        /// will be the response stream for an HTTP request.
        /// </summary>
        /// <param name="streamToWriteTo">The stream to write to.</param>
        /// <param name="resultToWrite">The result to write.</param>
        /// <param name="options">A set options to customize how the response is serialized to the stream.</param>
        /// <returns>Task.</returns>
        public async Task WriteAsync(Stream streamToWriteTo, IGraphOperationResult resultToWrite, GraphQLResponseOptions options = null)
        {
            options = options ?? GraphQLResponseOptions.Default;

            Utf8JsonWriter writer = null;

            try
            {
                writer = new Utf8JsonWriter(streamToWriteTo, _writerOptions);
                this.WriteResult(writer, resultToWrite, options);
            }
            finally
            {
                if (writer != null)
                {
                    await writer.DisposeAsync();
                }
            }
        }
예제 #7
0
        /// <summary>
        /// Creates a new dictionary of properties for the message map
        /// Spec: https://graphql.github.io/graphql-spec/June2018/#sec-Errors .
        /// </summary>
        /// <param name="writer">The json writer to output the reslts to.</param>
        /// <param name="message">The message to render into the output.</param>
        /// <param name="options">A set options to customize how the response is serialized to the stream.</param>
        private void WriteMessage(Utf8JsonWriter writer, IGraphMessage message, GraphQLResponseOptions options)
        {
            writer.WriteStartObject();
            this.WritePreEncodedString(writer, "message", message.Message);

            if (message.Origin.Location != SourceLocation.None)
            {
                writer.WriteStartArray("locations");
                writer.WriteStartObject();
                writer.WriteNumber("line", message.Origin.Location.LineNumber);
                writer.WriteNumber("column", message.Origin.Location.LinePosition);
                writer.WriteEndObject();
                writer.WriteEndArray(); // locations
            }

            if (message.Origin.Path != SourcePath.None)
            {
                writer.WriteStartArray("path");
                foreach (var loc in message.Origin.Path)
                {
                    if (loc is int i)
                    {
                        writer.WriteNumberValue(i);
                    }
                    else if (loc is string str)
                    {
                        this.WritePreEncodedStringValue(writer, str);
                    }
                    else
                    {
                        writer.WriteNullValue();
                    }
                }

                writer.WriteEndArray(); // path
            }

            writer.WriteStartObject("extensions");
            this.WriteLeaf(writer, "code", message.Code);

            var timestamp = _timeLocalizer?.Invoke(message.TimeStamp) ?? message.TimeStamp;

            this.WriteLeaf(writer, "timestamp", timestamp);
            this.WriteLeaf(writer, "severity", message.Severity);

            if (message.MetaData != null && message.MetaData.Count > 0)
            {
                writer.WriteStartObject("metaData");
                foreach (var item in message.MetaData)
                {
                    this.WriteLeaf(writer, item.Key, item.Value, true);
                }

                writer.WriteEndObject(); // metadata
            }

            if (options.ExposeExceptions && message.Exception != null)
            {
                writer.WriteStartObject("exception");
                this.WriteLeaf(writer, "type", message.Exception.GetType().FriendlyName());
                this.WriteLeaf(writer, "message", message.Exception.Message);

                const int maxStackTrace     = 4000;
                var       stacktraceMessage = message.Exception.StackTrace;
                if (stacktraceMessage?.Length > maxStackTrace)
                {
                    stacktraceMessage  = stacktraceMessage.Substring(0, maxStackTrace);
                    stacktraceMessage += $"[cut at {maxStackTrace} characters]";
                }

                if (!string.IsNullOrWhiteSpace(stacktraceMessage))
                {
                    this.WriteLeaf(writer, "stacktrace", stacktraceMessage);
                }

                writer.WriteEndObject(); // exception
            }

            writer.WriteEndObject(); // extensions
            writer.WriteEndObject(); // message
        }
 /// <summary>
 /// Attempts to serialize the provided <see cref="IGraphOperationResult" /> directly to the
 /// provided json writer.
 /// </summary>
 /// <param name="jsonWriter">The json writer.</param>
 /// <param name="resultToWrite">The result to write.</param>
 /// <param name="options">A set options to customize how the response is serialized to the stream.</param>
 public void WriteAsync(Utf8JsonWriter jsonWriter, IGraphOperationResult resultToWrite, GraphQLResponseOptions options = null)
 {
     this.WriteResult(jsonWriter, resultToWrite, options);
 }