Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improvements in EmbedIO.Net.Internal namespace; also, component collections are back. #448

Merged
merged 18 commits into from
Feb 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/EmbedIO/EmbedIO.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,15 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="Nullable" Version="1.2.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="Unosquare.Swan.Lite" Version="2.6.1" />
<PackageReference Include="Unosquare.Swan.Lite" Version="2.6.2" />
</ItemGroup>

</Project>
22 changes: 7 additions & 15 deletions src/EmbedIO/Files/FileModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -505,12 +505,12 @@ private async Task HandleResource(IHttpContext context, MappedResourceInfo info,
var partialUpperBound = contentLength - 1;
var isPartial = compressionMethod == CompressionMethod.None
&& context.Request.IsRangeRequest(contentLength, entityTag, info.LastModifiedUtc, out partialStart, out partialUpperBound);
var partialLength = contentLength;
var responseContentLength = contentLength;

if (isPartial)
{
// Prepare a "206 Partial Content" response.
partialLength = partialUpperBound - partialStart + 1;
responseContentLength = partialUpperBound - partialStart + 1;
context.Response.StatusCode = (int)HttpStatusCode.PartialContent;
PreparePositiveResponse(context.Response, info, contentType, entityTag, setCompressionInResponse);
context.Response.Headers.Set(HttpHeaderNames.ContentRange, $"bytes {partialStart}-{partialUpperBound}/{contentLength}");
Expand Down Expand Up @@ -548,18 +548,10 @@ await source.CopyToAsync(compressor, WebServer.StreamCopyBufferSize, context.Can
// Transfer cached content if present.
if (content != null)
{
if (isPartial)
{
context.Response.ContentLength64 = partialLength;
await context.Response.OutputStream.WriteAsync(content, (int)partialStart, (int)partialLength, context.CancellationToken)
.ConfigureAwait(false);
}
else
{
context.Response.ContentLength64 = content.Length;
await context.Response.OutputStream.WriteAsync(content, 0, content.Length, context.CancellationToken)
.ConfigureAwait(false);
}
context.Response.ContentLength64 = responseContentLength;
var offset = isPartial ? (int) partialStart : 0;
await context.Response.OutputStream.WriteAsync(content, offset, (int)responseContentLength, context.CancellationToken)
.ConfigureAwait(false);

return;
}
Expand Down Expand Up @@ -588,7 +580,7 @@ await context.Response.OutputStream.WriteAsync(content, 0, content.Length, conte
}
}

var transferSize = partialLength;
var transferSize = responseContentLength;
while (transferSize >= WebServer.StreamCopyBufferSize)
{
var read = await source.ReadAsync(buffer, 0, WebServer.StreamCopyBufferSize, context.CancellationToken)
Expand Down
6 changes: 4 additions & 2 deletions src/EmbedIO/Files/Internal/FileCacheItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace EmbedIO.Files.Internal
{
internal sealed class FileCacheItem
{
#pragma warning disable SA1401 // Field should be private - performance is a strongest concern here.
#pragma warning disable SA1401 // Field should be private - performance is a stronger concern here.
// These fields create a sort of linked list of items
// inside the cache's dictionary.
// Their purpose is to keep track of items
Expand All @@ -21,6 +21,8 @@ internal sealed class FileCacheItem
// Size of a WeakReference<T> in bytes
private static readonly long SizeOfWeakReference = Environment.Is64BitProcess ? 16 : 32;

private readonly object _syncRoot = new object();

// Educated guess about the size of an Item in memory (see comments on constructor).
// 3 * SizeOfPointer + total size of fields, rounded up to a multiple of 16.
//
Expand Down Expand Up @@ -122,7 +124,7 @@ internal FileCacheItem(FileCache.Section section, DateTime lastModifiedUtc, long
// This is the bare minimum locking we need
// to ensure we don't mess sizes up.
byte[]? oldContent;
lock (this)
lock (_syncRoot)
{
switch (compressionMethod)
{
Expand Down
33 changes: 33 additions & 0 deletions src/EmbedIO/HttpContextExtensions-Redirect.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System;
using System.Net;
using EmbedIO.Utilities;

namespace EmbedIO
{
partial class HttpContextExtensions
{
/// <summary>
/// Sets a redirection status code and adds a <c>Location</c> header to the response.
/// </summary>
/// <param name="this">The <see cref="IHttpContext"/> interface on which this method is called.</param>
/// <param name="location">The URL to which the user agent should be redirected.</param>
/// <param name="statusCode">The status code to set on the response.</param>
/// <exception cref="NullReferenceException"><paramref name="this"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentNullException"><paramref name="location"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentException">
/// <para><paramref name="location"/> is not a valid relative or absolute URL.<see langword="null"/>.</para>
/// <para>- or -</para>
/// <para><paramref name="statusCode"/> is not a redirection (3xx) status code.</para>
/// </exception>
public static void Redirect(this IHttpContext @this, string location, int statusCode = (int)HttpStatusCode.Found)
{
location = Validate.Url(nameof(location), location, @this.Request.Url);

if (statusCode < 300 || statusCode > 399)
throw new ArgumentException("Redirect status code is not valid.", nameof(statusCode));

@this.Response.SetEmptyResponse(statusCode);
@this.Response.Headers[HttpHeaderNames.Location] = location;
}
}
}
24 changes: 0 additions & 24 deletions src/EmbedIO/HttpContextExtensions-Responses.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,30 +12,6 @@ partial class HttpContextExtensions
private const string StandardHtmlHeaderFormat = "<html><head><meta charset=\"{2}\"><title>{0} - {1}</title></head><body><h1>{0} - {1}</h1>";
private const string StandardHtmlFooter = "</body></html>";

/// <summary>
/// Sets a redirection status code and adds a <c>Location</c> header to the response.
/// </summary>
/// <param name="this">The <see cref="IHttpContext"/> interface on which this method is called.</param>
/// <param name="location">The URL to which the user agent should be redirected.</param>
/// <param name="statusCode">The status code to set on the response.</param>
/// <exception cref="NullReferenceException"><paramref name="this"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentNullException"><paramref name="location"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentException">
/// <para><paramref name="location"/> is not a valid relative or absolute URL.<see langword="null"/>.</para>
/// <para>- or -</para>
/// <para><paramref name="statusCode"/> is not a redirection (3xx) status code.</para>
/// </exception>
public static void Redirect(this IHttpContext @this, string location, int statusCode = (int)HttpStatusCode.Found)
{
location = Validate.Url(nameof(location), location, @this.Request.Url);

if (statusCode < 300 || statusCode > 399)
throw new ArgumentException("Redirect status code is not valid.", nameof(statusCode));

@this.Response.SetEmptyResponse(statusCode);
@this.Response.Headers[HttpHeaderNames.Location] = location;
}

/// <summary>
/// Asynchronously sends a string as response.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion src/EmbedIO/HttpResponseExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public static void SetEmptyResponse(this IHttpResponse @this, int statusCode)

@this.StatusCode = statusCode;
@this.StatusDescription = statusDescription;
@this.ContentType = string.Empty;
@this.ContentType = MimeType.Default;
@this.ContentEncoding = null;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/EmbedIO/ICookieCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public interface ICookieCollection : IEnumerable<Cookie>, ICollection
/// </value>
/// <param name="name">The name.</param>
/// <returns>The cookie matching the specified name.</returns>
Cookie this[string name] { get; }
Cookie? this[string name] { get; }

/// <summary>
/// Determines whether this <see cref="ICookieCollection"/> contains the specified <see cref="Cookie"/>.
Expand Down
2 changes: 1 addition & 1 deletion src/EmbedIO/IHttpMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ public interface IHttpMessage
/// </value>
Version ProtocolVersion { get; }
}
}
}
2 changes: 1 addition & 1 deletion src/EmbedIO/IWebModuleContainer.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using System.Collections.Concurrent;
using Swan.Collections;
using EmbedIO.Utilities;

namespace EmbedIO
{
Expand Down
2 changes: 1 addition & 1 deletion src/EmbedIO/Internal/DummyWebModuleContainer.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System.Collections.Concurrent;
using System.Runtime.CompilerServices;
using Swan;
using Swan.Collections;
using EmbedIO.Utilities;

namespace EmbedIO.Internal
{
Expand Down
2 changes: 1 addition & 1 deletion src/EmbedIO/Internal/WebModuleCollection.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Swan.Collections;
using EmbedIO.Utilities;
using Swan.Logging;

namespace EmbedIO.Internal
Expand Down
2 changes: 1 addition & 1 deletion src/EmbedIO/ModuleGroup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
using System.Threading;
using System.Threading.Tasks;
using EmbedIO.Internal;
using Swan.Collections;
using EmbedIO.Utilities;

namespace EmbedIO
{
Expand Down
28 changes: 6 additions & 22 deletions src/EmbedIO/Net/Internal/HttpListenerRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public Encoding ContentEncoding
public bool IsAuthenticated => false;

/// <inheritdoc />
public bool IsLocal => LocalEndPoint?.Address?.Equals(RemoteEndPoint?.Address) ?? true;
public bool IsLocal => LocalEndPoint.Address?.Equals(RemoteEndPoint.Address) ?? true;

/// <inheritdoc />
public bool IsSecureConnection => _context.Connection.IsSecure;
Expand All @@ -124,28 +124,12 @@ public bool KeepAlive
if (_kaSet)
return _keepAlive;

_kaSet = true;

// 1. Connection header
// 2. Protocol (1.1 == keep-alive by default)
// 3. Keep-Alive header
var cnc = Headers[HttpHeaderNames.Connection];
if (!string.IsNullOrEmpty(cnc))
{
_keepAlive = string.Compare(cnc, "keep-alive", StringComparison.OrdinalIgnoreCase) == 0;
}
else if (ProtocolVersion == HttpVersion.Version11)
{
_keepAlive = true;
}
else
{
cnc = Headers[HttpHeaderNames.KeepAlive];

if (!string.IsNullOrEmpty(cnc))
_keepAlive = string.Compare(cnc, "closed", StringComparison.OrdinalIgnoreCase) != 0;
}
var cnc = Headers.GetValues(HttpHeaderNames.Connection);
_keepAlive = ProtocolVersion < HttpVersion.Version11
? cnc != null && cnc.Length == 1 && string.Compare(cnc[0], "keep-alive", StringComparison.OrdinalIgnoreCase) == 0
: cnc == null || cnc.All(s => string.Compare(s, "close", StringComparison.OrdinalIgnoreCase) != 0);

_kaSet = true;
return _keepAlive;
}
}
Expand Down
Loading