unosquare / embedio

A tiny, cross-platform, module based web server for .NET
http://unosquare.github.io/embedio
Other
1.46k stars 176 forks source link

Add ResponseSerializer.None #501

Closed rdeago closed 3 years ago

rdeago commented 3 years ago

Some users have been asking for a way to not serialize WebApiModule responses. The rationale is that Web API controllers are the easiest way to write server code, but one may want to return HTML, an image, or whatever, instead of JSON data.

ResponseSerializer.None

This PR adds a ResponseSerializer.None method that can be used when initializing a WebApiModule as follows:

            var server = new WebServer(o => o
                // ... other initialization code ...
                .WithWebApi("/api", ResponseSerializer.None(false), m => m
                    .WithController<MyController>())
                // ... other initialization code ...

Chunked transfer encoding vs. buffering

The false parameter in the code snippet above tells EmbedIO to send data directly to the client using chunked transfer encoding. Although this has always been the behavior of ResponseSerializer.Json, some clients require a Content-Length header to be present in the response; by specifying ResponseSerializer.None(true) the response will be buffered in memory and sent all at once, along with a Content-Length header.

Supported data types

If a controller method returns void, Task<void>, or otherwise returns a null value, the response will have no body.

If a controller method returns byte[] or Task<byte[]>, ResponseSerializer.None will send the returned array of bytes as-is.

If a controller method returns string or Task<string>, ResponseSerializer.None will send the returned string, encoded according to context.ContentEncoding.

Any other type (or result type, for asynchronous controller methods) will be converted to a string via its ToString method and sent as specified in the previous paragraph.

Response compression

ResponseSerializer.None will negotiate content compression according to context.ContentType and relevant request headers, the same way FileModule does.

Additions to ResponseSerializer.Json

This PR adds three new overloads to the ResponseSerializer.Json method, to allow for buffering of JSON responses. Existing overloads will continue to use chunked transfer encoding.

The new overloads, as well as the previously existing ones, will also negotiate content compression the same way as ResponseSerializer.None (which all of them now use under the hood).

WebServer.Utf8NoBomEncoding

Another addition is the static WebServer.Utf8NoBomEncoding property, a UTF-8 encoding that does not send a byte order mark at the start of a response stream. Some clients, especially non-Windows clients, may get confused by the byte order mark, which is also totally redundant given that text encoding is (or should be) specified in the Content-Type response header; this had been fixed in ResponseSerializer.Json, but not on a global level. The WebServer.DefaultEncoding property is now set to Utf8NoBomEncoding.

Other modifications

The target platform for tests and samples is now net5.0; GitHub actions have been updated accordingly.

Dependency versions are now managed centrally via a Directory.Packages.props file.

The Directory.Build.props file is now in the repository root instead of the src folder and centralizes common build options, as well as development dependencies such as analyzers.

The library version specified in Directory.Build.props is now 3.5.0, which makes sense given the added funcionality.

All dependency versions have been updated; most noticeably, EmbedIO now uses SWAN version 3.1.0.

Finally, I did some some trivial code cleanup, mostly by adding discards on unused expressions values.