-
Notifications
You must be signed in to change notification settings - Fork 17
Expand file tree
/
Copy pathQueryFunction.cs
More file actions
102 lines (87 loc) · 4.59 KB
/
QueryFunction.cs
File metadata and controls
102 lines (87 loc) · 4.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
using System.Text.Json;
using System.Web;
using CommandQuery.SystemTextJson;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;
namespace CommandQuery.AzureFunctions
{
/// <inheritdoc />
public class QueryFunction : IQueryFunction
{
private readonly IQueryProcessor _queryProcessor;
private readonly ILogger<QueryFunction> _logger;
private readonly JsonSerializerOptions? _options;
/// <summary>
/// Initializes a new instance of the <see cref="QueryFunction"/> class.
/// </summary>
/// <param name="queryProcessor">An <see cref="IQueryProcessor"/>.</param>
/// <param name="logger">An <see cref="ILogger{T}"/>.</param>
/// <param name="options"><see cref="JsonSerializerOptions"/> to control the behavior during deserialization of <see cref="HttpRequestData.Body"/> and serialization of <see cref="HttpResponseData.Body"/>.</param>
public QueryFunction(IQueryProcessor queryProcessor, ILogger<QueryFunction> logger, JsonSerializerOptions? options = null)
{
_queryProcessor = queryProcessor;
_logger = logger;
_options = options;
}
/// <inheritdoc />
public async Task<HttpResponseData> HandleAsync(string queryName, HttpRequestData req, CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(req);
if (_logger.IsEnabled(LogLevel.Information))
{
_logger.LogInformation("Handle {Query}", queryName);
}
try
{
var result = req.Method == "GET"
? await _queryProcessor.ProcessAsync<object>(queryName, Dictionary(req.Url), cancellationToken).ConfigureAwait(false)
: await _queryProcessor.ProcessAsync<object>(queryName, await req.ReadAsStringAsync().ConfigureAwait(false), _options, cancellationToken).ConfigureAwait(false);
return await req.OkAsync(result, _options).ConfigureAwait(false);
}
catch (Exception exception)
{
var payload = req.Method == "GET" ? req.Url.ToString() : await req.ReadAsStringAsync().ConfigureAwait(false);
_logger.LogError(exception, "Handle query failed: {Query}, {Payload}", queryName, payload);
return exception.IsHandled()
? await req.BadRequestAsync(exception, _options).ConfigureAwait(false)
: await req.InternalServerErrorAsync(exception, _options).ConfigureAwait(false);
}
Dictionary<string, IEnumerable<string>> Dictionary(Uri url)
{
var query = HttpUtility.ParseQueryString(url.Query);
return query.AllKeys.ToDictionary<string?, string, IEnumerable<string>>(k => k!, k => query.GetValues(k)!);
}
}
/// <inheritdoc />
public async Task<IActionResult> HandleAsync(string queryName, HttpRequest req, CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(req);
if (_logger.IsEnabled(LogLevel.Information))
{
_logger.LogInformation("Handle {Query}", queryName);
}
try
{
var result = req.Method == "GET"
? await _queryProcessor.ProcessAsync<object>(queryName, Dictionary(req.Query), cancellationToken).ConfigureAwait(false)
: await _queryProcessor.ProcessAsync<object>(queryName, await req.ReadAsStringAsync().ConfigureAwait(false), _options, cancellationToken).ConfigureAwait(false);
return new OkObjectResult(result);
}
catch (Exception exception)
{
var payload = req.Method == "GET" ? req.GetDisplayUrl() : await req.ReadAsStringAsync().ConfigureAwait(false);
_logger.LogError(exception, "Handle query failed: {Query}, {Payload}", queryName, payload);
return exception.IsHandled()
? new BadRequestObjectResult(exception.ToError())
: new ObjectResult(exception.ToError()) { StatusCode = StatusCodes.Status500InternalServerError };
}
static Dictionary<string, IEnumerable<string>> Dictionary(IQueryCollection query)
{
return query.ToDictionary(kv => kv.Key, kv => kv.Value as IEnumerable<string>, StringComparer.OrdinalIgnoreCase);
}
}
}
}