When dealing with JSON data, and you dealing with large result sets, say larger than a 1MB or so, it will definitely be feasible in many situation to zip the data before sending it to your client application.
The first step is to add zipping to the pipeline that Nancy uses, we then check that the content type returned in the response is JSON and we check that the client can accept the encoding of GZIP.
public static void AddGZip(IPipelines pipelines) { pipelines.AfterRequest += ctx => { if ((!ctx.Response.ContentType.Contains("application/json")) || !ctx.Request.Headers.AcceptEncoding.Any( x => x.Contains("gzip"))) return; var jsonData = new MemoryStream(); ctx.Response.Contents.Invoke(jsonData); jsonData.Position = 0; if (jsonData.Length < 4096) { ctx.Response.Contents = s => { jsonData.CopyTo(s); s.Flush(); }; } else { ctx.Response.Headers["Content-Encoding"] = "gzip"; ctx.Response.Contents = s => { var gzip = new GZipStream(s, CompressionMode.Compress, true); jsonData.CopyTo(gzip); gzip.Close(); }; } }; }
Perfect, now what we want to do is also, is in the CLIENT application calling the rest service, we need to add a header to the request so the server knows is supports GZIP:
Accept-Encoding: gzip
So, we add this code to the client.
Request sent by client.
protected WebRequest AddHeaders(WebRequest request) { request.Headers.Add("Accept-Encoding", "gzip"); return request; }
Response processed by client.
if (((HttpWebResponse)response).ContentEncoding == "gzip" && response.ContentType.Contains("application/json")) { var gzip = new GZipStream(response.GetResponseStream(), CompressionMode.Decompress, true); var readerUnzipped = new StreamReader(gzip); Response = Deserialize(readerUnzipped); } else { Response = Deserialize(reader); }
Implement whatever deserializer you want, and then make sure you close the stream, reader.close π
Nice, saved me remembering how to do this π
Need to fix your code example though, it’s all escaped which makes the old cut and paste more difficult π