Exemplo n.º 1
0
        /// <summary>
        /// Asynchronously parses a request body in <c>application/x-www-form-urlencoded</c> format.
        /// </summary>
        /// <param name="this">The <see cref="IHttpContext"/> on which this method is called.</param>
        /// <returns>A <see cref="Task{TResult}">Task</see>, representing the ongoing operation,
        /// whose result will be a read-only <see cref="NameValueCollection"/>of form field names and values.</returns>
        /// <exception cref="NullReferenceException"><paramref name="this"/> is <see langword="null"/>.</exception>
        /// <remarks>
        /// <para>This method may safely be called more than once for the same <see cref="IHttpContext"/>:
        /// it will return the same collection instead of trying to parse the request body again.</para>
        /// </remarks>
        public static async Task <NameValueCollection> GetRequestFormDataAsync(this IHttpContext @this)
        {
            if ([email protected](FormDataKey, out var previousResult))
            {
                NameValueCollection result;
                try
                {
                    using var reader = @this.OpenRequestText();
                    result           = UrlEncodedDataParser.Parse(await reader.ReadToEndAsync().ConfigureAwait(false), false);
                }
                catch (Exception e)
                {
                    @this.Items[FormDataKey] = e;
                    throw;
                }

                @this.Items[FormDataKey] = result;
                return(result);
            }

            switch (previousResult)
            {
            case NameValueCollection collection:
                return(collection);

            case Exception exception:
                throw exception.RethrowPreservingStackTrace();

            case null:
                throw SelfCheck.Failure($"Previous result of {nameof(HttpContextExtensions)}.{nameof(GetRequestFormDataAsync)} is null.");

            default:
                throw SelfCheck.Failure($"Previous result of {nameof(HttpContextExtensions)}.{nameof(GetRequestFormDataAsync)} is of unexpected type {previousResult.GetType().FullName}");
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Parses a request URL query. Note that this is different from getting the <see cref="IHttpRequest.QueryString"/> property,
        /// in that fields without an equal sign are treated as if they have an empty value, instead of their keys being grouped
        /// as values of the <c>null</c> key.
        /// </summary>
        /// <param name="this">The <see cref="IHttpContext"/> on which this method is called.</param>
        /// <returns>A read-only <see cref="NameValueCollection"/>.</returns>
        /// <exception cref="NullReferenceException"><paramref name="this"/> is <see langword="null"/>.</exception>
        /// <remarks>
        /// <para>This method may safely be called more than once for the same <see cref="IHttpContext"/>:
        /// it will return the same collection instead of trying to parse the request body again.</para>
        /// </remarks>
        public static NameValueCollection GetRequestQueryData(this IHttpContext @this)
        {
            if ([email protected](QueryDataKey, out var previousResult))
            {
                NameValueCollection result;
                try
                {
                    result = UrlEncodedDataParser.Parse(@this.Request.Url.Query, false);
                }
                catch (Exception e)
                {
                    @this.Items[FormDataKey] = e;
                    throw;
                }

                @this.Items[FormDataKey] = result;
                return(result);
            }

            switch (previousResult)
            {
            case NameValueCollection collection:
                return(collection);

            case Exception exception:
                throw exception.RethrowPreservingStackTrace();

            case null:
                throw SelfCheck.Failure($"Previous result of {nameof(HttpContextExtensions)}.{nameof(GetRequestQueryData)} is null.");

            default:
                throw SelfCheck.Failure($"Previous result of {nameof(HttpContextExtensions)}.{nameof(GetRequestQueryData)} is of unexpected type {previousResult.GetType().FullName}");
            }
        }
Exemplo n.º 3
0
        protected override async Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            var serverRequest        = new TestRequest(Validate.NotNull(nameof(request), request));
            var cookiesFromContainer = CookieContainer.GetCookieHeader(serverRequest.Url);

            if (!string.IsNullOrEmpty(cookiesFromContainer))
            {
                serverRequest.Headers.Add(HttpHeaderNames.Cookie, cookiesFromContainer);
            }

            var context = new TestContext(serverRequest)
            {
                CancellationToken = cancellationToken,
                Route             = RouteMatch.UnsafeFromRoot(UrlPath.Normalize(serverRequest.Url.AbsolutePath, false)),
            };

            await _handler.HandleContextAsync(context).ConfigureAwait(false);

            var serverResponse  = context.TestResponse;
            var responseCookies = serverResponse.Headers.Get(HttpHeaderNames.SetCookie);

            if (!string.IsNullOrEmpty(responseCookies))
            {
                CookieContainer.SetCookies(serverRequest.Url, responseCookies);
            }

            var response = new HttpResponseMessage((HttpStatusCode)serverResponse.StatusCode)
            {
                RequestMessage = request,
                Version        = serverResponse.ProtocolVersion,
                ReasonPhrase   = serverResponse.StatusDescription,
                Content        = serverResponse.Body == null ? null : new ByteArrayContent(serverResponse.Body),
            };

            foreach (var key in serverResponse.Headers.AllKeys)
            {
                var responseHeaderType = GetResponseHeaderType(key);
                switch (responseHeaderType)
                {
                case ResponseHeaderType.Content:
                    response.Content?.Headers.Add(key, serverResponse.Headers.GetValues(key));
                    break;

                case ResponseHeaderType.Response:
                    response.Headers.Add(key, serverResponse.Headers.GetValues(key));
                    break;

                case ResponseHeaderType.None:
                    break;

                default:
                    throw SelfCheck.Failure("Unexpected response header type {responseHeaderType}.");
                }
            }

            return(response);
        }
Exemplo n.º 4
0
        public byte[]? GetContent(CompressionMethod compressionMethod)
        {
            // If there are both entity tag and content, use them.
            switch (compressionMethod)
            {
            case CompressionMethod.Deflate:
                if (_deflatedContent != null)
                {
                    return(_deflatedContent);
                }
                break;

            case CompressionMethod.Gzip:
                if (_gzippedContent != null)
                {
                    return(_gzippedContent);
                }
                break;

            case CompressionMethod.None:
                if (_uncompressedContent != null)
                {
                    return(_uncompressedContent);
                }
                break;

            default:
                throw SelfCheck.Failure($"Unexpected compression method {compressionMethod}.");
            }

            // Try to convert existing content, if any.
            byte[]? content;
            if (_uncompressedContent != null)
            {
                content = CompressionUtility.ConvertCompression(_uncompressedContent, CompressionMethod.None, compressionMethod);
            }
            else if (_gzippedContent != null)
            {
                content = CompressionUtility.ConvertCompression(_gzippedContent, CompressionMethod.Gzip, compressionMethod);
            }
            else if (_deflatedContent != null)
            {
                content = CompressionUtility.ConvertCompression(_deflatedContent, CompressionMethod.Deflate, compressionMethod);
            }
            else
            {
                // No content whatsoever.
                return(null);
            }

            return(SetContent(compressionMethod, content));
        }
Exemplo n.º 5
0
        private TResolver GetResolver(RouteMatcher matcher)
        {
            var resolver = _resolvers.FirstOrDefault(r => r.Matcher.Equals(matcher));

            if (resolver != null)
            {
                return(resolver);
            }

            resolver = CreateResolver(matcher);
            _resolvers.Add(resolver ?? throw SelfCheck.Failure($"{nameof(CreateResolver)} returned null."));
            return(resolver);
        }
Exemplo n.º 6
0
        public async Task ListDirectoryAsync(
            MappedResourceInfo info,
            string absolutePath,
            IEnumerable <MappedResourceInfo> entries,
            Stream stream,
            CancellationToken cancellationToken)
        {
            const int MaxEntryLength = 50;
            const int SizeIndent     = -20; // Negative for right alignment

            if (!info.IsDirectory)
            {
                throw SelfCheck.Failure($"{nameof(HtmlDirectoryLister)}.{nameof(ListDirectoryAsync)} invoked with a file, not a directory.");
            }

            var encodedPath = WebUtility.HtmlEncode(absolutePath);

            using var text = new StreamWriter(stream, Encoding.UTF8);
            text.Write("<html><head><title>Index of ");
            text.Write(encodedPath);
            text.Write("</title></head><body><h1>Index of ");
            text.Write(encodedPath);
            text.Write("</h1><hr/><pre>");

            if (encodedPath.Length > 1)
            {
                text.Write("<a href='../'>../</a>\n");
            }

            entries = entries.ToArray();

            foreach (var directory in entries.Where(m => m.IsDirectory).OrderBy(e => e.Name))
            {
                text.Write($"<a href=\"{Uri.EscapeDataString(directory.Name)}{Path.DirectorySeparatorChar}\">{WebUtility.HtmlEncode(directory.Name)}</a>");
                text.Write(new string(' ', Math.Max(1, MaxEntryLength - directory.Name.Length + 1)));
                text.Write(HttpDate.Format(directory.LastModifiedUtc));
                text.Write('\n');
                await Task.Yield();
            }

            foreach (var file in entries.Where(m => m.IsFile).OrderBy(e => e.Name))
            {
                text.Write($"<a href=\"{Uri.EscapeDataString(file.Name)}{Path.DirectorySeparatorChar}\">{WebUtility.HtmlEncode(file.Name)}</a>");
                text.Write(new string(' ', Math.Max(1, MaxEntryLength - file.Name.Length + 1)));
                text.Write(HttpDate.Format(file.LastModifiedUtc));
                text.Write($" {file.Length.ToString("#,###", CultureInfo.InvariantCulture),SizeIndent}\n");
                await Task.Yield();
            }

            text.Write("</pre><hr/></body></html>");
        }
Exemplo n.º 7
0
        /// <inheritdoc />
        protected override async Task OnRequestAsync([ValidatedNotNull] IHttpContext context)
        {
            var result = await _resolvers.UnsafeResolveAsync(context).ConfigureAwait(false);

            switch (result)
            {
            case RouteResolutionResult.RouteNotMatched:
            case RouteResolutionResult.NoHandlerSuccessful:
                await OnPathNotFoundAsync(context).ConfigureAwait(false);

                break;

            case RouteResolutionResult.NoHandlerSelected:
                await OnMethodNotAllowedAsync(context).ConfigureAwait(false);

                break;

            case RouteResolutionResult.Success:
                return;

            default:
                throw SelfCheck.Failure($"Internal error: unknown route resolution result {result}.");
            }
        }
 /// <summary>
 /// <para>Gets the underlying <see cref="IHttpContextImpl"/> interface of an <see cref="IHttpContext"/>.</para>
 /// <para>This API mainly supports the EmbedIO infrastructure; it is not intended to be used directly from your code,
 /// unless to fulfill very specific needs in the development of plug-ins (modules, etc.) for EmbedIO.</para>
 /// </summary>
 /// <param name="this">The <see cref="IHttpContext"/> interface on which this method is called.</param>
 /// <returns>The underlying <see cref="IHttpContextImpl"/> interface representing
 /// the HTTP context implementation.</returns>
 /// <exception cref="ArgumentNullException">
 /// <paramref name="this"/> is <see langword="null"/>.
 /// </exception>
 /// <exception cref="EmbedIOInternalErrorException">
 /// <paramref name="this"/> does not implement <see cref="IHttpContextImpl"/>.
 /// </exception>
 public static IHttpContextImpl GetImplementation(this IHttpContext @this)
 => Validate.NotNull(nameof(@this), @this) as IHttpContextImpl
 ?? throw SelfCheck.Failure($"{@this.GetType().FullName} does not implement {nameof(IHttpContextImpl)}.");