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

KSP-CKAN / CKAN / 29550533164

17 Jul 2026 02:41AM UTC coverage: 87.981% (+0.1%) from 87.84%
29550533164

Pull #4694

github

web-flow
Merge 167d5746a into 0daeea8d7
Pull Request #4694: New URL protocol and handler improvements

2037 of 2161 branches covered (94.26%)

Branch coverage included in aggregate %.

80 of 86 new or added lines in 2 files covered. (93.02%)

8724 of 10070 relevant lines covered (86.63%)

1.81 hits per line

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

96.77
/Core/IO/ProtocolRouter.cs
1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Web;
5

6
namespace CKAN.IO
7
{
8
    public static class ProtocolRouter
9
    {
10
        public static event Action<string>? OnFocus;
11
        public static event Action<string>? OnSearch;
12
        public static event Action<List<(string Mod, string? Version)>>? OnInstall;
13

14
        public static void Handle(string rawUrl)
15
        {
16
            if (string.IsNullOrWhiteSpace(rawUrl))
2✔
17
            {
18
                return;
2✔
19
            }
20

21
            // Tolerate a missing or partial scheme. Uri.TryCreate needs the full prefix.
22
            if (!rawUrl.StartsWith("ckan://"))
2✔
23
            {
24
                rawUrl = "ckan://" + rawUrl.TrimStart('/');
2✔
25
            }
26

27
            if (!Uri.TryCreate(rawUrl, UriKind.Absolute, out var uri))
2✔
28
            {
NEW
29
                return;
×
30
            }
31

32
            string operation = uri.Host.ToLowerInvariant();
2✔
33
            var query = HttpUtility.ParseQueryString(uri.Query);
2✔
34

35
            switch (operation)
36
            {
37
                case "focus":
38
                    {
39
                        string? mod = query["mod"];
2✔
40
                        if (!string.IsNullOrWhiteSpace(mod)) { OnFocus?.Invoke(mod); }
4✔
41
                        break;
2✔
42
                    }
43

44
                case "search":
45
                    {
46
                        string? q = query["q"];
2✔
47
                        if (!string.IsNullOrWhiteSpace(q)) { OnSearch?.Invoke(q); }
4✔
48
                        break;
2✔
49
                    }
50

51
                case "install":
52
                    {
53
                        string[]? modValues = query.GetValues("mod")
2✔
54
                                                   ?.Where(x => !string.IsNullOrWhiteSpace(x))
2✔
55
                                                   .ToArray();
56

57
                        if (modValues == null || modValues.Length == 0)
2✔
58
                        {
59
                            break;
60
                        }
61

62
                        var mods = modValues
2✔
63
                            .Select(mod =>
64
                            {
65
                                int colonIndex = mod.IndexOf(':');
2✔
66
                                return colonIndex == -1
2✔
67
                                    ? (mod, null)
68
                                    : (mod[..colonIndex], (string?)mod[(colonIndex + 1)..]);
69
                            })
70
                            .ToList();
71

72
                        OnInstall?.Invoke(mods);
2✔
73
                        break;
74
                    }
75
            }
76
        }
2✔
77
    }
78
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc