Notes :
- it does not strictly follow the semver convention.
- no technical debt : code that's need to be refactored/broken, will be.
- when something breaks, it's documented and a migration guide is provided.
- no long-term support or backports for major versions, just stick to the latest update.
- found a bug or way to optimize, feel free to submit a patch.
- docker template
- dotnet template
- captcha module
- HTTP/3 quic
After months of rewrite, testing, release candidates, breaking changes, documentation work, and a few painful but necessary design decisions, SimpleW v26 is finally ready.
This release is not just an update. It is a complete rewrite of SimpleW.
The old version was built on top of NetCoreServer, mostly through overrides and custom extensions. It worked, it was fast, and it served the project well for a long time. But over time, SimpleW needed its own HTTP architecture: something simpler, cleaner, easier to extend, and easier to maintain.
So v26 was rebuilt from scratch.
The result is a smaller and more explicit core, still focused on performance, but now designed around SimpleW's own model: middleware, modules, addons, a cleaner request/response lifecycle, better routing, better observability, stronger request protection, and a much better foundation for real applications.
- Complete rewrite from scratch
- New middleware and module architecture
- New addon ecosystem
- Cleaner routing, including host-based routing
- Sync and async handlers with request cancellation
- Better static files support with cache, Last-Modified, ETag and Content-Range
- WebSocket and SSE modules with room-based broadcasting
- New Principal / Identity authentication model
- Logging, traces, metrics and enrichment per server instance
- Better malformed request protection
- Easier extensibility with custom router and engine support
- Updated documentation and migration guide
Several addons are already available, including BasicAuth, Jwt, OpenID, Firewall, Hosting, Razor, Swagger, LetsEncrypt, Templates, Serilog, Log4net and Dependency Injection.
SimpleW v26 is now minimal by default, fast by design, and much easier to compose for production applications.
Thank you to everyone who followed the rewrite, tested the prereleases, read the documentation, reported issues, or simply waited patiently.
Now the real fun begins.
There is a complete migration guide.
| Feature / Aspect | SimpleW v16 (old) | SimpleW v26 (new) |
|---|---|---|
| NET runtime | NET8 | NET8 but should consider NET9/NET10 for better perfs and RAM usage under heavy load (e.g: NET8 400Mo, NET9 100Mo, NET10 70Mo) |
| Core architecture | ✅ from scratch (custom, simple, clean) | |
| Code readability | ✅ | |
| Overall design philosophy | ✅ minimal, custom, fast | |
| Long-term maintainability | ✅ much easier | |
| Performance | ✅ (very high) | ✅ (very high) |
| Middleware | ❌ | ✅ |
| Modules | ❌ | ✅ |
| Extensibility | ✅ middleware, module, callback, subclass | |
| Custom Router / Engine | ❌ | ✅ UseRouter(), UseEngine() |
| Response Builder | ✅(status, contentType, headers, body, cookies) | ✅ (status, contentType, contentLength, headers, body, cookies, compression) |
| Result Handler | ❌ | ✅ configurable response pipeline |
| Handler (Expression Tree) | ✅ sync ❌async | ✅ sync ✅ async + RequestAborted |
| Handler metadata | ❌ | ✅ metadata attributes for middleware and addons |
| Routing | ✅ (minimal, attribute, querystring, regexp, path, wildcard) | ✅ (minimal, attribute, querystring, path, wildcard, host) |
| Minimal API | ✅ | ✅ |
| Controllers | ✅ | ✅ |
| Dependency Injection | ❌ | ✅ (using the Dependency Injection addon) |
| SSL / HTTPS | ✅ (SslContext) | ✅ (SslContext, mutual authentication) |
| WebSocket | ✅ (full broadcast) | ✅ (smart broadcast using "rooms") |
| Server-Sent Events (SSE) | ✅ | ✅ (smart broadcast using "rooms") |
| Unix socket | ✅ | ✅ |
| Static files | ✅ (Cache, FileWatcher) | ✅ (Cache, FileWatcher, Last-Modified, Etag) |
| Cross-Origin Resource Sharing (CORS) | ✅ | ✅ |
| Body parsing (JSON) | ✅ | ✅ |
| Body parsing (form-urlencoded) | ✅ | ✅ |
| Body parsing (multipart/form-data) | ✅ | ✅ + streaming parser |
| Bag | ❌ | ✅ (share data between middleware) |
| Auth | ✅ Principal / Identity | |
| Custom JSON engine | ✅ | ✅ |
| HTTP pipelining | ❌ | ✅ |
| Content Range | ❌ | ✅ |
| Idle Timeout | ❌ | ✅ |
| Request Protection | ❌ | ✅(malformed) |
| Observability | ✅ (traces) & global to all processes | ✅ (traces, metrics, enrich) per SimpleWServer instance |
| Logging | ❌ | ✅ sinks, levels, lazy logging, bridges |
| Listener reload | ❌ | ✅ ReloadListenerAsync() |
| Documentation | ✅ | ✅ simplew.net |
| Tests | ✅ | ✅ (more tests) |
| Support | ❌ | ✅ Discord |
| Addons | ❌ | ✅ BasicAuth, Chaos, Firewall, Hosting, Jwt, Latency, Log4net, OpenID, Razor, Swagger, LetsEncrypt, Templates, Serilog, DependencyInjection, Newtonsoft |
Maintenance, rewritten some parts of the code and documentation for easier use.
- moved the
Controller.MakeAccessResponse()toHttpResponse.MakeAccessResponse()(see example)
- feature: add headers parameter to
HttpResponse.MakeResponse()(#71) - feature: add new
HttpResponse.MakeResponse(object content)methods (#75) - chore: inject
SessioninResponse(#73) - feature(test): add unit test for custom headers and compress types (#80)
- feature: avoid
PerformServerUpgradethere is no websocket route defined (#79) - refactor: move
MakeAccessResponse()intoHttpResponseclass (#76)
- fix(NetCoreServer):
WebSocket.PerformServerUpgrade()setMakeErrorResponse()whenConnection: "keep-alive"(#77)
Major release, including extensive rewrites and significant performance improvements (+9% req/s)
- removed the Newtonsoft.Json dependency from the SimpleW nuget package. The default json engine is now System.Text.Json. To switch back, set Newtonsoft as the
JsonEngineand install the a new SimpleW.Newtonsoft nuget package to (see example) - "X-*" headers are not trusted by default. To allow them, set the
TrustXHeadersserver property to true (see example). - in
Controller, allMake*Response()methods have been replaced byResponse.Make*Response()(see example) - removed
Controller.SendResponseAsync() - the cache in
AddStaticContent()is now disabled by default. Set thetimeoutparameter to enable caching (see example)
- feature: add new
JsonEngineproperty in Server and Netcoreserverextension (#49) - feature: add new package SimpleW.Newtonsoft to support Newtonsoft.Json as
JsonEngine(#50) - chore: remove the Newtonsoft.Json dependency from the SimpleW package
- feature: use
JsonEnginefor Inline Func return serialization (#58) - feature: support Accept-Encoding br (Brotli) on
HttpResponse(#51) - chore: move all Make*Response from
ControllertoHttpResponsepartial class (#44) - feature: support CORS in
AddStaticContent()response (#60) - feature:
AddStaticContent()with no cache (#46) - feature: improve overall performances in
Router,StaticContentandDynamicContent - feature(test): add unit and integration tests.
- fix: add new property
TrustXHeaders(#48)
Maintenance
- chore: expose the
Serveras a property from theSession(#47) - feature: support minimal API with new
MapGet()andMapPost()methods in server class (#45)
Major release
- telemetry is now disabled by default. To enable it, set
EnableTelemetryproperty totrue(#42)
- fix: AutoIndex must sort directory first then file (#11)
- chore: add missing constructor from NetCoreServer (#43)
- chore: throw exception when using component while the server is already started (#41)
- feature: handle unix socket (#38), PR by philippseith
- feature: add new server
EnableTelemetryproperty to enable telemetry (#42)
Maintenance
- fix possible null exception in
BroadcastSSESessions()(#37)
- feature: support CORS in Server Sent Events with
MakeServerSentEventsResponse()(#40)
Major release
- create a documentation website
- feature: support Server Sent Events SSE (#34)
- chore: update nuget package informations (description, tags, logo, url)
- refactor: rename all properties
WebUserstoWebSocketUsersinISimpleWServer(#36)
Maintenance
- fix payload parsing for 64 byte payloads (#32), PR by baris-btcturk
- made possible to append extra response http headers in PerformServerUpgrade stage (#31), PR by lifeengines to fix bramley-jetcharge issue
Major release
- fix: possible header mismatch when upgrading to websocket connection (#27)
- chore: bump to NET8 (#26)
Maintenance
- backport fix from
Microsoft.IO.RecyclableMemoryStreamv3.0.1 to v2.3. - backport fix into
HttpMultipartDataParserv8.4.0
Major release
- support HTTPS protocol using the new
SimpleWSServer()class.
Maintenance
- the
getWebUserCallbackdelegate set withSimpleW.SetToken()is new call byController.JwtToWebUser()to redressController.webuseron each request.
Maintenance
- refactor: remove unused
expirationparameter fromNetCoreServerExtension.ValidateJwt()(#19) - refactor: remove unused
Controller.TokenExpirationproperty (#18)
- refactor: change jwt default create expiration from 30min to 15min (#20)
Maintenance
- rename
WebSocketMessage.datatoWebSocketMessage.body(#17)
- documentation
Maintenance
- remove
NetCoreServerExtension.GetBearer()method.
Controller.GetJwt()is now virtual and can be overrided in subclass.- documentation
Maintenance
- rename
SimpleW.SetTokenWebUserCallback()method toSimpleW.SetToken()and reorder parameters (#3). - rename
Controller.OnBeforeHandler()method toController.OnBeforeMethod().
- fix(AutoIndex): do not show ".." in root path (#10).
- feature(WebSocket): handle multiple socket endpoints and not just once (#9).
- documentation
Maintenance
- property
RegExpEnabledmust be explicitly enabled to allow regular expression in route path (#2). - refactor(Router): use
Dictionnary<Key, Route>whenRegExpEnabledis false, performances improvement (#1)
Maintenance
- update nuget package settings
Maintenance
- update nuget package settings
Maintenance
- fix wrong label and status for
OnWsDisconnectedlogging
Maintenance
- fix wrong label and status for
OnWsDisconnectedlogging
- add release-notes
- enhance logging
Maintenance
- remove
Prefixproperty fromRouteAttributeclass
- add new
AutoIndexproperty to list documents when defaultDocument does not exists - add new property
RegExpEnabledto force Router handle regular expression in Routes
Maintenance
- sync with upstream (NetCoreServer fix websocket closing)
- split
Routewith a newRouterclass - rename
ObjectMethodExecutortoControllerMethodExecutor - use
StringComparison.OrdinalIgnoreCase
Maintenance
- clean code
- add documentation
- add license
- include LitJWT sources in projet files
Major release
- fix huge performances degradation due to old
Trace.Trace*()methods
Maintenance
- rename
AddApiContent()toAddDynamicContent()
Maintenance
- throw error on starting static server when containing file which size is 0
- reorganize
CompileHandler()method - refactor
ObjectMethodExecutor.Controllers() - add some check to
AddApiContent()andAddWebSocketContent()methods - refactor
RouteAttribute.SetPrefix() - clean code
Maintenance
- refactor
mimeTable - add NetCoreServer Official Readme
- sync with upstream (HttpMultipartDataParser to v8.2.0)
Maintenance
- compliant to OpenTelemetry http semantic convention
Maintenance
- convert old trace to
system.diagnostics.Activityfor OpenTelemetry
Maintenance
- preliminary support of
system.diagnostics.Activityfor OpenTelemetry
Maintenance
- change scope from protected to public for
Controller.MakeResponse*()
Maintenance
- add new
MakeDownloadResponse(MemoryStream content)
Maintenance
- change
MakeRedirectResponse()scope to private
Maintenance
- add new helper
Controller.MakeRedirectResponse()
Maintenance
- clean code
Maintenance
- support
DateOnlyinController.Method()parameter
Maintenance
- sync with upstream (Newtonsoft v13.0.3)
BodyMap/JsonMap/BodyMapAnonymous: add new json custom converter for hh:mm timeonly
Maintenance
- add new
Controller.MakeResponse()
Major release
- refactor SimpleW with
BodyMap(),BodyMapAnonymous()andBodyFile()
- comment
Major release
- sync with upstream (NetCoreServer v7.0.0)
- sync with upstream (LitJWT v2.0.2)
- sync with upstream (Newtonsoft v13.0.2)
- retargeting to NET7
Maintenance
- uniformize http and websocket log
Maintenance
- comment
- replace special char
"in logging url
Maintenance
- logging error and exception
Maintenance
- refactor
Controller.GetWebUser()intoSetWebUser()andJwtToWebUser() - support
JWTinWebSocketconnexion
Maintenance
- refactor
SimpleWServer.AddWebSocketContent() - support
JWTinWebSocket
New Major Version
- fix null exception in
Controller.GetJwt()when parsing request url
- support
Websocket - support
Routefor websocket - refactor
SimpleWSession/Controllerwith(SimpleWServer)Session.Server
New Major Version
- rename
AddRESTContenttoAddApiContent
- remove exception message output when http 500 error
Maintenance
- sync with upstream (NetCoreServer v6.6.0)
- sync with upstream (Http-Multipart-Data-Parser v7.0.0)
Maintenance
- support CORS
- add new
HttpResponse.MakeCORSResponse()method
Maintenance
- replace
X-Schemeheader byX-Forwarded-Proto
- handle
X-Forwarded-Hostheader in log
Maintenance
- support
X-Schemerequest header for logging
Maintenance
- log full request url for file in cache and normalize log url
- log real remote ip
- refactor
Routewith the newFQURL()method
Maintenance
shouldSerializeContractResolver()handle nested class
Maintenance
- sync with upstream (NetCoreServer v6.5.0 fix websocket regression)
Maintenance
- add new parameter
descriptiontoRouteAttribute
Maintenance
- sync with upstream (NetCoreServer v6.4.0 with Span/Memory)
Maintenance
- sync with upstream NetCoreServer (fix deadlock in websocker/wssession)
- sync with upstream NetCoreServer (Add HTTP cookie SameSite=Strict mode)
- comment
- add new parameter
exceptstoSimpleW.AddRESTContent()to exclude controllers - support wildcard in
RouteAttribute
Maintenance
- sync with upstream package LitJWT from v1.2.0 to v2.0.1
Maintenance
- enhance http logging (time, status, user_agent...)
Maintenance
- add new parameter
expirationtoNetCoreServerExtension.CreateJwt()to controlJWTexpiration
Maintenance
- enhance http logging (time, status, user_agent...)
Maintenance
- add new paremeter
refreshinCreateJwt()to control howSessionshould refresh the underlying 'IWebUser'
Maintenance
- rename
NetCoreServerExtension.PostMap()toNetCoreServerExtension.JsonMap()
Maintenance
- rename
NetCoreServerExtension.GetBearerToken()toNetCoreServerExtension.GetBearer()
Maintenance
- replace logging
console.logbysystem.diagnostics
Maintenance
- change some method scope of Route class to private
- rename
Route.Parse()toRoute.ParseQueryString()
JWTHTTP Header can be override by ajwtquerystring in url- comment
- add new
NetCoreServerExtension.CreateJwt(IWebUser webuser) - refactor
ValidateJwtwith Generic - refactor and simplify
TokenWebUserclass
New Major Version
- rename class
ControllertoControllerBase
- add new parameter
TokenExpirationtoTokenWebUser
Maintenance
- rename
DelegateSetTokenWebUser(string login=null)toDelegateSetTokenWebUser(Guid id = new Guid())
Maintenance
- ignore case when parsing http header authorization
Maintenance
- add new ControllerBase
MakeForbiddenResponse()andMakeAccessResponse()
Maintenance
- replace
InvariantCulturewithOrdinal - remove
JsonSerializerSettingsDefaultCulturefromNetCoreServerExtension.PostMap() - enhance exception message in
NetCoreServerExtension.PostMap() - add comment
Maintenance
- retargeting to NET6
Maintenance
- add
Http-Multipart-Data-Parser
Maintenance
- remove debug message
Maintenance
- fix NetCoreServer
FileCache.InsertFileInternal()ReadAllBytes()error
Maintenance
- fix correct timestamp in console log
Maintenance
- fix netcoresever
FileCache - fix compressTypes in
ControllerBase.SendResponseAsync()
New Major Version
- sync with upstream (NetCoreServer v6.1.0)
Maintenance
- refactor
SimpleWServer.AddWebSocketContent()
Initial nuget package release
- rename
PostUpdate()toPostMap()
Maintenance
- support Guid parameter in
Controller.Method()
Maintenance
- parameter null converter in
Controller.Method()
Initial stable release
- serve Statics Files
- serve REST API
- routes
- set default document
- set custom mime type
- log with console.writeline