Skip to content

Commit bfd4660

Browse files
authored
Internal server error if there are multiple matching callbacks (#272)
1 parent 58659be commit bfd4660

File tree

10 files changed

+1031
-49
lines changed

10 files changed

+1031
-49
lines changed

.editorconfig

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
# EditorConfig for Visual Studio 2022: https://learn.microsoft.com/en-us/visualstudio/ide/create-portable-custom-editor-options?view=vs-2022
2+
3+
# This is a top-most .editorconfig file
4+
root = true
5+
6+
#=====================================================
7+
#
8+
# nanoFramework specific settings
9+
#
10+
#
11+
#=====================================================
12+
[*]
13+
# Generic EditorConfig settings
14+
end_of_line = crlf
15+
charset = utf-8-bom
16+
17+
# Visual Studio spell checker
18+
spelling_languages = en-us
19+
spelling_checkable_types = strings,identifiers,comments
20+
spelling_error_severity = information
21+
spelling_exclusion_path = spelling_exclusion.dic
22+
23+
#=====================================================
24+
#
25+
# Settings copied from the .NET runtime
26+
#
27+
# https://github.com/dotnet/runtime
28+
#
29+
#=====================================================
30+
# Default settings:
31+
# A newline ending every file
32+
# Use 4 spaces as indentation
33+
insert_final_newline = true
34+
indent_style = space
35+
indent_size = 4
36+
trim_trailing_whitespace = true
37+
38+
# Generated code
39+
[*{_AssemblyInfo.cs,.notsupported.cs,AsmOffsets.cs}]
40+
generated_code = true
41+
42+
# C# files
43+
[*.cs]
44+
# New line preferences
45+
csharp_new_line_before_open_brace = all
46+
csharp_new_line_before_else = true
47+
csharp_new_line_before_catch = true
48+
csharp_new_line_before_finally = true
49+
csharp_new_line_before_members_in_object_initializers = true
50+
csharp_new_line_before_members_in_anonymous_types = true
51+
csharp_new_line_between_query_expression_clauses = true
52+
53+
# Indentation preferences
54+
csharp_indent_block_contents = true
55+
csharp_indent_braces = false
56+
csharp_indent_case_contents = true
57+
csharp_indent_case_contents_when_block = false
58+
csharp_indent_switch_labels = true
59+
csharp_indent_labels = one_less_than_current
60+
61+
# Modifier preferences
62+
csharp_preferred_modifier_order = public,private,protected,internal,file,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,required,volatile,async:suggestion
63+
64+
# avoid this. unless absolutely necessary
65+
dotnet_style_qualification_for_field = false:suggestion
66+
dotnet_style_qualification_for_property = false:suggestion
67+
dotnet_style_qualification_for_method = false:suggestion
68+
dotnet_style_qualification_for_event = false:suggestion
69+
70+
# Types: use keywords instead of BCL types, and permit var only when the type is clear
71+
csharp_style_var_for_built_in_types = false:suggestion
72+
csharp_style_var_when_type_is_apparent = false:none
73+
csharp_style_var_elsewhere = false:suggestion
74+
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
75+
dotnet_style_predefined_type_for_member_access = true:suggestion
76+
77+
# name all constant fields using PascalCase
78+
dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion
79+
dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields
80+
dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style
81+
dotnet_naming_symbols.constant_fields.applicable_kinds = field
82+
dotnet_naming_symbols.constant_fields.required_modifiers = const
83+
dotnet_naming_style.pascal_case_style.capitalization = pascal_case
84+
85+
# static fields should have s_ prefix
86+
dotnet_naming_rule.static_fields_should_have_prefix.severity = suggestion
87+
dotnet_naming_rule.static_fields_should_have_prefix.symbols = static_fields
88+
dotnet_naming_rule.static_fields_should_have_prefix.style = static_prefix_style
89+
dotnet_naming_symbols.static_fields.applicable_kinds = field
90+
dotnet_naming_symbols.static_fields.required_modifiers = static
91+
dotnet_naming_symbols.static_fields.applicable_accessibilities = private, internal, private_protected
92+
dotnet_naming_style.static_prefix_style.required_prefix = s_
93+
dotnet_naming_style.static_prefix_style.capitalization = camel_case
94+
95+
# internal and private fields should be _camelCase
96+
dotnet_naming_rule.camel_case_for_private_internal_fields.severity = suggestion
97+
dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields
98+
dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style
99+
dotnet_naming_symbols.private_internal_fields.applicable_kinds = field
100+
dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal
101+
dotnet_naming_style.camel_case_underscore_style.required_prefix = _
102+
dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case
103+
104+
# Code style defaults
105+
csharp_using_directive_placement = outside_namespace:suggestion
106+
dotnet_sort_system_directives_first = true
107+
csharp_prefer_braces = true:silent
108+
csharp_preserve_single_line_blocks = true:none
109+
csharp_preserve_single_line_statements = false:none
110+
csharp_prefer_static_local_function = true:suggestion
111+
csharp_prefer_simple_using_statement = false:none
112+
csharp_style_prefer_switch_expression = true:suggestion
113+
dotnet_style_readonly_field = true:suggestion
114+
115+
# Expression-level preferences
116+
dotnet_style_object_initializer = true:suggestion
117+
dotnet_style_collection_initializer = true:suggestion
118+
dotnet_style_prefer_collection_expression = when_types_exactly_match
119+
dotnet_style_explicit_tuple_names = true:suggestion
120+
dotnet_style_coalesce_expression = true:suggestion
121+
dotnet_style_null_propagation = true:suggestion
122+
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
123+
dotnet_style_prefer_inferred_tuple_names = true:suggestion
124+
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
125+
dotnet_style_prefer_auto_properties = true:suggestion
126+
dotnet_style_prefer_conditional_expression_over_assignment = true:silent
127+
dotnet_style_prefer_conditional_expression_over_return = true:silent
128+
csharp_prefer_simple_default_expression = true:suggestion
129+
130+
# Expression-bodied members
131+
csharp_style_expression_bodied_methods = true:silent
132+
csharp_style_expression_bodied_constructors = true:silent
133+
csharp_style_expression_bodied_operators = true:silent
134+
csharp_style_expression_bodied_properties = true:silent
135+
csharp_style_expression_bodied_indexers = true:silent
136+
csharp_style_expression_bodied_accessors = true:silent
137+
csharp_style_expression_bodied_lambdas = true:silent
138+
csharp_style_expression_bodied_local_functions = true:silent
139+
140+
# Pattern matching
141+
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
142+
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
143+
csharp_style_inlined_variable_declaration = true:suggestion
144+
145+
# Null checking preferences
146+
csharp_style_throw_expression = true:suggestion
147+
csharp_style_conditional_delegate_call = true:suggestion
148+
149+
# Other features
150+
csharp_style_prefer_index_operator = false:none
151+
csharp_style_prefer_range_operator = false:none
152+
csharp_style_pattern_local_over_anonymous_function = false:none
153+
154+
# Space preferences
155+
csharp_space_after_cast = false
156+
csharp_space_after_colon_in_inheritance_clause = true
157+
csharp_space_after_comma = true
158+
csharp_space_after_dot = false
159+
csharp_space_after_keywords_in_control_flow_statements = true
160+
csharp_space_after_semicolon_in_for_statement = true
161+
csharp_space_around_binary_operators = before_and_after
162+
csharp_space_around_declaration_statements = do_not_ignore
163+
csharp_space_before_colon_in_inheritance_clause = true
164+
csharp_space_before_comma = false
165+
csharp_space_before_dot = false
166+
csharp_space_before_open_square_brackets = false
167+
csharp_space_before_semicolon_in_for_statement = false
168+
csharp_space_between_empty_square_brackets = false
169+
csharp_space_between_method_call_empty_parameter_list_parentheses = false
170+
csharp_space_between_method_call_name_and_opening_parenthesis = false
171+
csharp_space_between_method_call_parameter_list_parentheses = false
172+
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
173+
csharp_space_between_method_declaration_name_and_open_parenthesis = false
174+
csharp_space_between_method_declaration_parameter_list_parentheses = false
175+
csharp_space_between_parentheses = false
176+
csharp_space_between_square_brackets = false
177+
178+
# License header
179+
file_header_template = Licensed to the .NET Foundation under one or more agreements.\nThe .NET Foundation licenses this file to you under the MIT license.
180+
181+
# C++ Files
182+
[*.{cpp,h,in}]
183+
curly_bracket_next_line = true
184+
indent_brace_style = Allman
185+
186+
# Xml project files
187+
[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,nativeproj,locproj}]
188+
indent_size = 2
189+
190+
[*.{csproj,vbproj,proj,nativeproj,locproj}]
191+
charset = utf-8
192+
193+
# Xml build files
194+
[*.builds]
195+
indent_size = 2
196+
197+
# Xml files
198+
[*.{xml,stylecop,resx,ruleset}]
199+
indent_size = 2
200+
201+
# Xml config files
202+
[*.{props,targets,config,nuspec}]
203+
indent_size = 2
204+
205+
# YAML config files
206+
[*.{yml,yaml}]
207+
indent_size = 2
208+
209+
# Shell scripts
210+
[*.sh]
211+
end_of_line = lf
212+
[*.{cmd,bat}]
213+
end_of_line = crlf

README.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,53 @@ With the previous example the following happens:
196196

197197
All up, this is an example to show how to use authentication, it's been defined to allow flexibility.
198198

199+
The webserver supports having multiple authentication methods or credentials for the same route. Each pair of authentication method plus credentials should have its own method in the controller:
200+
201+
```csharp
202+
class MixedController
203+
{
204+
205+
[Route("sameroute")]
206+
[Authentication("Basic")]
207+
public void Basic(WebServerEventArgs e)
208+
{
209+
WebServer.OutPutStream(e.Context.Response, "sameroute: Basic");
210+
}
211+
212+
[Authentication("ApiKey:superKey1234")]
213+
[Route("sameroute")]
214+
public void Key(WebServerEventArgs e)
215+
{
216+
WebServer.OutPutStream(e.Context.Response, "sameroute: API key #1");
217+
}
218+
219+
[Authentication("ApiKey:superKey5678")]
220+
[Route("sameroute")]
221+
public void Key2(WebServerEventArgs e)
222+
{
223+
WebServer.OutPutStream(e.Context.Response, "sameroute: API key #2");
224+
}
225+
226+
[Route("sameroute")]
227+
public void None(WebServerEventArgs e)
228+
{
229+
WebServer.OutPutStream(e.Context.Response, "sameroute: Public");
230+
}
231+
}
232+
```
233+
234+
The webserver selects the route for a request:
235+
236+
- If there are no matching methods, a not-found response (404) is returned.
237+
- If authentication information is passed in the header of the request, then only methods that require authentication are considered. If one of the method's credentials matches the credentials passed in the request, that method is called. Otherwise a non-authorized response (401) will be returned.
238+
- If no authentication information is passed in the header of the request:
239+
- If one of the methods does not require authentication, that method is called.
240+
- Otherwise a non-authorized response (401) will be returned. If one of the methods requires basic authentication, the `WWW-Authenticate` header is included to request credentials.
241+
242+
The webserver does not support more than one matching method. Calling multiple methods most likely results in an exception as a subsequent method tries to modify a response that is already processed by the first method. The webserver does not know what to do and returns an internal server error (500). The body of the response lists the matching methods.
243+
244+
Having multiple matching methods is considered a programming error. One way this occurs is if two methods in a controller accidentally have the same route. Returning an internal server error with the names of the methods makes it easy to discover the error. It is expected that the error is discovered and fixed in testing. Then the internal error will not occur in the application that is deployed to a device.
245+
199246
## Managing incoming queries thru events
200247

201248
Very basic usage is the following:

0 commit comments

Comments
 (0)