{"id":13570456,"url":"https://github.com/reactiveui/Fusillade","last_synced_at":"2025-04-04T06:32:36.386Z","repository":{"id":16340138,"uuid":"19089866","full_name":"reactiveui/Fusillade","owner":"reactiveui","description":"An opinionated HTTP library for Mobile Development","archived":false,"fork":false,"pushed_at":"2024-10-28T14:05:02.000Z","size":2114,"stargazers_count":310,"open_issues_count":7,"forks_count":33,"subscribers_count":22,"default_branch":"main","last_synced_at":"2024-10-29T14:36:08.287Z","etag":null,"topics":["cross-platform","dotnet","dotnet-core","http","http-client","mobile","speculative-requests","volley","xamarin"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/reactiveui.png","metadata":{"funding":{"github":["reactivemarbles"]},"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","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":"2014-04-24T00:08:11.000Z","updated_at":"2024-10-24T07:12:10.000Z","dependencies_parsed_at":"2023-11-11T08:31:39.716Z","dependency_job_id":"5145e261-a2cd-40d1-8752-f6e73d7342fb","html_url":"https://github.com/reactiveui/Fusillade","commit_stats":{"total_commits":316,"total_committers":22,"mean_commits":"14.363636363636363","dds":0.5411392405063291,"last_synced_commit":"4c755d63d2d0551161185260f7eea92684f274f7"},"previous_names":["paulcbetts/fusillade"],"tags_count":16,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reactiveui%2FFusillade","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reactiveui%2FFusillade/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reactiveui%2FFusillade/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reactiveui%2FFusillade/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/reactiveui","download_url":"https://codeload.github.com/reactiveui/Fusillade/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247134992,"owners_count":20889412,"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":["cross-platform","dotnet","dotnet-core","http","http-client","mobile","speculative-requests","volley","xamarin"],"created_at":"2024-08-01T14:00:52.552Z","updated_at":"2025-04-04T06:32:31.370Z","avatar_url":"https://github.com/reactiveui.png","language":"C#","readme":"\n[![NuGet Stats](https://img.shields.io/nuget/v/fusillade.svg)](https://www.nuget.org/packages/fusillade) ![Build](https://github.com/reactiveui/Fusillade/workflows/Build/badge.svg) [![Code Coverage](https://codecov.io/gh/reactiveui/fusillade/branch/main/graph/badge.svg)](https://codecov.io/gh/reactiveui/akavache)\n\n\u003cbr /\u003e\n\u003ca href=\"https://github.com/reactiveui/fusillade\"\u003e\n  \u003cimg width=\"120\" heigth=\"120\" src=\"https://raw.githubusercontent.com/reactiveui/styleguide/master/logo_fusillade/main.png\"\u003e\n\u003c/a\u003e\n\n## Fusillade: An opinionated HTTP library for Mobile Development\n\nFusillade helps you to write more efficient code in mobile and desktop\napplications written in C#. Its design goals and feature set are inspired by\n[Volley](http://arnab.ch/blog/2013/08/asynchronous-http-requests-in-android-using-volley/)\nas well as [Picasso](http://square.github.io/picasso/).\n\n### What even does this do for me?\n\nFusillade is a set of HttpMessageHandlers (i.e. \"drivers\" for HttpClient) that\nmake your mobile applications more efficient and responsive:\n\n* **Auto-deduplication of relevant requests** - if every instance of your TweetView\n  class requests the same avatar image, Fusillade will only do *one* request\n  and give the result to every instance. All `GET`, `HEAD`, and `OPTIONS` requests are deduplicated.\n\n* **Request Limiting** - Requests are always dispatched 4 at a time (the\n  Volley default) - issue lots of requests without overwhelming the network\n  connection.\n\n* **Request Prioritization** - background requests should run at a lower\n  priority than requests initiated by the user, but actually *implementing*\n  this is quite difficult. With a few changes to your app, you can hint to\n  Fusillade which requests should skip to the front of the queue.\n\n* **Speculative requests** - On page load, many apps will try to speculatively\n  cache data (i.e. try to pre-download data that the user *might* click on).\n  Marking requests as speculative will allow requests until a certain data\n  limit is reached, then cancel future requests (i.e. \"Keep downloading data\n  in the background until we've got 5MB of cached data\")\n\n### How do I use it?\n\nThe easiest way to interact with Fusillade is via a class called `NetCache`,\nwhich has a number of built-in scenarios:\n\n```cs\npublic static class NetCache\n{\n    // Use to fetch data into a cache when a page loads. Expect that\n    // these requests will only get so far then give up and start failing\n    public static HttpMessageHandler Speculative { get; set; }\n\n    // Use for network requests that are running in the background\n    public static HttpMessageHandler Background { get; set; }\n\n    // Use for network requests that are fetching data that the user is\n    // waiting on *right now*\n    public static HttpMessageHandler UserInitiated { get; set; }\n}\n```\n\nTo use them, just create an `HttpClient` with the given handler:\n\n```cs\nvar client = new HttpClient(NetCache.UserInitiated);\nvar response = await client.GetAsync(\"http://httpbin.org/get\");\nvar str = await response.Content.ReadAsStringAsync();\n\nConsole.WriteLine(str);\n```\n\n### Where does it work?\n\nEverywhere! Fusillade is a Portable Library, it works on:\n\n* Xamarin.Android\n* Xamarin.iOS\n* Xamarin.Mac\n* Windows Desktop apps\n* WinRT / Windows Phone 8.1 apps\n* Windows Phone 8\n\n### More on speculative requests\n\nGenerally, on a mobile app, you'll want to *reset* the Speculative limit every\ntime the app resumes from standby. How you do this depends on the platform,\nbut in that callback, you need to call:\n\n```cs\nNetCache.Speculative.ResetLimit(1048576 * 5/*MB*/);\n```\n\n### Offline Support\n\nFusillade can optionally cache responses that it sees, then play them back to\nyou when your app is offline (or you just want to speed up your app by fetching\ncached data). Here's how to set it up:\n\n* Implement the IRequestCache interface:\n\n```cs\npublic interface IRequestCache\n{\n    /// \u003csummary\u003e\n    /// Implement this method by saving the Body of the response. The\n    /// response is already downloaded as a ByteArrayContent so you don't\n    /// have to worry about consuming the stream.\n    /// \u003cparam name=\"request\"\u003eThe originating request.\u003c/param\u003e\n    /// \u003cparam name=\"response\"\u003eThe response whose body you should save.\u003c/param\u003e\n    /// \u003cparam name=\"key\"\u003eA unique key used to identify the request details.\u003c/param\u003e\n    /// \u003cparam name=\"ct\"\u003eCancellation token.\u003c/param\u003e\n    /// \u003creturns\u003eCompletion.\u003c/returns\u003e\n    Task Save(HttpRequestMessage request, HttpResponseMessage response, string key, CancellationToken ct);\n\n    /// \u003csummary\u003e\n    /// Implement this by loading the Body of the given request / key.\n    /// \u003c/summary\u003e\n    /// \u003cparam name=\"request\"\u003eThe originating request.\u003c/param\u003e\n    /// \u003cparam name=\"key\"\u003eA unique key used to identify the request details,\n    /// that was given in Save().\u003c/param\u003e\n    /// \u003cparam name=\"ct\"\u003eCancellation token.\u003c/param\u003e\n    /// \u003creturns\u003eThe Body of the given request, or null if the search\n    /// completed successfully but the response was not found.\u003c/returns\u003e\n    Task\u003cbyte[]\u003e Fetch(HttpRequestMessage request, string key, CancellationToken ct);\n}\n```\n\n* Set an instance to `NetCache.RequestCache`, and make some requests:\n\n```cs\nNetCache.RequestCache = new MyCoolCache();\n\nvar client = new HttpClient(NetCache.UserInitiated);\nawait client.GetStringAsync(\"https://httpbin.org/get\");\n```\n\n* Now you can use `NetCache.Offline` to get data even when the Internet is disconnected:\n\n```cs\n// This will never actually make an HTTP request, it will either succeed via\n// reading from MyCoolCache, or return an HttpResponseMessage with a 503 Status code.\nvar client = new HttpClient(NetCache.Offline);\nawait client.GetStringAsync(\"https://httpbin.org/get\");\n```\n\n### How do I use this with ModernHttpClient?\n\nAdd this line to a **static constructor** of your app's startup class:\n\n```cs\nusing Splat;\n\nLocator.CurrentMutable.RegisterConstant(new NativeMessageHandler(), typeof(HttpMessageHandler));\n```\n\n### What do the priorities mean?\n\nThe precedence is UserInitiated \u003e Background \u003e Speculative\nWhich means that anything set as UserInitiate has a higher priority than Background or Speculative. \n\nExplicit is a special that allows to set an explicit value that can be higher, lower or in between any of the predefined cases. \n\n```csharp\nvar lowerThanSpeculative = new RateLimitedHttpMessageHandler(\n                new HttpClientHandler(), \n                Priority.Explicit, \n                9);\n\nvar moreThanSpeculativeButLessThanBAckground = new RateLimitedHttpMessageHandler(\n                new HttpClientHandler(), \n                Priority.Explicit, \n                15);\n\nvar doItBeforeEverythingElse = new RateLimitedHttpMessageHandler(\n                new HttpClientHandler(), \n                Priority.Explicit, \n                1000);\n```\n\n### Statics? That sucks! I like $OTHER_THING! Your priorities suck, I want to come up with my own scheme!\n\n`NetCache` is just a nice pre-canned default, the interesting code is in a\nclass called `RateLimitedHttpMessageHandler`. You can create it explicitly and\nconfigure it as-needed.\n\n### What's with the name?\n\nThe word 'Fusillade' is a synonym for Volley :)\n\n## Contribute\n\nFusillade is developed under an OSI-approved open source license, making it freely usable and distributable, even for commercial use. Because of our Open Collective model for funding and transparency, we are able to funnel support and funds through to our contributors and community. We ❤ the people who are involved in this project, and we’d love to have you on board, especially if you are just getting started or have never contributed to open-source before.\n\nSo here's to you, lovely person who wants to join us — this is how you can support us:\n\n* [Responding to questions on StackOverflow](https://stackoverflow.com/questions/tagged/fusillade)\n* [Passing on knowledge and teaching the next generation of developers](http://ericsink.com/entries/dont_use_rxui.html)\n* [Donations](https://reactiveui.net/donate) and [Corporate Sponsorships](https://reactiveui.net/sponsorship)\n* [Asking your employer to reciprocate and contribute to open-source](https://github.com/github/balanced-employee-ip-agreement)\n* Submitting documentation updates where you see fit or lacking.\n* Making contributions to the code base.\n","funding_links":["https://github.com/sponsors/reactivemarbles"],"categories":["C# #","Network"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freactiveui%2FFusillade","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freactiveui%2FFusillade","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freactiveui%2FFusillade/lists"}