-
-
Notifications
You must be signed in to change notification settings - Fork 28
/
InlineBuilder.cs
209 lines (170 loc) · 9.5 KB
/
InlineBuilder.cs
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
using System;
using System.Linq;
using System.Collections.Generic;
using GenHTTP.Api.Content;
using GenHTTP.Api.Infrastructure;
using GenHTTP.Api.Protocol;
using GenHTTP.Modules.Conversion;
using GenHTTP.Modules.Conversion.Providers;
using GenHTTP.Modules.Conversion.Formatters;
using GenHTTP.Modules.Reflection.Injectors;
using GenHTTP.Modules.Reflection;
namespace GenHTTP.Modules.Functional.Provider
{
public class InlineBuilder : IHandlerBuilder<InlineBuilder>
{
private static readonly HashSet<FlexibleRequestMethod> ALL_METHODS = new(Enum.GetValues<RequestMethod>().Select(m => FlexibleRequestMethod.Get(m)));
private readonly List<IConcernBuilder> _Concerns = new();
private readonly List<InlineFunction> _Functions = new();
private IBuilder<SerializationRegistry>? _Serializers;
private IBuilder<InjectionRegistry>? _Injectors;
private IBuilder<FormatterRegistry>? _Formatters;
#region Functionality
/// <summary>
/// Configures the serialization registry to be used by this handler. Allows
/// to add support for additional formats such as protobuf.
/// </summary>
/// <param name="registry">The registry to be used by the handler</param>
public InlineBuilder Serializers(IBuilder<SerializationRegistry> registry)
{
_Serializers = registry;
return this;
}
/// <summary>
/// Configures the injectors to be used to extract complex parameter values.
/// </summary>
/// <param name="registry">The registry to be used by the handler</param>
public InlineBuilder Injectors(IBuilder<InjectionRegistry> registry)
{
_Injectors = registry;
return this;
}
/// <summary>
/// Configures the formatters to be used to extract path values.
/// </summary>
/// <param name="registry">The registry to be used by the handler</param>
public InlineBuilder Formatters(IBuilder<FormatterRegistry> registry)
{
_Formatters = registry;
return this;
}
/// <summary>
/// Adds a route for a request of any type to the root of the handler.
/// </summary>
/// <param name="function">The logic to be executed</param>
/// <param name="ignoreContent">True to exclude the content from sitemaps etc.</param>
/// <param name="contentHints">A type implementing IContentHints to allow content discovery</param>
public InlineBuilder Any(Delegate function, bool ignoreContent = false, Type? contentHints = null)
{
return On(function, ALL_METHODS, null, ignoreContent, contentHints);
}
/// <summary>
/// Adds a route for a request of any type to the specified path.
/// </summary>
/// <param name="path">The path of the request to handle (e.g. "/my-method")</param>
/// <param name="function">The logic to be executed</param>
/// <param name="ignoreContent">True to exclude the content from sitemaps etc.</param>
/// <param name="contentHints">A type implementing IContentHints to allow content discovery</param>
public InlineBuilder Any(string path, Delegate function, bool ignoreContent = false, Type? contentHints = null)
{
return On(function, ALL_METHODS, path, ignoreContent, contentHints);
}
/// <summary>
/// Adds a route for a GET request to the root of the handler.
/// </summary>
/// <param name="function">The logic to be executed</param>
/// <param name="ignoreContent">True to exclude the content from sitemaps etc.</param>
/// <param name="contentHints">A type implementing IContentHints to allow content discovery</param>
public InlineBuilder Get(Delegate function, bool ignoreContent = false, Type? contentHints = null)
{
return On(function, new() { FlexibleRequestMethod.Get(RequestMethod.GET) }, null, ignoreContent, contentHints);
}
/// <summary>
/// Adds a route for a GET request to the specified path.
/// </summary>
/// <param name="path">The path of the request to handle (e.g. "/my-method")</param>
/// <param name="function">The logic to be executed</param>
/// <param name="ignoreContent">True to exclude the content from sitemaps etc.</param>
/// <param name="contentHints">A type implementing IContentHints to allow content discovery</param>
public InlineBuilder Get(string path, Delegate function, bool ignoreContent = false, Type? contentHints = null)
{
return On(function, new() { FlexibleRequestMethod.Get(RequestMethod.GET) }, path, ignoreContent, contentHints);
}
/// <summary>
/// Adds a route for a HEAD request to the root of the handler.
/// </summary>
/// <param name="function">The logic to be executed</param>
public InlineBuilder Head(Delegate function) => On(function, new() { FlexibleRequestMethod.Get(RequestMethod.HEAD) });
/// <summary>
/// Adds a route for a HEAD request to the specified path.
/// </summary>
/// <param name="path">The path of the request to handle (e.g. "/my-method")</param>
public InlineBuilder Head(string path, Delegate function) => On(function, new() { FlexibleRequestMethod.Get(RequestMethod.HEAD) }, path);
/// <summary>
/// Adds a route for a POST request to the root of the handler.
/// </summary>
/// <param name="function">The logic to be executed</param>
public InlineBuilder Post(Delegate function) => On(function, new() { FlexibleRequestMethod.Get(RequestMethod.POST) });
/// <summary>
/// Adds a route for a POST request to the specified path.
/// </summary>
/// <param name="path">The path of the request to handle (e.g. "/my-method")</param>
public InlineBuilder Post(string path, Delegate function) => On(function, new() { FlexibleRequestMethod.Get(RequestMethod.POST) }, path);
/// <summary>
/// Adds a route for a PUT request to the root of the handler.
/// </summary>
/// <param name="function">The logic to be executed</param>
public InlineBuilder Put(Delegate function) => On(function, new() { FlexibleRequestMethod.Get(RequestMethod.PUT) });
/// <summary>
/// Adds a route for a PUT request to the specified path.
/// </summary>
/// <param name="path">The path of the request to handle (e.g. "/my-method")</param>
public InlineBuilder Put(string path, Delegate function) => On(function, new() { FlexibleRequestMethod.Get(RequestMethod.PUT) }, path);
/// <summary>
/// Adds a route for a DELETE request to the root of the handler.
/// </summary>
/// <param name="function">The logic to be executed</param>
public InlineBuilder Delete(Delegate function) => On(function, new() { FlexibleRequestMethod.Get(RequestMethod.DELETE) });
/// <summary>
/// Adds a route for a DELETE request to the specified path.
/// </summary>
/// <param name="path">The path of the request to handle (e.g. "/my-method")</param>
public InlineBuilder Delete(string path, Delegate function) => On(function, new() { FlexibleRequestMethod.Get(RequestMethod.DELETE) }, path);
/// <summary>
/// Executes the given function for the specified path and method.
/// </summary>
/// <param name="function">The logic to be executed</param>
/// <param name="methods">The HTTP verbs to respond to</param>
/// <param name="path">The path which needs to be specified by the client to call this logic</param>
/// <param name="ignoreContent">True to exclude the content from sitemaps etc.</param>
/// <param name="contentHints">A type implementing IContentHints to allow content discovery</param>
public InlineBuilder On(Delegate function, HashSet<FlexibleRequestMethod>? methods = null, string? path = null, bool ignoreContent = false, Type? contentHints = null)
{
var requestMethods = methods ?? new HashSet<FlexibleRequestMethod>();
if (requestMethods.Count == 1 && requestMethods.Contains(FlexibleRequestMethod.Get(RequestMethod.GET)))
{
requestMethods.Add(FlexibleRequestMethod.Get(RequestMethod.HEAD));
}
if (path?.StartsWith('/') == true)
{
path = path[1..];
}
var config = new MethodConfiguration(requestMethods, ignoreContent, contentHints);
_Functions.Add(new InlineFunction(path, config, function));
return this;
}
public InlineBuilder Add(IConcernBuilder concern)
{
_Concerns.Add(concern);
return this;
}
public IHandler Build(IHandler parent)
{
var serializers = (_Serializers ?? Serialization.Default()).Build();
var injectors = (_Injectors ?? Injection.Default()).Build();
var formatters = (_Formatters ?? Formatting.Default()).Build();
return Concerns.Chain(parent, _Concerns, (p) => new InlineHandler(p, _Functions, serializers, injectors, formatters));
}
#endregion
}
}