├── .editorconfig ├── .github └── workflows │ ├── build.yaml │ ├── pr.yaml │ └── release-all.yaml ├── .gitignore ├── .mailmap ├── Aliencube.AzureFunctions.Extensions.sln ├── Aliencube.AzureFunctions.Extensions.sln.DotSettings ├── LICENSE ├── README.md ├── Settings.StyleCop ├── builds └── common.props ├── docs └── common.md ├── icons └── Aliencube.AzureFunctions.Extensions.Common.png ├── release-notes ├── common-1.0.0.md └── common-1.1.0.md ├── src └── Aliencube.AzureFunctions.Extensions.Common │ ├── Aliencube.AzureFunctions.Extensions.Common.csproj │ ├── ContentTypes.cs │ ├── ExceptionMessages.cs │ ├── HttpRequestExtensions.cs │ ├── HttpVerbs.cs │ ├── OpenApiFormatExtensions.cs │ ├── PayloadExtensions.cs │ └── SourceFrom.cs └── test └── Aliencube.AzureFunctions.Extensions.Common.Tests ├── Aliencube.AzureFunctions.Extensions.Common.Tests.csproj ├── HttpRequestExtensionsTests.cs ├── Models ├── FakeRequestHeader.cs ├── FakeRequestModel.cs └── FakeRequestQuery.cs ├── OpenApiFormatExtensionsTests.cs └── PayloadExtensionsTests.cs /.editorconfig: -------------------------------------------------------------------------------- 1 | # Version: 1.3.1 (Using https://semver.org/) 2 | # Updated: 2019-08-04 3 | # See https://github.com/RehanSaeed/EditorConfig/releases for release notes. 4 | # See https://github.com/RehanSaeed/EditorConfig for updates to this file. 5 | # See http://EditorConfig.org for more information about .editorconfig files. 6 | 7 | ########################################## 8 | # Common Settings 9 | ########################################## 10 | 11 | # This file is the top-most EditorConfig file 12 | root = true 13 | 14 | # All Files 15 | [*] 16 | charset = utf-8 17 | indent_style = space 18 | indent_size = 4 19 | insert_final_newline = true 20 | trim_trailing_whitespace = true 21 | 22 | ########################################## 23 | # File Extension Settings 24 | ########################################## 25 | 26 | # Visual Studio Solution Files 27 | [*.sln] 28 | indent_style = tab 29 | 30 | # Visual Studio XML Project Files 31 | [*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}] 32 | indent_size = 2 33 | 34 | # Various XML Configuration Files 35 | [*.{xml,config,props,targets,nuspec,resx,ruleset,vsixmanifest,vsct}] 36 | indent_size = 2 37 | 38 | # JSON Files 39 | [*.{json,json5}] 40 | indent_size = 2 41 | 42 | # YAML Files 43 | [*.{yml,yaml}] 44 | indent_size = 2 45 | 46 | # Markdown Files 47 | [*.md] 48 | trim_trailing_whitespace = false 49 | 50 | # Web Files 51 | [*.{htm,html,js,ts,tsx,css,sass,scss,less,svg,vue}] 52 | indent_size = 2 53 | 54 | # Batch Files 55 | [*.{cmd,bat}] 56 | 57 | # Bash Files 58 | [*.sh] 59 | end_of_line = lf 60 | 61 | ########################################## 62 | # .NET Language Conventions 63 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions 64 | ########################################## 65 | 66 | # .NET Code Style Settings 67 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#net-code-style-settings 68 | [*.{cs,csx,cake,vb}] 69 | # "this." and "Me." qualifiers 70 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#this-and-me 71 | dotnet_style_qualification_for_field = true:warning 72 | dotnet_style_qualification_for_property = true:warning 73 | dotnet_style_qualification_for_method = true:warning 74 | dotnet_style_qualification_for_event = true:warning 75 | # Language keywords instead of framework type names for type references 76 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#language-keywords 77 | dotnet_style_predefined_type_for_locals_parameters_members = true:warning 78 | dotnet_style_predefined_type_for_member_access = true:warning 79 | # Modifier preferences 80 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#normalize-modifiers 81 | dotnet_style_require_accessibility_modifiers = always:warning 82 | csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async 83 | visual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async 84 | dotnet_style_readonly_field = true:warning 85 | # Parentheses preferences 86 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#parentheses-preferences 87 | dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:warning 88 | dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:warning 89 | dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:warning 90 | dotnet_style_parentheses_in_other_operators = never_if_unnecessary:suggestion 91 | # Expression-level preferences 92 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#expression-level-preferences 93 | dotnet_style_object_initializer = true:warning 94 | dotnet_style_collection_initializer = true:warning 95 | dotnet_style_explicit_tuple_names = true:warning 96 | dotnet_style_prefer_inferred_tuple_names = true:warning 97 | dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning 98 | dotnet_style_prefer_auto_properties = true:warning 99 | dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning 100 | dotnet_style_prefer_conditional_expression_over_assignment = false:suggestion 101 | dotnet_style_prefer_conditional_expression_over_return = false:suggestion 102 | dotnet_style_prefer_compound_assignment = true:warning 103 | # Null-checking preferences 104 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#null-checking-preferences 105 | dotnet_style_coalesce_expression = true:warning 106 | dotnet_style_null_propagation = true:warning 107 | # Parameter preferences 108 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#parameter-preferences 109 | dotnet_code_quality_unused_parameters = all:warning 110 | # More style options (Undocumented) 111 | # https://github.com/MicrosoftDocs/visualstudio-docs/issues/3641 112 | dotnet_style_operator_placement_when_wrapping = end_of_line 113 | 114 | # C# Code Style Settings 115 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#c-code-style-settings 116 | [*.{cs,csx,cake}] 117 | # Implicit and explicit types 118 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#implicit-and-explicit-types 119 | csharp_style_var_for_built_in_types = true:warning 120 | csharp_style_var_when_type_is_apparent = true:warning 121 | csharp_style_var_elsewhere = true:warning 122 | # Expression-bodied members 123 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#expression-bodied-members 124 | # IDE0022 125 | csharp_style_expression_bodied_methods = false:silent 126 | # IDE0021 127 | csharp_style_expression_bodied_constructors = false:silent 128 | # IDE0023, IDE0024 129 | csharp_style_expression_bodied_operators = false:silent 130 | # IDE0025 131 | csharp_style_expression_bodied_properties = true:silent 132 | # IDE0026 133 | csharp_style_expression_bodied_indexers = true:silent 134 | # IDE0027 135 | csharp_style_expression_bodied_accessors = true:silent 136 | # IDE0053 137 | csharp_style_expression_bodied_lambdas = true:silent 138 | # IDE0061 139 | csharp_style_expression_bodied_local_functions = false:silent 140 | # Pattern matching 141 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#pattern-matching 142 | csharp_style_pattern_matching_over_is_with_cast_check = true:warning 143 | csharp_style_pattern_matching_over_as_with_null_check = true:warning 144 | # Inlined variable declarations 145 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#inlined-variable-declarations 146 | csharp_style_inlined_variable_declaration = true:warning 147 | # Expression-level preferences 148 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#expression-level-preferences 149 | csharp_prefer_simple_default_expression = true:warning 150 | # "Null" checking preferences 151 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#c-null-checking-preferences 152 | csharp_style_throw_expression = true:warning 153 | csharp_style_conditional_delegate_call = true:warning 154 | # Code block preferences 155 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#code-block-preferences 156 | csharp_prefer_braces = true:warning 157 | # Unused value preferences 158 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#unused-value-preferences 159 | csharp_style_unused_value_expression_statement_preference = discard_variable:suggestion 160 | csharp_style_unused_value_assignment_preference = discard_variable:suggestion 161 | # Index and range preferences 162 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#index-and-range-preferences 163 | csharp_style_prefer_index_operator = true:warning 164 | csharp_style_prefer_range_operator = true:warning 165 | # Miscellaneous preferences 166 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#miscellaneous-preferences 167 | csharp_style_deconstructed_variable_declaration = true:warning 168 | csharp_style_pattern_local_over_anonymous_function = true:warning 169 | csharp_using_directive_placement = outside_namespace:warning 170 | csharp_prefer_static_local_function = true:warning 171 | csharp_prefer_simple_using_statement = false:warning 172 | 173 | ########################################## 174 | # .NET Formatting Conventions 175 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-code-style-settings-reference#formatting-conventions 176 | ########################################## 177 | 178 | # Organize usings 179 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#organize-using-directives 180 | dotnet_sort_system_directives_first = always:error 181 | dotnet_separate_import_directive_groups = always:error 182 | # Newline options 183 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#new-line-options 184 | csharp_new_line_before_open_brace = all 185 | csharp_new_line_before_else = true 186 | csharp_new_line_before_catch = true 187 | csharp_new_line_before_finally = true 188 | csharp_new_line_before_members_in_object_initializers = true 189 | csharp_new_line_before_members_in_anonymous_types = true 190 | csharp_new_line_between_query_expression_clauses = true 191 | # Indentation options 192 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#indentation-options 193 | csharp_indent_case_contents = true 194 | csharp_indent_switch_labels = true 195 | csharp_indent_labels = no_change 196 | csharp_indent_block_contents = true 197 | csharp_indent_braces = false 198 | csharp_indent_case_contents_when_block = false 199 | # Spacing options 200 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#spacing-options 201 | csharp_space_after_cast = false 202 | csharp_space_after_keywords_in_control_flow_statements = true 203 | csharp_space_between_parentheses = false 204 | csharp_space_before_colon_in_inheritance_clause = true 205 | csharp_space_after_colon_in_inheritance_clause = true 206 | csharp_space_around_binary_operators = before_and_after 207 | csharp_space_between_method_declaration_parameter_list_parentheses = false 208 | csharp_space_between_method_declaration_empty_parameter_list_parentheses = false 209 | csharp_space_between_method_declaration_name_and_open_parenthesis = false 210 | csharp_space_between_method_call_parameter_list_parentheses = false 211 | csharp_space_between_method_call_empty_parameter_list_parentheses = false 212 | csharp_space_between_method_call_name_and_opening_parenthesis = false 213 | csharp_space_after_comma = true 214 | csharp_space_before_comma = false 215 | csharp_space_after_dot = false 216 | csharp_space_before_dot = false 217 | csharp_space_after_semicolon_in_for_statement = true 218 | csharp_space_before_semicolon_in_for_statement = false 219 | csharp_space_around_declaration_statements = false 220 | csharp_space_before_open_square_brackets = false 221 | csharp_space_between_empty_square_brackets = false 222 | csharp_space_between_square_brackets = false 223 | # Wrapping options 224 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#wrap-options 225 | csharp_preserve_single_line_statements = false 226 | csharp_preserve_single_line_blocks = true 227 | 228 | ########################################## 229 | # .NET Naming Conventions 230 | # https://docs.microsoft.com/visualstudio/ide/editorconfig-naming-conventions 231 | ########################################## 232 | 233 | [*.{cs,csx,cake,vb}] 234 | 235 | ########################################## 236 | # Styles 237 | ########################################## 238 | 239 | # camel_case_style - Define the camelCase style 240 | dotnet_naming_style.camel_case_style.capitalization = camel_case 241 | # pascal_case_style - Define the PascalCase style 242 | dotnet_naming_style.pascal_case_style.capitalization = pascal_case 243 | # first_upper_style - The first character must start with an upper-case character 244 | dotnet_naming_style.first_upper_style.capitalization = first_word_upper 245 | # prefix_interface_with_i_style - Interfaces must be PascalCase and the first character of an interface must be an 'I' 246 | dotnet_naming_style.prefix_interface_with_i_style.capitalization = pascal_case 247 | dotnet_naming_style.prefix_interface_with_i_style.required_prefix = I 248 | # prefix_type_parameters_with_t_style - Generic Type Parameters must be PascalCase and the first character must be a 'T' 249 | dotnet_naming_style.prefix_type_parameters_with_t_style.capitalization = pascal_case 250 | dotnet_naming_style.prefix_type_parameters_with_t_style.required_prefix = T 251 | # disallowed_style - Anything that has this style applied is marked as disallowed 252 | dotnet_naming_style.disallowed_style.capitalization = pascal_case 253 | dotnet_naming_style.disallowed_style.required_prefix = ____RULE_VIOLATION____ 254 | dotnet_naming_style.disallowed_style.required_suffix = ____RULE_VIOLATION____ 255 | # internal_error_style - This style should never occur... if it does, it's indicates a bug in file or in the parser using the file 256 | dotnet_naming_style.internal_error_style.capitalization = pascal_case 257 | dotnet_naming_style.internal_error_style.required_prefix = ____INTERNAL_ERROR____ 258 | dotnet_naming_style.internal_error_style.required_suffix = ____INTERNAL_ERROR____ 259 | 260 | ########################################## 261 | # .NET Design Guideline Field Naming Rules 262 | # Naming rules for fields follow the .NET Framework design guidelines 263 | # https://docs.microsoft.com/dotnet/standard/design-guidelines/index 264 | ########################################## 265 | 266 | # All public/protected/protected_internal constant fields must be PascalCase 267 | # https://docs.microsoft.com/dotnet/standard/design-guidelines/field 268 | dotnet_naming_symbols.public_protected_constant_fields_group.applicable_accessibilities = public, protected, protected_internal 269 | dotnet_naming_symbols.public_protected_constant_fields_group.required_modifiers = const 270 | dotnet_naming_symbols.public_protected_constant_fields_group.applicable_kinds = field 271 | dotnet_naming_rule.public_protected_constant_fields_must_be_pascal_case_rule.symbols = public_protected_constant_fields_group 272 | dotnet_naming_rule.public_protected_constant_fields_must_be_pascal_case_rule.style = pascal_case_style 273 | dotnet_naming_rule.public_protected_constant_fields_must_be_pascal_case_rule.severity = warning 274 | 275 | # All public/protected/protected_internal static readonly fields must be PascalCase 276 | # https://docs.microsoft.com/dotnet/standard/design-guidelines/field 277 | dotnet_naming_symbols.public_protected_static_readonly_fields_group.applicable_accessibilities = public, protected, protected_internal 278 | dotnet_naming_symbols.public_protected_static_readonly_fields_group.required_modifiers = static, readonly 279 | dotnet_naming_symbols.public_protected_static_readonly_fields_group.applicable_kinds = field 280 | dotnet_naming_rule.public_protected_static_readonly_fields_must_be_pascal_case_rule.symbols = public_protected_static_readonly_fields_group 281 | dotnet_naming_rule.public_protected_static_readonly_fields_must_be_pascal_case_rule.style = pascal_case_style 282 | dotnet_naming_rule.public_protected_static_readonly_fields_must_be_pascal_case_rule.severity = warning 283 | 284 | # No other public/protected/protected_internal fields are allowed 285 | # https://docs.microsoft.com/dotnet/standard/design-guidelines/field 286 | dotnet_naming_symbols.other_public_protected_fields_group.applicable_accessibilities = public, protected, protected_internal 287 | dotnet_naming_symbols.other_public_protected_fields_group.applicable_kinds = field 288 | dotnet_naming_rule.other_public_protected_fields_disallowed_rule.symbols = other_public_protected_fields_group 289 | dotnet_naming_rule.other_public_protected_fields_disallowed_rule.style = disallowed_style 290 | dotnet_naming_rule.other_public_protected_fields_disallowed_rule.severity = error 291 | 292 | ########################################## 293 | # StyleCop Field Naming Rules 294 | # Naming rules for fields follow the StyleCop analyzers 295 | # This does not override any rules using disallowed_style above 296 | # https://github.com/DotNetAnalyzers/StyleCopAnalyzers 297 | ########################################## 298 | 299 | # All constant fields must be PascalCase 300 | # https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1303.md 301 | dotnet_naming_symbols.stylecop_constant_fields_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected, private 302 | dotnet_naming_symbols.stylecop_constant_fields_group.required_modifiers = const 303 | dotnet_naming_symbols.stylecop_constant_fields_group.applicable_kinds = field 304 | dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.symbols = stylecop_constant_fields_group 305 | dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.style = pascal_case_style 306 | dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.severity = warning 307 | 308 | # All static readonly fields must be PascalCase 309 | # https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1311.md 310 | dotnet_naming_symbols.stylecop_static_readonly_fields_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected, private 311 | dotnet_naming_symbols.stylecop_static_readonly_fields_group.required_modifiers = static, readonly 312 | dotnet_naming_symbols.stylecop_static_readonly_fields_group.applicable_kinds = field 313 | dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.symbols = stylecop_static_readonly_fields_group 314 | dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.style = pascal_case_style 315 | dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.severity = warning 316 | 317 | # No non-private instance fields are allowed 318 | # https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1401.md 319 | dotnet_naming_symbols.stylecop_fields_must_be_private_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected 320 | dotnet_naming_symbols.stylecop_fields_must_be_private_group.applicable_kinds = field 321 | dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.symbols = stylecop_fields_must_be_private_group 322 | dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.style = disallowed_style 323 | dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.severity = error 324 | 325 | # Private fields must be camelCase 326 | # https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1306.md 327 | dotnet_naming_symbols.stylecop_private_fields_group.applicable_accessibilities = private 328 | dotnet_naming_symbols.stylecop_private_fields_group.applicable_kinds = field 329 | dotnet_naming_rule.stylecop_private_fields_must_be_camel_case_rule.symbols = stylecop_private_fields_group 330 | dotnet_naming_rule.stylecop_private_fields_must_be_camel_case_rule.style = camel_case_style 331 | dotnet_naming_rule.stylecop_private_fields_must_be_camel_case_rule.severity = warning 332 | 333 | # Local variables must be camelCase 334 | # https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1312.md 335 | dotnet_naming_symbols.stylecop_local_fields_group.applicable_accessibilities = local 336 | dotnet_naming_symbols.stylecop_local_fields_group.applicable_kinds = local 337 | dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.symbols = stylecop_local_fields_group 338 | dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.style = camel_case_style 339 | dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.severity = silent 340 | 341 | # This rule should never fire. However, it's included for at least two purposes: 342 | # First, it helps to understand, reason about, and root-case certain types of issues, such as bugs in .editorconfig parsers. 343 | # Second, it helps to raise immediate awareness if a new field type is added (as occurred recently in C#). 344 | dotnet_naming_symbols.sanity_check_uncovered_field_case_group.applicable_accessibilities = * 345 | dotnet_naming_symbols.sanity_check_uncovered_field_case_group.applicable_kinds = field 346 | dotnet_naming_rule.sanity_check_uncovered_field_case_rule.symbols = sanity_check_uncovered_field_case_group 347 | dotnet_naming_rule.sanity_check_uncovered_field_case_rule.style = internal_error_style 348 | dotnet_naming_rule.sanity_check_uncovered_field_case_rule.severity = error 349 | 350 | 351 | ########################################## 352 | # Other Naming Rules 353 | ########################################## 354 | 355 | # All of the following must be PascalCase: 356 | # - Namespaces 357 | # https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-namespaces 358 | # https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1300.md 359 | # - Classes and Enumerations 360 | # https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces 361 | # https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1300.md 362 | # - Delegates 363 | # https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces#names-of-common-types 364 | # - Constructors, Properties, Events, Methods 365 | # https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-type-members 366 | dotnet_naming_symbols.element_group.applicable_kinds = namespace, class, enum, struct, delegate, event, method, property 367 | dotnet_naming_rule.element_rule.symbols = element_group 368 | dotnet_naming_rule.element_rule.style = pascal_case_style 369 | dotnet_naming_rule.element_rule.severity = warning 370 | 371 | # Interfaces use PascalCase and are prefixed with uppercase 'I' 372 | # https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces 373 | dotnet_naming_symbols.interface_group.applicable_kinds = interface 374 | dotnet_naming_rule.interface_rule.symbols = interface_group 375 | dotnet_naming_rule.interface_rule.style = prefix_interface_with_i_style 376 | dotnet_naming_rule.interface_rule.severity = warning 377 | 378 | # Generics Type Parameters use PascalCase and are prefixed with uppercase 'T' 379 | # https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces 380 | dotnet_naming_symbols.type_parameter_group.applicable_kinds = type_parameter 381 | dotnet_naming_rule.type_parameter_rule.symbols = type_parameter_group 382 | dotnet_naming_rule.type_parameter_rule.style = prefix_type_parameters_with_t_style 383 | dotnet_naming_rule.type_parameter_rule.severity = warning 384 | 385 | # Function parameters use camelCase 386 | # https://docs.microsoft.com/dotnet/standard/design-guidelines/naming-parameters 387 | dotnet_naming_symbols.parameters_group.applicable_kinds = parameter 388 | dotnet_naming_rule.parameters_rule.symbols = parameters_group 389 | dotnet_naming_rule.parameters_rule.style = camel_case_style 390 | dotnet_naming_rule.parameters_rule.severity = warning 391 | 392 | ########################################## 393 | # License 394 | ########################################## 395 | # The following applies as to the .editorconfig file ONLY, and is 396 | # included below for reference, per the requirements of the license 397 | # corresponding to this .editorconfig file. 398 | # See: https://github.com/RehanSaeed/EditorConfig 399 | # 400 | # MIT License 401 | # 402 | # Copyright (c) 2017-2019 Muhammad Rehan Saeed 403 | # Copyright (c) 2019 Henry Gabryjelski 404 | # 405 | # Permission is hereby granted, free of charge, to any 406 | # person obtaining a copy of this software and associated 407 | # documentation files (the "Software"), to deal in the 408 | # Software without restriction, including without limitation 409 | # the rights to use, copy, modify, merge, publish, distribute, 410 | # sublicense, and/or sell copies of the Software, and to permit 411 | # persons to whom the Software is furnished to do so, subject 412 | # to the following conditions: 413 | # 414 | # The above copyright notice and this permission notice shall be 415 | # included in all copies or substantial portions of the Software. 416 | # 417 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 418 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 419 | # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 420 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 421 | # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 422 | # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 423 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 424 | # OTHER DEALINGS IN THE SOFTWARE. 425 | ########################################## 426 | -------------------------------------------------------------------------------- /.github/workflows/build.yaml: -------------------------------------------------------------------------------- 1 | name: Build and Test 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - feature/* 8 | 9 | jobs: 10 | build_and_test: 11 | name: Build and test 12 | strategy: 13 | matrix: 14 | os: [ 'windows-latest', 'ubuntu-latest', 'macos-latest' ] 15 | 16 | runs-on: ${{ matrix.os }} 17 | 18 | steps: 19 | - name: Checkout the repository 20 | uses: actions/checkout@v2 21 | 22 | - name: Setup .NET SDK 6 23 | uses: actions/setup-dotnet@v1 24 | with: 25 | dotnet-version: '6.x' 26 | 27 | # - name: Add MSBuild to PATH 28 | # uses: microsoft/setup-msbuild@v1.0.0 29 | 30 | - name: Restore NuGet packages 31 | shell: pwsh 32 | run: | 33 | dir 34 | dotnet restore . 35 | 36 | - name: Build solution 37 | shell: pwsh 38 | run: | 39 | dir 40 | dotnet build . -c Debug -v minimal 41 | 42 | - name: Test solution 43 | shell: pwsh 44 | run: | 45 | dir 46 | dotnet test . -c Debug 47 | -------------------------------------------------------------------------------- /.github/workflows/pr.yaml: -------------------------------------------------------------------------------- 1 | name: Pull Request 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | build_and_test: 10 | name: Build and test 11 | strategy: 12 | matrix: 13 | os: [ 'windows-latest', 'ubuntu-latest', 'macos-latest' ] 14 | 15 | runs-on: ${{ matrix.os }} 16 | 17 | steps: 18 | - name: Checkout the repository 19 | uses: actions/checkout@v2 20 | 21 | - name: Setup .NET SDK 6 22 | uses: actions/setup-dotnet@v1 23 | with: 24 | dotnet-version: '6.x' 25 | 26 | # - name: Add MSBuild to PATH 27 | # uses: microsoft/setup-msbuild@v1.0.0 28 | 29 | - name: Restore NuGet packages 30 | shell: pwsh 31 | run: | 32 | dir 33 | dotnet restore . 34 | 35 | - name: Build solution 36 | shell: pwsh 37 | run: | 38 | dir 39 | dotnet build . -c Debug -v minimal 40 | 41 | - name: Test solution 42 | shell: pwsh 43 | run: | 44 | dir 45 | dotnet test . -c Debug 46 | -------------------------------------------------------------------------------- /.github/workflows/release-all.yaml: -------------------------------------------------------------------------------- 1 | name: Release NuGet 2 | 3 | on: 4 | push: 5 | branches: 6 | - release/common-* 7 | 8 | jobs: 9 | build_test_package_release: 10 | name: Build, test, package and release 11 | strategy: 12 | matrix: 13 | os: [ 'windows-latest' ] 14 | 15 | runs-on: ${{ matrix.os }} 16 | 17 | steps: 18 | # - name: Check event payload 19 | # shell: pwsh 20 | # run: | 21 | # echo ${{ toJSON(github.event) }} 22 | 23 | - name: Set release module and version 24 | id: release 25 | shell: pwsh 26 | run: | 27 | $branch = "${{ github.event.ref }}" -replace "refs/heads/release/", "" 28 | $segments = $branch -split "-" 29 | $module = $segments[0] 30 | $version = $segments[1] 31 | 32 | echo "::set-output name=module::$module" 33 | echo "::set-output name=version::$version" 34 | 35 | - name: Check release module and version 36 | shell: pwsh 37 | run: | 38 | echo "module: ${{ steps.release.outputs.module }}" 39 | echo "version: ${{ steps.release.outputs.version }}" 40 | 41 | - name: Checkout the repository 42 | uses: actions/checkout@v2 43 | 44 | - name: Setup .NET SDK 6 45 | uses: actions/setup-dotnet@v1 46 | with: 47 | dotnet-version: '6.x' 48 | 49 | # - name: Add MSBuild to PATH 50 | # uses: microsoft/setup-msbuild@v1.0.0 51 | 52 | - name: Restore NuGet packages 53 | shell: pwsh 54 | run: | 55 | dir 56 | dotnet restore . 57 | 58 | - name: Build solution for Common 59 | if: steps.release.outputs.module == 'common' 60 | shell: pwsh 61 | run: | 62 | dir 63 | dotnet build ./src/Aliencube.AzureFunctions.Extensions.Common -c Release -p:Version=${{ steps.release.outputs.version }} -v minimal 64 | dotnet build ./test/Aliencube.AzureFunctions.Extensions.Common.Tests -c Release 65 | 66 | - name: Test solution for Common 67 | if: steps.release.outputs.module == 'common' 68 | shell: pwsh 69 | run: | 70 | dir 71 | dotnet test ./test/Aliencube.AzureFunctions.Extensions.Common.Tests -c Release 72 | 73 | - name: List Package for Common 74 | if: steps.release.outputs.module == 'common' 75 | id: package 76 | shell: pwsh 77 | run: | 78 | $package = Get-ChildItem -Path ./src/*.Common -Include *.nupkg -Recurse | Where-Object { $_.FullName -like "*${{ steps.release.outputs.version }}*" } 79 | $path = $package[0].FullName 80 | $name = $package[0].Name 81 | 82 | echo "::set-output name=path::$path" 83 | echo "::set-output name=name::$name" 84 | 85 | - name: Check package path and name 86 | shell: pwsh 87 | run: | 88 | echo "path: ${{ steps.package.outputs.path }}" 89 | echo "name: ${{ steps.package.outputs.name }}" 90 | 91 | - name: Create Release to GitHub 92 | id: ghrelease 93 | uses: actions/create-release@v1 94 | env: 95 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 96 | with: 97 | tag_name: "${{ steps.release.outputs.module }}-${{ steps.release.outputs.version }}" 98 | release_name: Release "${{ steps.release.outputs.module }}-v${{ steps.release.outputs.version }}" 99 | draft: false 100 | prerelease: false 101 | 102 | - name: Upload NuGet package to GitHub 103 | uses: actions/upload-release-asset@v1 104 | env: 105 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 106 | with: 107 | upload_url: ${{ steps.ghrelease.outputs.upload_url }} 108 | asset_path: ${{ steps.package.outputs.path }} 109 | asset_name: ${{ steps.package.outputs.name }} 110 | asset_content_type: application/octet-stream 111 | 112 | - name: Release to NuGet 113 | shell: pwsh 114 | run: | 115 | dotnet nuget push ${{ steps.package.outputs.path }} --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.NUGET_API_KEY }} 116 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # MSTest test Results 33 | [Tt]est[Rr]esult*/ 34 | [Bb]uild[Ll]og.* 35 | 36 | # NUNIT 37 | *.VisualState.xml 38 | TestResult.xml 39 | 40 | # Build Results of an ATL Project 41 | [Dd]ebugPS/ 42 | [Rr]eleasePS/ 43 | dlldata.c 44 | 45 | # .NET Core 46 | project.lock.json 47 | project.fragment.lock.json 48 | artifacts/ 49 | **/Properties/launchSettings.json 50 | 51 | *_i.c 52 | *_p.c 53 | *_i.h 54 | *.ilk 55 | *.meta 56 | *.obj 57 | *.pch 58 | *.pdb 59 | *.pgc 60 | *.pgd 61 | *.rsp 62 | *.sbr 63 | *.tlb 64 | *.tli 65 | *.tlh 66 | *.tmp 67 | *.tmp_proj 68 | *.log 69 | *.vspscc 70 | *.vssscc 71 | .builds 72 | *.pidb 73 | *.svclog 74 | *.scc 75 | 76 | # Chutzpah Test files 77 | _Chutzpah* 78 | 79 | # Visual C++ cache files 80 | ipch/ 81 | *.aps 82 | *.ncb 83 | *.opendb 84 | *.opensdf 85 | *.sdf 86 | *.cachefile 87 | *.VC.db 88 | *.VC.VC.opendb 89 | 90 | # Visual Studio profiler 91 | *.psess 92 | *.vsp 93 | *.vspx 94 | *.sap 95 | 96 | # TFS 2012 Local Workspace 97 | $tf/ 98 | 99 | # Guidance Automation Toolkit 100 | *.gpState 101 | 102 | # ReSharper is a .NET coding add-in 103 | _ReSharper*/ 104 | *.[Rr]e[Ss]harper 105 | *.DotSettings.user 106 | 107 | # JustCode is a .NET coding add-in 108 | .JustCode 109 | 110 | # TeamCity is a build add-in 111 | _TeamCity* 112 | 113 | # DotCover is a Code Coverage Tool 114 | *.dotCover 115 | 116 | # Visual Studio code coverage results 117 | *.coverage 118 | *.coveragexml 119 | 120 | # NCrunch 121 | _NCrunch_* 122 | .*crunch*.local.xml 123 | nCrunchTemp_* 124 | 125 | # MightyMoose 126 | *.mm.* 127 | AutoTest.Net/ 128 | 129 | # Web workbench (sass) 130 | .sass-cache/ 131 | 132 | # Installshield output folder 133 | [Ee]xpress/ 134 | 135 | # DocProject is a documentation generator add-in 136 | DocProject/buildhelp/ 137 | DocProject/Help/*.HxT 138 | DocProject/Help/*.HxC 139 | DocProject/Help/*.hhc 140 | DocProject/Help/*.hhk 141 | DocProject/Help/*.hhp 142 | DocProject/Help/Html2 143 | DocProject/Help/html 144 | 145 | # Click-Once directory 146 | publish/ 147 | 148 | # Publish Web Output 149 | *.[Pp]ublish.xml 150 | *.azurePubxml 151 | # TODO: Comment the next line if you want to checkin your web deploy settings 152 | # but database connection strings (with potential passwords) will be unencrypted 153 | *.pubxml 154 | *.publishproj 155 | 156 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 157 | # checkin your Azure Web App publish settings, but sensitive information contained 158 | # in these scripts will be unencrypted 159 | PublishScripts/ 160 | 161 | # NuGet Packages 162 | *.nupkg 163 | # The packages folder can be ignored because of Package Restore 164 | **/packages/* 165 | # except build/, which is used as an MSBuild target. 166 | !**/packages/build/ 167 | # Uncomment if necessary however generally it will be regenerated when needed 168 | #!**/packages/repositories.config 169 | # NuGet v3's project.json files produces more ignorable files 170 | *.nuget.props 171 | *.nuget.targets 172 | 173 | # Microsoft Azure Build Output 174 | csx/ 175 | *.build.csdef 176 | 177 | # Microsoft Azure Emulator 178 | ecf/ 179 | rcf/ 180 | 181 | # Windows Store app package directories and files 182 | AppPackages/ 183 | BundleArtifacts/ 184 | Package.StoreAssociation.xml 185 | _pkginfo.txt 186 | 187 | # Visual Studio cache files 188 | # files ending in .cache can be ignored 189 | *.[Cc]ache 190 | # but keep track of directories ending in .cache 191 | !*.[Cc]ache/ 192 | 193 | # Others 194 | ClientBin/ 195 | ~$* 196 | *~ 197 | *.dbmdl 198 | *.dbproj.schemaview 199 | *.jfm 200 | *.pfx 201 | *.publishsettings 202 | orleans.codegen.cs 203 | 204 | # Since there are multiple workflows, uncomment next line to ignore bower_components 205 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 206 | #bower_components/ 207 | 208 | # RIA/Silverlight projects 209 | Generated_Code/ 210 | 211 | # Backup & report files from converting an old project file 212 | # to a newer Visual Studio version. Backup files are not needed, 213 | # because we have git ;-) 214 | _UpgradeReport_Files/ 215 | Backup*/ 216 | UpgradeLog*.XML 217 | UpgradeLog*.htm 218 | 219 | # SQL Server files 220 | *.mdf 221 | *.ldf 222 | *.ndf 223 | 224 | # Business Intelligence projects 225 | *.rdl.data 226 | *.bim.layout 227 | *.bim_*.settings 228 | 229 | # Microsoft Fakes 230 | FakesAssemblies/ 231 | 232 | # GhostDoc plugin setting file 233 | *.GhostDoc.xml 234 | 235 | # Node.js Tools for Visual Studio 236 | .ntvs_analysis.dat 237 | node_modules/ 238 | 239 | # Typescript v1 declaration files 240 | typings/ 241 | 242 | # Visual Studio 6 build log 243 | *.plg 244 | 245 | # Visual Studio 6 workspace options file 246 | *.opt 247 | 248 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 249 | *.vbw 250 | 251 | # Visual Studio LightSwitch build output 252 | **/*.HTMLClient/GeneratedArtifacts 253 | **/*.DesktopClient/GeneratedArtifacts 254 | **/*.DesktopClient/ModelManifest.xml 255 | **/*.Server/GeneratedArtifacts 256 | **/*.Server/ModelManifest.xml 257 | _Pvt_Extensions 258 | 259 | # Paket dependency manager 260 | .paket/paket.exe 261 | paket-files/ 262 | 263 | # FAKE - F# Make 264 | .fake/ 265 | 266 | # JetBrains Rider 267 | .idea/ 268 | *.sln.iml 269 | 270 | # CodeRush 271 | .cr/ 272 | 273 | # Python Tools for Visual Studio (PTVS) 274 | __pycache__/ 275 | *.pyc 276 | 277 | # Cake - Uncomment if you are using it 278 | # tools/** 279 | # !tools/packages.config 280 | 281 | # Telerik's JustMock configuration file 282 | *.jmconfig 283 | 284 | # BizTalk build output 285 | *.btp.cs 286 | *.btm.cs 287 | *.odx.cs 288 | *.xsd.cs 289 | 290 | *.bak 291 | *.org 292 | outputs/ -------------------------------------------------------------------------------- /.mailmap: -------------------------------------------------------------------------------- 1 | # 2 | # This list is used by git-shortlog to fix a few botched name translations 3 | # in the git archive, either because the author's full name was messed up 4 | # and/or not always written the same way, making contributions from the 5 | # same person appearing not to be so. 6 | # 7 | # Reference: https://github.com/git/git/blob/master/.mailmap 8 | # 9 | 10 | Justin Yoo 11 | Justin Yoo 12 | Justin Yoo 13 | -------------------------------------------------------------------------------- /Aliencube.AzureFunctions.Extensions.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.0.31912.275 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A1CB6B0E-9E97-4823-910B-735DB69B1931}" 7 | ProjectSection(SolutionItems) = preProject 8 | .editorconfig = .editorconfig 9 | .gitignore = .gitignore 10 | .mailmap = .mailmap 11 | builds\common.props = builds\common.props 12 | LICENSE = LICENSE 13 | README.md = README.md 14 | Settings.StyleCop = Settings.StyleCop 15 | EndProjectSection 16 | EndProject 17 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{810145E0-41CF-4E24-BD9C-E7517498BA29}" 18 | EndProject 19 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{8B62E3FB-9062-4716-803A-1FA51FCE68BC}" 20 | EndProject 21 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aliencube.AzureFunctions.Extensions.Common.Tests", "test\Aliencube.AzureFunctions.Extensions.Common.Tests\Aliencube.AzureFunctions.Extensions.Common.Tests.csproj", "{20B730BA-77D1-4EC4-BC68-7BE497669268}" 22 | EndProject 23 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aliencube.AzureFunctions.Extensions.Common", "src\Aliencube.AzureFunctions.Extensions.Common\Aliencube.AzureFunctions.Extensions.Common.csproj", "{E765907E-4E63-426A-8763-0074AD0F0A56}" 24 | EndProject 25 | Global 26 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 27 | Debug|Any CPU = Debug|Any CPU 28 | Release|Any CPU = Release|Any CPU 29 | EndGlobalSection 30 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 31 | {20B730BA-77D1-4EC4-BC68-7BE497669268}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 32 | {20B730BA-77D1-4EC4-BC68-7BE497669268}.Debug|Any CPU.Build.0 = Debug|Any CPU 33 | {20B730BA-77D1-4EC4-BC68-7BE497669268}.Release|Any CPU.ActiveCfg = Release|Any CPU 34 | {20B730BA-77D1-4EC4-BC68-7BE497669268}.Release|Any CPU.Build.0 = Release|Any CPU 35 | {E765907E-4E63-426A-8763-0074AD0F0A56}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 36 | {E765907E-4E63-426A-8763-0074AD0F0A56}.Debug|Any CPU.Build.0 = Debug|Any CPU 37 | {E765907E-4E63-426A-8763-0074AD0F0A56}.Release|Any CPU.ActiveCfg = Release|Any CPU 38 | {E765907E-4E63-426A-8763-0074AD0F0A56}.Release|Any CPU.Build.0 = Release|Any CPU 39 | EndGlobalSection 40 | GlobalSection(SolutionProperties) = preSolution 41 | HideSolutionNode = FALSE 42 | EndGlobalSection 43 | GlobalSection(NestedProjects) = preSolution 44 | {20B730BA-77D1-4EC4-BC68-7BE497669268} = {8B62E3FB-9062-4716-803A-1FA51FCE68BC} 45 | {E765907E-4E63-426A-8763-0074AD0F0A56} = {810145E0-41CF-4E24-BD9C-E7517498BA29} 46 | EndGlobalSection 47 | GlobalSection(ExtensibilityGlobals) = postSolution 48 | SolutionGuid = {70FEC644-BB3C-4441-AF91-DC694803C8F2} 49 | EndGlobalSection 50 | EndGlobal 51 | -------------------------------------------------------------------------------- /Aliencube.AzureFunctions.Extensions.sln.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | True -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 https://aliencube.org 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | > As the [Azure Functions OpenAPI Extension](https://github.com/Azure/azure-functions-openapi-extension/) package was [officially announced]((https://techcommunity.microsoft.com/t5/apps-on-azure/create-and-publish-openapi-enabled-azure-functions-with-visual/ba-p/2381067?WT.mc_id=github-0000-juyoo)) during the [//Build](https://mybuild.microsoft.com/sessions/5ac55e8d-82e5-4b9f-b9bc-d51187761b42?WT.mc_id=github-0000-juyoo) event in May 2021, this repository has now been pivoted to maintain other extensions for Azure Functions. 2 | > 3 | > If you have any questions around the OpenAPI extension, please pile up an issue to [here](https://github.com/Azure/azure-functions-openapi-extension/issues). 4 | 5 | 6 | # AzureFunctions.Extensions # 7 | 8 | This provides some useful extensions for Azure Functions. 9 | 10 | 11 | ## Getting Started ![Build and Test](https://github.com/aliencube/AzureFunctions.Extensions/workflows/Build%20and%20Test/badge.svg) ## 12 | 13 | | Package | Status | Version | 14 | | --- | --- | --- | 15 | | [Aliencube.AzureFunctions.Extensions.Common](./docs/common.md) | [![](https://img.shields.io/nuget/dt/Aliencube.AzureFunctions.Extensions.Common.svg)](https://www.nuget.org/packages/Aliencube.AzureFunctions.Extensions.Common/) | [![](https://img.shields.io/nuget/v/Aliencube.AzureFunctions.Extensions.Common.svg)](https://www.nuget.org/packages/Aliencube.AzureFunctions.Extensions.Common/) | 16 | 17 | 18 | ### Packages for Reference Only ### 19 | 20 | The following extensions are not actively developed any longer, but for reference only. You can find out the archived source codes by checking out the [archived](https://github.com/aliencube/AzureFunctions.Extensions/tree/archived) tag. 21 | 22 | | Package | Status | Version | 23 | | --- | --- | --- | 24 | | [Aliencube.AzureFunctions.Extensions.Configuration.AppSettings](../archived/docs/app-settings.md) | [![](https://img.shields.io/nuget/dt/Aliencube.AzureFunctions.Extensions.Configuration.AppSettings.svg)](https://www.nuget.org/packages/Aliencube.AzureFunctions.Extensions.Configuration.AppSettings/) | [![](https://img.shields.io/nuget/v/Aliencube.AzureFunctions.Extensions.Configuration.AppSettings.svg)](https://www.nuget.org/packages/Aliencube.AzureFunctions.Extensions.Configuration.AppSettings/) | 25 | | [Aliencube.AzureFunctions.Extensions.Configuration.Json](../archived/docs/configuration-json.md) | [![](https://img.shields.io/nuget/dt/Aliencube.AzureFunctions.Extensions.Configuration.Json.svg)](https://www.nuget.org/packages/Aliencube.AzureFunctions.Extensions.Configuration.Json/) | [![](https://img.shields.io/nuget/v/Aliencube.AzureFunctions.Extensions.Configuration.Json.svg)](https://www.nuget.org/packages/Aliencube.AzureFunctions.Extensions.Configuration.Json/) | 26 | | [Aliencube.AzureFunctions.Extensions.DependencyInjection](../archived/docs/dependency-injection.md) | [![](https://img.shields.io/nuget/dt/Aliencube.AzureFunctions.Extensions.DependencyInjection.svg)](https://www.nuget.org/packages/Aliencube.AzureFunctions.Extensions.DependencyInjection/) | [![](https://img.shields.io/nuget/v/Aliencube.AzureFunctions.Extensions.DependencyInjection.svg)](https://www.nuget.org/packages/Aliencube.AzureFunctions.Extensions.DependencyInjection/) | 27 | | [Aliencube.AzureFunctions.Extensions.OpenApi.Core](../archived/docs/openapi-core.md) | [![](https://img.shields.io/nuget/dt/Aliencube.AzureFunctions.Extensions.OpenApi.Core.svg)](https://www.nuget.org/packages/Aliencube.AzureFunctions.Extensions.OpenApi.Core/) | [![](https://img.shields.io/nuget/v/Aliencube.AzureFunctions.Extensions.OpenApi.Core.svg)](https://www.nuget.org/packages/Aliencube.AzureFunctions.Extensions.OpenApi.Core/) | 28 | | [Aliencube.AzureFunctions.Extensions.OpenApi](../archived/docs/openapi.md) | [![](https://img.shields.io/nuget/dt/Aliencube.AzureFunctions.Extensions.OpenApi.svg)](https://www.nuget.org/packages/Aliencube.AzureFunctions.Extensions.OpenApi/) | [![](https://img.shields.io/nuget/v/Aliencube.AzureFunctions.Extensions.OpenApi.svg)](https://www.nuget.org/packages/Aliencube.AzureFunctions.Extensions.OpenApi/) | 29 | | [Aliencube.AzureFunctions.Extensions.OpenApi.CLI](../archived/docs/openapi-cli.md) | [![](https://img.shields.io/static/v1?label=tag&message=cli-*&color=brightgreen)](https://github.com/aliencube/AzureFunctions.Extensions/releases) | [![](https://img.shields.io/static/v1?label=tag&message=cli-*&color=brightgreen)](https://github.com/aliencube/AzureFunctions.Extensions/releases) | 30 | 31 | 32 | ## Acknowledgement ## 33 | 34 | * In order to read JSON configuration on Azure Functions 1.x, these extensions have copied the source code of [Microsoft.Extensions.Configuration.Json](https://github.com/aspnet/Extensions/tree/master/src/Configuration/Config.Json) to make use of [Newtonsoft.Json 9.0.1](https://www.nuget.org/packages/Newtonsoft.Json/9.0.1) under the [MIT License](http://opensource.org/licenses/MIT). 35 | * [Swagger UI](https://github.com/swagger-api/swagger-ui) version used for this library is [3.20.5](https://github.com/swagger-api/swagger-ui/releases/tag/v3.20.5) under the [Apache 2.0 license](https://opensource.org/licenses/Apache-2.0). 36 | 37 | 38 | ## Contribution ## 39 | 40 | Your contributions are always welcome! All your work should be done in your forked repository. Once you finish your work with corresponding tests, please send us a pull request onto our `dev` branch for review. 41 | 42 | 43 | ## License ## 44 | 45 | **AzureFunctions.Extensions** is released under [MIT License](http://opensource.org/licenses/MIT) 46 | 47 | > The MIT License (MIT) 48 | > 49 | > Copyright (c) 2018 [aliencube.org](http://aliencube.org) 50 | > 51 | > Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 52 | > 53 | > The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 54 | > 55 | > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 56 | -------------------------------------------------------------------------------- /Settings.StyleCop: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | dev 5 | enums 6 | github 7 | json 8 | queryable 9 | querystring 10 | 11 | en-GB 12 | 13 | 14 | 15 | 16 | 17 | 18 | False 19 | 20 | 21 | 22 | 23 | False 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | False 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | False 44 | 45 | 46 | 47 | 48 | True 49 | 50 | 51 | 52 | 53 | 54 | 55 | False 56 | 57 | 58 | 59 | 60 | 61 | db 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /builds/common.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Aliencube Azure Functions Extensions 5 | © Aliencube Community. All rights reserved. 6 | 7 | justinyoo 8 | Justin Yoo 9 | Aliencube Community 10 | 11 | https://github.com/aliencube/AzureFunctions.Extensions 12 | git 13 | 14 | 15 | 16 | https://github.com/aliencube/AzureFunctions.Extensions 17 | MIT 18 | true 19 | 20 | https://raw.githubusercontent.com/aliencube/AzureFunctions.Extensions/main/icons/Aliencube.AzureFunctions.Extensions.Common.png 21 | Aliencube.AzureFunctions.Extensions.Common.png 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /docs/common.md: -------------------------------------------------------------------------------- 1 | # Aliencube.AzureFunctions.Extensions.Common # 2 | 3 | This extension provides constants and extension methods frequently used while developing Azure Functions apps. 4 | 5 | 6 | ## Constants ## 7 | 8 | The following constants represent the string respectively. 9 | 10 | 11 | ### `ContentTypes` ### 12 | 13 | It specifies the content type. 14 | 15 | * `ContentTypes.PlainText`: `text/plain` 16 | * `ContentTypes.TextHtml`: `text/html` 17 | * `ContentTypes.ApplicationJson`: `application/json` 18 | * `ContentTypes.TextVndYaml`: `text/vnd.yaml` 19 | 20 | 21 | ### `HttpVerbs` ### 22 | 23 | It specifies the HTTP method. 24 | 25 | * `HttpVerbs.GET`: `GET` 26 | * `HttpVerbs.POST`: `POST` 27 | * `HttpVerbs.PUT`: `PUT` 28 | * `HttpVerbs.PATCH`: `PATCH` 29 | * `HttpVerbs.DELETE`: `DELETE` 30 | 31 | 32 | ## Enums ## 33 | 34 | ### `SourceFrom` ### 35 | 36 | It specifies whether the HTTP request comes from. 37 | 38 | * `Header`: Request source comes from the request header. 39 | * `Query`: Request source comes from the request querystring. 40 | * `Body`: Request source comes from the request body. 41 | 42 | 43 | ## Extension Methods ## 44 | 45 | ### `HttpRequestExtensions.To(SourceFrom source)` ### 46 | 47 | It extracts relevant data from the given source of the HTTP request. 48 | 49 | ```csharp 50 | public async Task Run( 51 | [HttpTrigger(AuthorizationLevel.Anonymous, HttpVerbs.GET)] HttpRequest req) 52 | { 53 | var headers = await req.To(SourceFrom.Header) 54 | .ConfigureAwait(false); 55 | 56 | var queries = await req.To(SourceFrom.Query) 57 | .ConfigureAwait(false); 58 | 59 | var payload = await req.To(SourceFrom.Body) 60 | .ConfigureAwait(false); 61 | ... 62 | } 63 | ``` 64 | 65 | 66 | ### `OpenApiFormatExtensions.GetContentType()` ### 67 | 68 | It returns the content type based on the OpenAPI document format. 69 | 70 | ```csharp 71 | var format = OpenApiFormat.Json; 72 | var contentType = format.GetContentType(); 73 | ``` 74 | 75 | 76 | ### `PayloadExtensions.ToJson()` ### 77 | 78 | It serialises the given payload to JSON string. 79 | 80 | ```csharp 81 | var payload = new MyClass() { Message = "hello world" }; 82 | var serialised = payload.ToJson(); 83 | ``` 84 | 85 | 86 | ### `PayloadExtensions.FromJson()` ### 87 | 88 | It deserialises the JSON string value to given type. 89 | 90 | ```csharp 91 | var payload = "{ \"message\": \"hello world\" }" 92 | var deserialised = payload.FromJson(payload); 93 | ``` 94 | -------------------------------------------------------------------------------- /icons/Aliencube.AzureFunctions.Extensions.Common.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliencube/AzureFunctions.Extensions/c17643fdfb08a4744ef2c5f2685cd55b215ab0dd/icons/Aliencube.AzureFunctions.Extensions.Common.png -------------------------------------------------------------------------------- /release-notes/common-1.0.0.md: -------------------------------------------------------------------------------- 1 | # Release Note: `Aliencube.AzureFunctions.Extensions.Common` – `1.0.0` # 2 | 3 | [![](https://img.shields.io/nuget/v/Aliencube.AzureFunctions.Extensions.Common.svg)](https://www.nuget.org/packages/Aliencube.AzureFunctions.Extensions.Common/) 4 | 5 | Initial release 6 | -------------------------------------------------------------------------------- /release-notes/common-1.1.0.md: -------------------------------------------------------------------------------- 1 | # Release Note: `Aliencube.AzureFunctions.Extensions.Common` – `1.1.0` # 2 | 3 | [![](https://img.shields.io/nuget/v/Aliencube.AzureFunctions.Extensions.Common.svg)](https://www.nuget.org/packages/Aliencube.AzureFunctions.Extensions.Common/) 4 | 5 | New extension methods added 6 | 7 | 8 | ## Changes & Fixes ## 9 | 10 | * New `HttpRequest` extension method that generates the `MultiPartFormDataContent` instance. 11 | * Update `HttpRequest.To(SourceFrom)` extension method to accept all types. 12 | -------------------------------------------------------------------------------- /src/Aliencube.AzureFunctions.Extensions.Common/Aliencube.AzureFunctions.Extensions.Common.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | netstandard2.0 7 | 8 | true 9 | true 10 | $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb 11 | 1.0.0 12 | Aliencube.AzureFunctions.Extensions.Common 13 | Aliencube.AzureFunctions.Extensions.Common 14 | Useful extension methods and constants for Azure Functions apps 15 | This package provides some useful extension methods and constants frequently used, while building Azure Functions apps. 16 | AzureFunctions, Extensions 17 | 18 | Aliencube.AzureFunctions.Extensions.Common 19 | Aliencube.AzureFunctions.Extensions.Common 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/Aliencube.AzureFunctions.Extensions.Common/ContentTypes.cs: -------------------------------------------------------------------------------- 1 | namespace Aliencube.AzureFunctions.Extensions.Common 2 | { 3 | /// 4 | /// This specifies the content types. 5 | /// 6 | public static class ContentTypes 7 | { 8 | /// 9 | /// Identifies text/plain. 10 | /// 11 | public const string PlainText = "text/plain"; 12 | 13 | /// 14 | /// Identifies text/html. 15 | /// 16 | public const string TextHtml = "text/html"; 17 | 18 | /// 19 | /// Identifies application/json. 20 | /// 21 | public const string ApplicationJson = "application/json"; 22 | 23 | /// 24 | /// Identifies text/vnd.yaml. 25 | /// 26 | public const string TextVndYaml = "text/vnd.yaml"; 27 | 28 | /// 29 | /// Identifies application/x-www-form-urlencoded. 30 | /// 31 | public const string ApplicationFormUrlEncoded = "application/x-www-form-urlencoded"; 32 | 33 | /// 34 | /// Identifies multipart/form-data. 35 | /// 36 | public const string MultipartFormData = "multipart/form-data"; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Aliencube.AzureFunctions.Extensions.Common/ExceptionMessages.cs: -------------------------------------------------------------------------------- 1 | namespace Aliencube.AzureFunctions.Extensions.Common 2 | { 3 | /// 4 | /// This specifies the exception messages. 5 | /// 6 | public static class ExceptionMessages 7 | { 8 | /// 9 | /// Identifies invalid request source. 10 | /// 11 | public const string InvalidRequestSource = "Invalid request source"; 12 | 13 | /// 14 | /// Identifies invalid type. 15 | /// 16 | public const string InvalidType = "Invalid type"; 17 | 18 | /// 19 | /// Identifies invalid OpenAPI format. 20 | /// 21 | public const string InvalidOpenApiFormat = "Invalid Open API format"; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Aliencube.AzureFunctions.Extensions.Common/HttpRequestExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Linq; 4 | using System.Net.Http; 5 | using System.Threading.Tasks; 6 | 7 | using Microsoft.AspNetCore.Http; 8 | 9 | using Newtonsoft.Json; 10 | 11 | namespace Aliencube.AzureFunctions.Extensions.Common 12 | { 13 | /// 14 | /// This represents the extension entity for . 15 | /// 16 | public static class HttpRequestExtensions 17 | { 18 | /// 19 | /// Converts the to the instance of the given type. 20 | /// 21 | /// Type to convert and return. 22 | /// instance. 23 | /// value. Default value is . 24 | /// Returns the converted instance. 25 | public static async Task To(this HttpRequest req, SourceFrom source = SourceFrom.Body) 26 | { 27 | var result = default(T); 28 | switch (source) 29 | { 30 | case SourceFrom.Header: 31 | result = await ToFromHeader(req).ConfigureAwait(false); 32 | break; 33 | 34 | case SourceFrom.Query: 35 | result = await ToFromQuery(req).ConfigureAwait(false); 36 | break; 37 | 38 | case SourceFrom.Body: 39 | result = await ToFromBody(req).ConfigureAwait(false); 40 | break; 41 | 42 | case SourceFrom.None: 43 | default: 44 | throw new InvalidOperationException(ExceptionMessages.InvalidRequestSource); 45 | } 46 | 47 | return result; 48 | } 49 | 50 | /// 51 | /// Converts the to the instance. 52 | /// 53 | /// instance. 54 | /// Returns the instance. 55 | public static async Task ToMultipartFormDataContent(this HttpRequest req) 56 | { 57 | if (!req.Form.Files.Any()) 58 | { 59 | return null; 60 | } 61 | 62 | var mpfd = new MultipartFormDataContent(); 63 | foreach (var file in req.Form.Files) 64 | { 65 | var content = default(ByteArrayContent); 66 | using (var ms = new MemoryStream()) 67 | { 68 | await file.CopyToAsync(ms).ConfigureAwait(false); 69 | content = new ByteArrayContent(ms.ToArray()); 70 | } 71 | 72 | mpfd.Add(content, file.Name, file.FileName); 73 | } 74 | 75 | return mpfd; 76 | } 77 | 78 | private static async Task ToFromHeader(this HttpRequest req) 79 | { 80 | var serialised = JsonConvert.SerializeObject(req.Headers.ToDictionary(p => p.Key, p => p.Value.ToString())); 81 | var deserialised = JsonConvert.DeserializeObject(serialised); 82 | 83 | return await Task.FromResult(deserialised).ConfigureAwait(false); 84 | } 85 | 86 | private static async Task ToFromQuery(this HttpRequest req) 87 | { 88 | var serialised = JsonConvert.SerializeObject(req.Query.ToDictionary(p => p.Key, p => p.Value.ToString())); 89 | var deserialised = JsonConvert.DeserializeObject(serialised); 90 | 91 | return await Task.FromResult(deserialised).ConfigureAwait(false); 92 | } 93 | 94 | private static async Task ToFromBody(this HttpRequest req) 95 | { 96 | var result = default(T); 97 | using (var reader = new StreamReader(req.Body)) 98 | { 99 | var serialised = await reader.ReadToEndAsync().ConfigureAwait(false); 100 | result = JsonConvert.DeserializeObject(serialised); 101 | } 102 | 103 | return result; 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/Aliencube.AzureFunctions.Extensions.Common/HttpVerbs.cs: -------------------------------------------------------------------------------- 1 | namespace Aliencube.AzureFunctions.Extensions.Common 2 | { 3 | /// 4 | /// This specifies the HTTP method to use. 5 | /// 6 | public static class HttpVerbs 7 | { 8 | /// 9 | /// Identifies the GET method. 10 | /// 11 | public const string GET = "GET"; 12 | 13 | /// 14 | /// Identifies the POST method. 15 | /// 16 | public const string POST = "POST"; 17 | 18 | /// 19 | /// Identifies the PUT method. 20 | /// 21 | public const string PUT = "PUT"; 22 | 23 | /// 24 | /// Identifies the PATCH method. 25 | /// 26 | public const string PATCH = "PATCH"; 27 | 28 | /// 29 | /// Identifies the DELETE method. 30 | /// 31 | public const string DELETE = "DELETE"; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Aliencube.AzureFunctions.Extensions.Common/OpenApiFormatExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using Microsoft.OpenApi; 4 | 5 | namespace Aliencube.AzureFunctions.Extensions.Common 6 | { 7 | /// 8 | /// This represents the extension entity for the class. 9 | /// 10 | public static class OpenApiFormatExtensions 11 | { 12 | /// 13 | /// Gets the content type. 14 | /// 15 | /// value. 16 | /// The content type. 17 | public static string GetContentType(this OpenApiFormat format) 18 | { 19 | switch (format) 20 | { 21 | case OpenApiFormat.Json: 22 | return ContentTypes.ApplicationJson; 23 | 24 | case OpenApiFormat.Yaml: 25 | return ContentTypes.TextVndYaml; 26 | 27 | default: 28 | throw new InvalidOperationException(ExceptionMessages.InvalidOpenApiFormat); 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Aliencube.AzureFunctions.Extensions.Common/PayloadExtensions.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace Aliencube.AzureFunctions.Extensions.Common 4 | { 5 | /// 6 | /// This represents the extensions entity for any payload. 7 | /// 8 | public static class PayloadExtensions 9 | { 10 | /// 11 | /// Serialises the given payload to JSON string. 12 | /// 13 | /// Type of the payload to serialise. 14 | /// Payload object. 15 | /// Returns the serialised JSON string value. 16 | public static string ToJson(this T payload) 17 | { 18 | if (payload == null) 19 | { 20 | return default; 21 | } 22 | 23 | var result = JsonConvert.SerializeObject(payload); 24 | 25 | return result; 26 | } 27 | 28 | /// 29 | /// Deserialises the JSON string value to given type. 30 | /// 31 | /// Type of the payload to deserialise. 32 | /// JSON string value. 33 | /// Returns the deserialised object. 34 | public static T FromJson(this string payload) 35 | { 36 | if (string.IsNullOrWhiteSpace(payload)) 37 | { 38 | return default; 39 | } 40 | 41 | var result = JsonConvert.DeserializeObject(payload); 42 | 43 | return result; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Aliencube.AzureFunctions.Extensions.Common/SourceFrom.cs: -------------------------------------------------------------------------------- 1 | namespace Aliencube.AzureFunctions.Extensions.Common 2 | { 3 | /// 4 | /// This specifies the source of the request to parse. 5 | /// 6 | public enum SourceFrom 7 | { 8 | /// 9 | /// Identifies none. 10 | /// 11 | None = 0, 12 | 13 | /// 14 | /// Identifies the request header. 15 | /// 16 | Header = 1, 17 | 18 | /// 19 | /// Identifies the request query. 20 | /// 21 | Query = 2, 22 | 23 | /// 24 | /// Identifies the request body. 25 | /// 26 | Body = 3 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /test/Aliencube.AzureFunctions.Extensions.Common.Tests/Aliencube.AzureFunctions.Extensions.Common.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | 7 | false 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /test/Aliencube.AzureFunctions.Extensions.Common.Tests/HttpRequestExtensionsTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Text; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | 9 | using Aliencube.AzureFunctions.Extensions.Common.Tests.Models; 10 | 11 | using FluentAssertions; 12 | 13 | using Microsoft.AspNetCore.Http; 14 | using Microsoft.AspNetCore.Http.Internal; 15 | using Microsoft.Extensions.Primitives; 16 | using Microsoft.VisualStudio.TestTools.UnitTesting; 17 | 18 | using Moq; 19 | 20 | using Newtonsoft.Json; 21 | 22 | namespace Aliencube.AzureFunctions.Extensions.Common.Tests 23 | { 24 | [TestClass] 25 | public class HttpRequestExtensionsTests 26 | { 27 | [DataTestMethod] 28 | [DataRow(SourceFrom.None)] 29 | public void Given_InvalidRequestSource_When_To_Invoked_Then_It_Should_Throw_Exception(SourceFrom source) 30 | { 31 | var req = new Mock(); 32 | 33 | Func func = async () => await HttpRequestExtensions.To(req.Object, source).ConfigureAwait(false); 34 | 35 | func.Should().ThrowAsync(); 36 | } 37 | 38 | [DataTestMethod] 39 | [DataRow(SourceFrom.Header)] 40 | [DataRow(SourceFrom.Query)] 41 | public void Given_InvalidType_When_To_Invoked_Then_It_Should_Throw_Exception(SourceFrom source) 42 | { 43 | var req = new Mock(); 44 | 45 | Func func = async () => await HttpRequestExtensions.To(req.Object, source).ConfigureAwait(false); 46 | 47 | func.Should().ThrowAsync(); 48 | } 49 | 50 | [DataTestMethod] 51 | [DataRow("x-secret-key", "hello-world")] 52 | public async Task Given_Header_When_To_Invoked_Then_It_Should_Return_Result(string key, string value) 53 | { 54 | var store = new Dictionary() { { key, value } }; 55 | var headers = new HeaderDictionary(store); 56 | 57 | var req = new Mock(); 58 | req.SetupGet(p => p.Headers).Returns(headers); 59 | 60 | var result = await HttpRequestExtensions.To(req.Object, SourceFrom.Header).ConfigureAwait(false); 61 | 62 | result.Should().NotBeNull(); 63 | result.SecretKey.Should().Be(value); 64 | } 65 | 66 | [DataTestMethod] 67 | [DataRow("key", "value")] 68 | public async Task Given_Query_When_To_Invoked_Then_It_Should_Return_Result(string key, string value) 69 | { 70 | var store = new Dictionary() { { key, value } }; 71 | var queries = new QueryCollection(store); 72 | 73 | var req = new Mock(); 74 | req.SetupGet(p => p.Query).Returns(queries); 75 | 76 | var result = await HttpRequestExtensions.To(req.Object, SourceFrom.Query).ConfigureAwait(false); 77 | 78 | result.Should().NotBeNull(); 79 | result.Key.Should().Be(value); 80 | } 81 | 82 | [DataTestMethod] 83 | [DataRow("hello world")] 84 | public async Task Given_Payload_When_To_Invoked_Then_It_Should_Return_Result(string message) 85 | { 86 | var payload = new FakeRequestModel() { Message = message }; 87 | var serialised = JsonConvert.SerializeObject(payload); 88 | var bytes = Encoding.UTF8.GetBytes(serialised); 89 | var stream = new MemoryStream(); 90 | await stream.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false); 91 | stream.Position = 0; 92 | 93 | var req = new Mock(); 94 | req.SetupGet(p => p.Body).Returns(stream); 95 | 96 | var result = await HttpRequestExtensions.To(req.Object, SourceFrom.Body).ConfigureAwait(false); 97 | 98 | result.Message.Should().Be(message); 99 | 100 | await stream.DisposeAsync().ConfigureAwait(false); 101 | } 102 | 103 | [TestMethod] 104 | public async Task Given_Null_Payload_When_ToMultipartFormDataContent_Invoked_Then_It_Should_Return_Null() 105 | { 106 | var files = new FormFileCollection(); 107 | 108 | var form = new Mock(); 109 | form.SetupGet(p => p.Files).Returns(files); 110 | 111 | var req = new Mock(); 112 | req.SetupGet(p => p.Form).Returns(form.Object); 113 | 114 | var result = await HttpRequestExtensions.ToMultipartFormDataContent(req.Object).ConfigureAwait(false); 115 | 116 | result.Should().BeNull(); 117 | } 118 | 119 | [DataTestMethod] 120 | [DataRow("hello", "world.jpg")] 121 | public async Task Given_Payload_When_ToMultipartFormDataContent_Invoked_Then_It_Should_Return_Result(string name, string filename) 122 | { 123 | var file = new Mock(); 124 | file.SetupGet(p => p.Name).Returns(name); 125 | file.SetupGet(p => p.FileName).Returns(filename); 126 | file.Setup(p => p.CopyToAsync(It.IsAny(), It.IsAny())).Returns(Task.CompletedTask); 127 | 128 | var files = new FormFileCollection 129 | { 130 | file.Object 131 | }; 132 | 133 | var form = new Mock(); 134 | form.SetupGet(p => p.Files).Returns(files); 135 | 136 | var req = new Mock(); 137 | req.SetupGet(p => p.Form).Returns(form.Object); 138 | 139 | var result = await HttpRequestExtensions.ToMultipartFormDataContent(req.Object).ConfigureAwait(false); 140 | 141 | result.Should().NotBeNull(); 142 | } 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /test/Aliencube.AzureFunctions.Extensions.Common.Tests/Models/FakeRequestHeader.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace Aliencube.AzureFunctions.Extensions.Common.Tests.Models 4 | { 5 | public class FakeRequestHeader 6 | { 7 | [JsonProperty("x-secret-key")] 8 | public string? SecretKey { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /test/Aliencube.AzureFunctions.Extensions.Common.Tests/Models/FakeRequestModel.cs: -------------------------------------------------------------------------------- 1 | namespace Aliencube.AzureFunctions.Extensions.Common.Tests.Models 2 | { 3 | public class FakeRequestModel 4 | { 5 | public string? Message { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /test/Aliencube.AzureFunctions.Extensions.Common.Tests/Models/FakeRequestQuery.cs: -------------------------------------------------------------------------------- 1 | namespace Aliencube.AzureFunctions.Extensions.Common.Tests.Models 2 | { 3 | public class FakeRequestQuery 4 | { 5 | public string? Key { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /test/Aliencube.AzureFunctions.Extensions.Common.Tests/OpenApiFormatExtensionsTests.cs: -------------------------------------------------------------------------------- 1 | using FluentAssertions; 2 | 3 | using Microsoft.OpenApi; 4 | using Microsoft.VisualStudio.TestTools.UnitTesting; 5 | 6 | namespace Aliencube.AzureFunctions.Extensions.Common.Tests 7 | { 8 | [TestClass] 9 | public class OpenApiFormatExtensionsTests 10 | { 11 | [DataTestMethod] 12 | [DataRow(OpenApiFormat.Json, ContentTypes.ApplicationJson)] 13 | [DataRow(OpenApiFormat.Yaml, ContentTypes.TextVndYaml)] 14 | public void Given_OpenApiFormat_When_GetContentType_Invoked_Then_It_Should_Return_Result(OpenApiFormat format, string expected) 15 | { 16 | var result = OpenApiFormatExtensions.GetContentType(format); 17 | 18 | result.Should().Be(expected); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /test/Aliencube.AzureFunctions.Extensions.Common.Tests/PayloadExtensionsTests.cs: -------------------------------------------------------------------------------- 1 | using Aliencube.AzureFunctions.Extensions.Common.Tests.Models; 2 | 3 | using FluentAssertions; 4 | 5 | using Microsoft.VisualStudio.TestTools.UnitTesting; 6 | 7 | using Newtonsoft.Json; 8 | 9 | namespace Aliencube.AzureFunctions.Extensions.Common.Tests 10 | { 11 | [TestClass] 12 | public class PayloadExtensionsTests 13 | { 14 | [TestMethod] 15 | public void Given_Null_When_ToJson_Invoked_Then_It_Should_Return_Null() 16 | { 17 | var result = PayloadExtensions.ToJson(null!); 18 | 19 | result.Should().BeNull(); 20 | } 21 | 22 | [DataTestMethod] 23 | [DataRow("hello world")] 24 | public void Given_Payload_When_ToJson_Invoked_Then_It_Should_Return_Result(string message) 25 | { 26 | var payload = new FakeRequestModel() { Message = message }; 27 | var serialised = JsonConvert.SerializeObject(payload); 28 | 29 | var result = PayloadExtensions.ToJson(payload); 30 | 31 | result.Should().Be(serialised); 32 | } 33 | 34 | [TestMethod] 35 | public void Given_Null_When_FromJson_Invoked_Then_It_Should_Return_Null() 36 | { 37 | var result = PayloadExtensions.FromJson(null); 38 | 39 | result.Should().BeNull(); 40 | } 41 | 42 | [DataTestMethod] 43 | [DataRow("hello world")] 44 | public void Given_Payload_When_FromJson_Invoked_Then_It_Should_Return_Result(string message) 45 | { 46 | var payload = new FakeRequestModel() { Message = message }; 47 | var serialised = JsonConvert.SerializeObject(payload); 48 | 49 | var result = PayloadExtensions.FromJson(serialised); 50 | 51 | result.Message.Should().Be(message); 52 | } 53 | } 54 | } 55 | --------------------------------------------------------------------------------