Releases: sisk-http/core
v1.3
v.1.3
Sisk 1.3 is being released today! This update brings performance improvements, another way to write your favorite APIs, and something similar to dependency injection.
Sisk's commitment remains the same: to be simple to develop a quality HTTP application. Sisk has no dependencies other than the .NET ecosystem itself, and all its code is still less than 1KB in total. Sisk has a minimal footprint, focusing performance on your application's layer, not the server.
We would also like to showcase the new logo of the project. It is more modern while still referencing what the project used to be.
Performance improvements
Sisk has a limitation: it depends on the current implementation of HttpListener to work. This implementation is great on Windows and has performance comparable to ASP.NET, but in recent tests, we found that the managed implementation of HttpListener lags significantly behind ASP.NET's Kestrel, which happens outside Windows environments. Even so, Sisk still manages to be much more performant and efficient than many other development frameworks in other languages. Our goal is not to be better than ASP.NET, but the closer we get to its performance, the more viable the choice of Sisk becomes for more projects.
In version 1.3, we achieved an average performance increase of 15% overall for request processing. This is because we improved the way the server sends the content of a response to the client. The HttpResponse object depends on HttpContent to define content to send to the client, and previously, this object had to be serialized through HttpContent.ReadAsByteArrayAsync. The problem is that many contents are based on ByteArrayContent, and when calling this method on this type of content, a memory buffer was created, and the response bytes were copied to this buffer. Then, this buffer was copied to the response's output stream.
Thanks to UnsafeAccessor in .NET 8, we can access the response bytes directly, without the need to create this secondary buffer. This greatly improved overall performance.
In addition, there were performance improvements outside of the request processor as well. Improvements were made in the way the server writes messages to the access log and deserializes multipart content.
Static HttpContexts
An experimental feature is to expose the current HttpContext of a request in a local context of the execution thread. This allows you to expose members of a request outside the request method, greatly improving the readability of your code. The code snippet below shows an abstract class that functions as an API controller with an embedded database.
public abstract class Controller : RouterModule
{
public DbContext Database
{
// Create or get an new DbContext instance
get => HttpContext.Current.RequestBag.GetOrAdd(() => new DbContext());
}
// Exposing the HttpRequest instance is supported too
public HttpRequest Request { get => HttpContext.Current.Request; }
protected override void OnSetup(Router parentRouter)
{
base.OnSetup(parentRouter);
HasRequestHandler(RequestHandler.Create(
execute: (req, ctx) =>
{
// disposes the current DbContext if used
ctx.RequestBag.GetOrDefault<DbContext>()?.Dispose();
return null;
},
executionMode: RequestHandlerExecutionMode.AfterResponse));
}
}
And use this implementation with methods that do not have an HttpRequest parameter, as you already have a Request in your controller instance.
[RoutePrefix("/api/posts")]
public class PostsController : Controller
{
[RouteGet]
public IEnumerable<Blog> ListPosts()
{
return Database.Posts
.Where(post => post.AuthorId == AuthenticatedUser.Id)
.ToList();
}
[RouteGet("<id>")]
public Post GetPost()
{
int blogId = Request.RouteParameters["id"].GetInteger();
Post? post = Database.Posts
.FirstOrDefault(post => post.Id == blogId && post.AuthorId == AuthenticatedUser.Id);
return post ?? new HttpResponse(404);
}
}
You can read more about this feature in the documentation.
Full changelog
New features:
- New logo.
- Added support for .NET 9.
- Added the
StringKeyStore.SetRange
method. - Added the
TypedValueDictionary.GetOrDefault<T>
method. - Added the
TypedValueDictionary.GetOrAdd<T>
method. - Added the
TypedValueDictionary.GetOrAddAsync<T>
method. - Added the
HttpRequest.Uri
property. - Added the
HttpServerExecutionResult.Elapsed
property. - Added the
HttpContext.Current
static property. - Added the
HttpResponseExtensions.WithHeader(StringKeyStore)
method. - Added the
MimeHelper.DefaultMimeType
static property. - Added the
MimeHelper.IsBrowserKnownInlineMimeType(string)
method. - Added the
HttpServerFlags.PreventResponseContentsInProhibitedMethods
flag. - Added the
Route.Get
,Route.Post
,Route.Put
,Route.Delete
,Route.Head
,Route.Options
,Route.Any
andRoute.Patch
static methods. - Added the
RouterModule.OnSetup
virtual method. - Added the
CookieHelper
static class.
Changes:
- Improved the path matching algorithm.
- Improved the log writer algorithm.
- The HTTP server will now show an warning when it's starting without any route defined.
- Changed type from
Router.Action
fromRouteAction
toDelegate
. - Changed return type from
TypedValueDictionary.Unset
fromvoid
tobool
. - Fixed when the HTTP server was starting with one random port and defined ports when using portable configurations.
Fixes:
- Fixed the
TypedValueDictionary.IsSet<T>
attribute usage. - Fixed an issue where byte counts were being calculated with decimals in
SizeHelper.HumanReadableSize
.
Breaking changes:
- Removed the
HttpKnownHeaderNames.From
member. - Removed the
HttpRequest.GetQueryValue
methods. - Removed the
HttpServer.GetVersion()
method. You can still use theHttpServer.PoweredBy
property instead. - Route/paths parameters will not be added into
HttpRequest.Query
anymore. You should use theHttpRequest.RouteParameters
property instead. - Made
CookieHelper
and static class and removed it from all classes who used it. You still can use theSetCookie
methods from where it was defined. - Deprecated the
HttpServerConfiguration.DefaultEncoding
property.
Thank you for using Sisk!
v1.2
v1.2
This changelog includes changes from v1.0.2 to v1.2.0.
What's Changed
- Added the
StringValue.Create(string)
method. - Added the
HttpResponse(HttpStatusInformation)
constructor. - Added
IEquatable<Route>
toRoute
class. - Added
IEquatable<MultipartObject>
toMultipartObject
class. - Added
notnull
for constraint<T>
of theValueResult<T>
class. - Added the
DefaultPageCSS
static property toDefaultMessagePage
class. - Added the
CreateBuilder(string)
static method toHttpServer
class. - Added experimental support for listening ports paths instead only listening at the root index.
- Added the
ListeningPort.Path
property, plus their constructors. - Added the
HttpRequest.RouteParameters
property. In next Sisk versions, all path/route parameters will be moved to this property insteadHttpRequest.Query
. For now, theQuery
property will have the same behavior as before. - Added boolean operators for
HttpStatusInformation
struct. - Added the
StringKeyStore
class. - Added the
CookieHelper.BuildCookieHeaderValue
static method. - Added the
ConfigurationFileLookupDirectory
enum toPortableConfigurationBuilder.WithConfigFile
method. - Added the
HttpContext.ExtraHeaders
property. - Added the extension method
HttpResponse.WithCookie(Cookie)
method. - Added the
HttpServerExecutionResult.Context
property. - Improved the
ListeningPort.Parse
method. - Improved various
CookieHelpers
methods syntax signatures. - The
HttpContext.Router
property ins't nullable anymore. - The
HttpServerConfiguration.AccessLogsStream
property nows defaults toLogStream.ConsoleOutput
. - The
HttpRequestException
is now sealed. - The
HttpResponse.Headers
property ins't read-only anymore. - The
HttpServerFlags.EnableNewMultipartFormReader
is now enabled by default. If you encounter problems with the Multipart form parser, you can disable it and use the old parser. - The
Router.GlobalRequestHandlers
ins't nullable anymore. And it is anList<IRequestHandler>
insteadIRequestHandler[]
now. - The
Router.NotFoundErrorHandler
andRouter.MethodNotAllowedErrorHandler
now, by default, returns an HTML response fromDefaultMessagePage
if the requests acceptstext/html
. You can disable this behavior by overriding the mentioned properties. - The
ServerConfiguration.MaximumContentLength
property is nowInt64
insteadInt32
. - Route matching and conflict catching algorithms improved.
- Removed string-based route-path algorithms.
- Fixed an issue regarding how the
CertificateUtil
class generates hashcodes for DNS names. - Fixed various documentation members typos.
- Fixed an issue where the
Expires
andLast-Modified
headers fromHttpContentHeaders
objects weren't being sent as universal time, but local time. - Fixed more issues related ot the
HttpContentHeaders
. - Fixed an issue where the
HttpServer
weren't releasing theWaitNext()
method on dispose. - Fixed an issue related to
HttpWebSocket
connections not being correctly closed. - Fixed
Sisk.SslProxy
HTTP serializer and deserializer issues. - Fixed logic error on
StringValueCollectoin.TryGetValue
. - Fixed multiple issues related to the
IniConfigurationReader
INI-configuration reader. - Fixed numeric errors on
SizeHelper
constants.
Breaking and deprecating changes:
- [Breaking] Dropped support for .NET 6 and 7. These versions will be maintained until November 30, 2024, in the
legacy
1.0.x branch for severe bugs and critical security issues. - [Breaking] Removed the
HttpServerHostContextBuilder.UseAutoScan(bool)
method. Thebool
parameter was removed. - [Breaking] Removed the
HtmlContent.DefaultEncoding
static property. It now evaluates toEncoding.Default
. - [Breaking] Removed the
HttpRequest.SetContextBag*
andHttpRequest.GetContextBag*
methods. You should use theHttpRequest.Bag
property instead. - [Breaking] Removed the
HttpRequest.Close*
method. You should use theHttpResponse.Refuse()
method instead. - [Breaking] Removed the
HttpResponse.CreateEmptyResponse
method. You should use the emptyHttpResponse
constructor instead. - [Breaking] Removed the
HttpResponse.CreateRedirectResponse
method. - [Breaking] Removed the
HttpResponse.StatusInformatoin
property. You should use theHttpResponse.Status
property instead. - [Breaking] The
AutoScanModules
methods (onRouter
andHttpServerHostContextBuilder
) now automatically set static classes as static members and searches for instance and static methods in instance classes if an public constructor is found. - [Breaking] The
RouterModule.HasRequestHandler(IRequestHandler)
method is nowprotected
. Before waspublic
. - [Breaking] Renamed the
Sisk.IniConfiguration.IniConfigurationPipeline
class name toIniConfigurationReader
. - [Depreated] the
HttpRequest.GetQueryValue
andHttpRequest.GetQueryValue<T>(string)
methods are now deprecated. You should use theHttpRequest.Query
property instead.
v1.1.1
What's Changed
- Fix logic in StringValueCollection.TryGetValue by @khalidabuhakmeh in #11
New Contributors
- @khalidabuhakmeh made their first contribution in #11
Full Changelog: 1.0.2.0...1.1.1.0
v1.0.2
- Added the
HttpServerHostContextBuilder.UseStartupMessage
method. - Added the
HttpServer.CreateListener()
method. - Added the
WaitTimeout
property toHttpWebSocket
. - Added the
HttpWebSocket.WaitNext(TimeSpan)
overload method. - Made
StringValue
andStringValueCollection
contructors public. - Now
IRequestHandler
can be applied on classes declarations. - Breaking: renamed the
PortableConfigurationBuilder.WithConfigurationPipeline
method toWithConfigReader
. - Improved the server exception message for
ServerConfiguration.ErrorsLogsStream
errors. - The
HttpWebSocket.WithPing
is not really fluent and returns the selfHttpWebSocket
instance as parameter. - Deprecate
HttpRequest.Close
method. You should use the newHttpResponse.Refuse()
method instead. - Deprecate
HttpResponse.CreateEmptyResponse()
method. - Fixed an issue where exceptions raised on HttpRequestHandler methods
ServerStarting
,ServerStarted
andSetupRouter
would be ignored. Eexceptions within these handlers are now thrown. - Fixed an deadlock in
HttpServerHostContext.Dispose()
method. #10
v1.0
v0.16.2
v0.16.1
v0.16
v0.16-rc-3
- fixed an issue
HttpRequest.GetQueryValue
would throw other exceptions besidesInvalidCastException
. - fixed an issue that read streams wasn't positioned at zero before sending again.
- fixed an issue regarding
Router.AutoScan<>
v0.15.3
This update includes an critical bugfix for v.0.15.3 and v.0.16-rc-3:
- when using
ResolveForwardedOriginAddress
, the forwarded IP was not the proxy IP.