{"id":15066044,"url":"https://github.com/SiC42/Http.Utilities","last_synced_at":"2025-10-05T03:30:39.597Z","repository":{"id":257286928,"uuid":"857824776","full_name":"SiC42/UrlBuilder","owner":"SiC42","description":null,"archived":false,"fork":false,"pushed_at":"2024-09-25T17:29:18.000Z","size":30,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-09-29T11:01:28.341Z","etag":null,"topics":["csharp","dotnet","http"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SiC42.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-09-15T17:48:07.000Z","updated_at":"2024-09-25T17:29:21.000Z","dependencies_parsed_at":"2024-09-15T19:22:35.389Z","dependency_job_id":null,"html_url":"https://github.com/SiC42/UrlBuilder","commit_stats":null,"previous_names":["sic42/urlbuilder"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SiC42%2FUrlBuilder","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SiC42%2FUrlBuilder/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SiC42%2FUrlBuilder/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SiC42%2FUrlBuilder/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SiC42","download_url":"https://codeload.github.com/SiC42/UrlBuilder/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":219876883,"owners_count":16554799,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["csharp","dotnet","http"],"created_at":"2024-09-25T01:00:29.170Z","updated_at":"2025-10-05T03:30:39.299Z","avatar_url":"https://github.com/SiC42.png","language":"C#","readme":"# Http.Utilities\n**This is a work in progress**\nThis repository provides packages to handle various aspects of HTTP calls, especially with `HttpClient`.\n\n## Url.Building\nThe package provides a way to handle building URLs.\nIt aims to be easier to use than the .NET `UriBuilder`.\n\n### Simple URL builder\nThis implementation can be used to build URLs on the fly.\n\n#### Examples\nBasic Usage\n\n```csharp\nvar builder = new UrlBuilder(\"http://mydomain.com/test?base=query\")\n            .SetScheme(\"https\")\n            .SetPort(4242)\n            .AddPath(\"hello/big\")\n            .AddPath(\"world\")\n            .AddQuery(\"this\", \"is\")\n            .AddQuery(\"a\", \"test\");\n\nUri url = builder.Build(); // https://mydomain.com:4242/test/hello/big/world?base=query\u0026this=is\u0026a=test\n```\nQuery Parameter Usage\n```csharp\nvar builder = new UrlBuilder(\"https://mydomain.com\")\n  .AddQuery(\"multiparam\", \"one\", \"two\")\n  .AddQuery(\"multiparam\", \"three\")\n  .AddQuery(\"queryWithoutValue\");\n\n\nUri url = builder.Build(); // https://mydomain.com?multiparam=one\u0026multiparam=two\u0026multiparam=three\u0026queryWithoutValue\n```\nPath Variables can also be used to later replace the variable you need. This is especially useful for [`ImmutableUrlBuilder`s](#immutable-url-builder).\n```csharp\nvar builder = new UrlBuilder(\"https://mydomain.com\")\n  .AddPath(\"{Greet}\")\n  .AddPath(\"world\");\n\nint i = 5;\nif(i % 2 == 0)\n{\n  builder = builder.WithPathValue(\"Greet\", \"hi\");\n}\nelse\n{\n  builder = builder.WithPathValue(\"Greet\", \"hello\");\n}\n\nUri url = builder.Build(); // https://mydomain.com/hello/world\n```\n\n### Immutable URL builder\nWhile the above used `UrlBuilder` is efficient, it has the problem that the internal state may be modified, e.g. when setting a path.\n```csharp\nvar builder = new UrlBuilder(\"https://mydomain.com\")\n\nvar builder2 = builder.AddPath(\"pathfor2\")\n\nvar url1 = builder.Build(); // https://mydomain.com/pathfor2\nvar url2 = builder2.Build(); // https://mydomain.com/pathfor2\n```\nThis is especially bug prone when the builder is initialized in the constructor and then further mutated in methods, e.g.\n\n```csharp\npublic MyClient\n{\n  private UrlBuilder _urlBuilder;\n  public MyClient(IOptions\u003cMyClientOptions\u003e options)\n  {\n    _urlBuilder = new UrlBuilder(options.Value.Url)\n    .SetPort(8080)\n    .AddPath(\"orders\");\n  }\n\n\n  public Order GetOrder(string orderId)\n  {\n    var url = _urlBuilder.AddPath(orderId).Build(); // ❌ may have multiple order ID paths when method called multiple times\n    // GET order ...\n  }\n\n  public List\u003cOrder\u003e GetOrders()\n  {\n    var url = _urlBuilder.Build(); // ❌ may have one or more order IDs added as path when GetOrder was called before\n    // GET order ...\n  }\n}\n```\nFor these cases, the `ImmutableUrlBuilder` can be used.\n```csharp\nvar builder = new ImmutableUrlBuilder(\"https://mydomain.com\")\n\nvar builder2 = builder.AddPath(\"pathfor2\")\n\nvar url1 = builder.Build(); // https://mydomain.com\nvar url2 = builder2.Build(); // https://mydomain.com/pathfor2\n```\nYou also can switch from a normal `UrlBuilder` to the `ImmutableUrlBuilder` using the `AsImmutable()`-method.\nUsing above `MyClient`-example, you may use this pattern:\n\n```csharp\npublic MyClient\n{\n  private ImmutableUrlBuilder _urlBuilder;\n  public MyClient(IOptions\u003cMyClientOptions\u003e options)\n  {\n    _urlBuilder = new UrlBuilder(options.Value.Url) // e.g. https://my-domain.com\n    .SetPort(8080)\n    .AddPath(\"orders\")\n    .AsImmutable();\n  }\n\n\n  public Order GetOrder(string orderId)\n  {\n    var url = _urlBuilder.AddPath(orderId).Build(); // URL will always be https://my-domain.com/orders/\u003corderId\u003e\n    // GET order ...\n  }\n\n  public List\u003cOrder\u003e GetOrders()\n  {\n    var url = _urlBuilder.Build(); // URL will always be https://my-domain.com/orders\n    // GET order ...\n  }\n}\n```\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FSiC42%2FHttp.Utilities","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FSiC42%2FHttp.Utilities","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FSiC42%2FHttp.Utilities/lists"}