• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ThreeMammals / Ocelot / 36707038946

30 Sep 2026 11:11AM UTC coverage: 97.127% (-0.5%) from 97.638%
36707038946

push

github

web-flow
#2352 Stop building upstream header templates from request headers in dynamic routing (#2427)

* #2352 Add tests reproducing RegexParseException for browser headers in dynamic routing
* #2352 Stop building upstream header templates from request headers in dynamic routing
* Update scripting in workflows related to code coverage copying the version from develop
* Code review by @raman-m
* Enable builds for release/25.0 branch
---------
Co-authored-by: Raman Maksimchuk <dotnet044@gmail.com>

6728 of 6927 relevant lines covered (97.13%)

3289.59 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.12
src/QueryStrings/AddQueriesToRequest.cs
1
using Microsoft.Extensions.Primitives;
2
using Ocelot.Configuration;
3
using Ocelot.Infrastructure.Claims;
4
using Ocelot.Request.Middleware;
5
using Ocelot.Responses;
6
using System.Security.Claims;
7

8
namespace Ocelot.QueryStrings;
9

10
public class AddQueriesToRequest : IAddQueriesToRequest
11
{
12
    private readonly IClaimsParser _claimsParser;
13

14
    public AddQueriesToRequest(IClaimsParser claimsParser)
8 ✔
15
    {
8 ✔
16
        _claimsParser = claimsParser;
8 ✔
17
    }
8 ✔
18

19
    public Response SetQueriesOnDownstreamRequest(List<ClaimToThing> claimsToThings, IEnumerable<Claim> claims, DownstreamRequest downstreamRequest)
20
    {
4 ✔
21
        var queryDictionary = ConvertQueryStringToDictionary(downstreamRequest.Query);
4 ✔
22

23
        foreach (var config in claimsToThings)
19 ✔
24
        {
4 ✔
25
            var value = _claimsParser.GetValue(claims, config.NewKey, config.Delimiter, config.Index);
4 ✔
26

27
            if (value.IsError)
4 ✔
28
            {
1 ✔
29
                return new ErrorResponse(value.Errors);
1 ✔
30
            }
31

32
            var exists = queryDictionary.FirstOrDefault(x => x.Key == config.ExistingKey);
3 ✔
33

34
            if (!string.IsNullOrEmpty(exists.Key))
3 ✔
35
            {
×
36
                queryDictionary[exists.Key] = value.Data;
×
37
            }
×
38
            else
39
            {
3 ✔
40
                queryDictionary.Add(config.ExistingKey, value.Data);
3 ✔
41
            }
3 ✔
42
        }
3 ✔
43

44
        downstreamRequest.Query = ConvertDictionaryToQueryString(queryDictionary);
3 ✔
45

46
        return new OkResponse();
3 ✔
47
    }
4 ✔
48

49
    private static Dictionary<string, StringValues> ConvertQueryStringToDictionary(string queryString)
50
    {
4 ✔
51
        var query = Microsoft.AspNetCore.WebUtilities.QueryHelpers
4 ✔
52
            .ParseQuery(queryString);
4 ✔
53

54
        return query;
4 ✔
55
    }
4 ✔
56

57
    private static string ConvertDictionaryToQueryString(Dictionary<string, StringValues> queryDictionary)
58
    {
3 ✔
59
        var builder = new StringBuilder();
3 ✔
60

61
        builder.Append('?');
3 ✔
62

63
        var outerCount = 0;
3 ✔
64

65
        foreach (var query in queryDictionary)
21 ✔
66
        {
6 ✔
67
            for (var innerCount = 0; innerCount < query.Value.Count; innerCount++)
26 ✔
68
            {
7 ✔
69
                builder.Append($"{query.Key}={query.Value[innerCount]}");
7 ✔
70

71
                if (innerCount < (query.Value.Count - 1))
7 ✔
72
                {
1 ✔
73
                    builder.Append('&');
1 ✔
74
                }
1 ✔
75
            }
7 ✔
76

77
            if (outerCount < (queryDictionary.Count - 1))
6 ✔
78
            {
3 ✔
79
                builder.Append('&');
3 ✔
80
            }
3 ✔
81

82
            outerCount++;
6 ✔
83
        }
6 ✔
84

85
        return builder.ToString();
3 ✔
86
    }
3 ✔
87
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc