/// <summary> /// Sign out the specified authentication scheme. /// </summary> /// <param name="context">The <see cref="ProtoContext"/>.</param> /// <param name="scheme">The name of the authentication scheme.</param> /// <param name="properties">The <see cref="AuthenticationProperties"/>.</param> /// <returns>A task.</returns> public virtual async Task SignOutAsync(ProtoContext context, string scheme, AuthenticationProperties properties) { if (scheme == null) { var defaultScheme = await Schemes.GetDefaultSignOutSchemeAsync(); scheme = defaultScheme?.Name; if (scheme == null) { throw new InvalidOperationException($"No authenticationScheme was specified, and there was no DefaultSignOutScheme found."); } } var handler = await Handlers.GetHandlerAsync(context, scheme); if (handler == null) { throw await CreateMissingSignOutHandlerException(scheme); } if (!(handler is IAuthenticationSignOutHandler signOutHandler)) { throw await CreateMismatchedSignOutHandlerException(scheme, handler); } await signOutHandler.SignOutAsync(properties); }
/// <inheritdoc /> public bool Match( ProtoContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection) { if (routeKey == null) { throw new ArgumentNullException(nameof(routeKey)); } if (values == null) { throw new ArgumentNullException(nameof(values)); } if (values.TryGetValue(routeKey, out var obj) && obj != null) { var value = Convert.ToString(obj, CultureInfo.InvariantCulture); return(!FileNameRouteConstraint.IsFileName(value)); } // No value or null value. // // We want to return true here because the core use-case of the constraint is to *exclude* // things that look like file names. There's nothing here that looks like a file name, so // let it through. return(true); }
/// <inheritdoc /> public bool Match( ProtoContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection) { if (routeKey == null) { throw new ArgumentNullException(nameof(routeKey)); } if (values == null) { throw new ArgumentNullException(nameof(values)); } foreach (var constraint in Constraints) { if (!constraint.Match(httpContext, route, routeKey, values, routeDirection)) { return(false); } } return(true); }
public async Task Invoke(ProtoContext httpContext) { var feature = new EndpointSelectorContext(); // There's an inherent race condition between waiting for init and accessing the matcher // this is OK because once `_matcher` is initialized, it will not be set to null again. var matcher = await InitializeAsync(); await matcher.MatchAsync(httpContext, feature); if (feature.Endpoint != null) { // Set the endpoint feature only on success. This means we won't overwrite any // existing state for related features unless we did something. SetFeatures(httpContext, feature); Log.MatchSuccess(_logger, feature); } else { Log.MatchFailure(_logger); } await _next(httpContext); }
/// <summary> /// Extension method for setting the <see cref="Endpoint"/> for the current request. /// </summary> /// <param name="context">The <see cref="ProtoContext"/> context.</param> /// <param name="endpoint">The <see cref="Endpoint"/>.</param> public static void SetEndpoint(this ProtoContext context, Endpoint endpoint) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var feature = context.Features.Get <IEndpointFeature>(); if (endpoint != null) { if (feature == null) { feature = new EndpointFeature(); context.Features.Set(feature); } feature.Endpoint = endpoint; } else { if (feature == null) { // No endpoint to set and no feature on context. Do nothing return; } feature.Endpoint = null; } }
/// <summary> /// This examines the request to see if it matches a configured directory, and if there are any files with the /// configured default names in that directory. If so this will append the corresponding file name to the request /// path for a later middleware to handle. /// </summary> /// <param name="context"></param> /// <returns></returns> public Task Invoke(ProtoContext context) { if (context.GetEndpoint() == null && Helpers.IsGetOrHeadMethod(context.Request.Method) && Helpers.TryMatchPath(context, _matchUrl, forDirectory: true, subpath: out var subpath)) { var dirContents = _fileProvider.GetDirectoryContents(subpath.Value); if (dirContents.Exists) { // Check if any of our default files exist. for (var matchIndex = 0; matchIndex < _options.DefaultFileNames.Count; matchIndex++) { var defaultFile = _options.DefaultFileNames[matchIndex]; var file = _fileProvider.GetFileInfo(subpath.Value + defaultFile); // TryMatchPath will make sure subpath always ends with a "/" by adding it if needed. if (file.Exists) { // If the path matches a directory but does not end in a slash, redirect to add the slash. // This prevents relative links from breaking. if (!Helpers.PathEndsInSlash(context.Request.Path)) { context.Response.StatusCode = 301; context.Response.Headers[HeaderNames.Location] = context.Request.PathBase + context.Request.Path + "/" + context.Request.QueryString; return(Task.CompletedTask); } // Match found, re-write the url. A later middleware will actually serve the file. context.Request.Path = new PathString(context.Request.Path.Value + defaultFile); break; } } } } return(_next(context)); }
private static Task Success(ProtoContext context) { context.Response.StatusCode = 200; context.Items["test.PathBase"] = context.Request.PathBase.Value; context.Items["test.Path"] = context.Request.Path.Value; return(Task.FromResult <object>(null)); }
/// <summary> /// Generates a URI with an absolute path based on the provided values. /// </summary> /// <param name="generator">The <see cref="LinkGenerator"/>.</param> /// <param name="httpContext">The <see cref="ProtoContext"/> associated with the current request.</param> /// <param name="routeName">The route name. Used to resolve endpoints. Optional.</param> /// <param name="values">The route values. Used to resolve endpoints and expand parameters in the route template. Optional.</param> /// <param name="pathBase"> /// An optional URI path base. Prepended to the path in the resulting URI. If not provided, the value of <see cref="ProtoRequest.PathBase"/> will be used. /// </param> /// <param name="fragment">An optional URI fragment. Appended to the resulting URI.</param> /// <param name="options"> /// An optional <see cref="LinkOptions"/>. Settings on provided object override the settings with matching /// names from <c>RouteOptions</c>. /// </param> /// <returns>A URI with an absolute path, or <c>null</c>.</returns> public static string GetPathByRouteValues( this LinkGenerator generator, ProtoContext httpContext, string routeName, object values, PathString?pathBase = default, FragmentString fragment = default, LinkOptions options = default) { if (generator == null) { throw new ArgumentNullException(nameof(generator)); } if (httpContext == null) { throw new ArgumentNullException(nameof(httpContext)); } var address = CreateAddress(httpContext, routeName, values); return(generator.GetPathByAddress <RouteValuesAddress>( httpContext, address, address.ExplicitValues, address.AmbientValues, pathBase, fragment, options)); }
/// <summary> /// Authenticate for the specified authentication scheme. /// </summary> /// <param name="context">The <see cref="ProtoContext"/>.</param> /// <param name="scheme">The name of the authentication scheme.</param> /// <returns>The result.</returns> public virtual async Task <AuthenticateResult> AuthenticateAsync(ProtoContext context, string scheme) { if (scheme == null) { var defaultScheme = await Schemes.GetDefaultAuthenticateSchemeAsync(); scheme = defaultScheme?.Name; if (scheme == null) { throw new InvalidOperationException($"No authenticationScheme was specified, and there was no DefaultAuthenticateScheme found."); } } var handler = await Handlers.GetHandlerAsync(context, scheme); if (handler == null) { throw await CreateMissingHandlerException(scheme); } var result = await handler.AuthenticateAsync(); if (result != null && result.Succeeded) { var transformed = await Transform.TransformAsync(result.Principal); return(AuthenticateResult.Success(new AuthenticationTicket(transformed, result.Properties, result.Ticket.AuthenticationScheme))); } return(result); }
/// <inheritdoc /> public bool Match( ProtoContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection) { if (routeKey == null) { throw new ArgumentNullException(nameof(routeKey)); } if (values == null) { throw new ArgumentNullException(nameof(values)); } if (values.TryGetValue(routeKey, out var obj) && obj != null) { var value = Convert.ToString(obj, CultureInfo.InvariantCulture); return(IsFileName(value)); } // No value or null value. return(false); }
/// <inheritdoc /> public bool Match( ProtoContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection) { if (routeKey == null) { throw new ArgumentNullException(nameof(routeKey)); } if (values == null) { throw new ArgumentNullException(nameof(values)); } if (values.TryGetValue(routeKey, out var value) && value != null) { var valueString = Convert.ToString(value, CultureInfo.InvariantCulture); return(valueString.Length <= MaxLength); } return(false); }
public Task Invoke(ProtoContext context) { // Detect if an opaque upgrade is available. If so, add a websocket upgrade. var upgradeFeature = context.Features.Get <IProtoUpgradeFeature>(); if (upgradeFeature != null && context.Features.Get <IProtoGameSocketFeature>() == null) { var webSocketFeature = new UpgradeHandshake(context, upgradeFeature, _options); context.Features.Set <IProtoGameSocketFeature>(webSocketFeature); if (!_anyOriginAllowed) { // Check for Origin header var originHeader = context.Request.Headers[HeaderNames.Origin]; if (!StringValues.IsNullOrEmpty(originHeader) && webSocketFeature.IsGameSocketRequest) { // Check allowed origins to see if request is allowed if (!_allowedOrigins.Contains(originHeader.ToString(), StringComparer.Ordinal)) { _logger.LogDebug("Request origin {Origin} is not in the list of allowed origins.", originHeader); context.Response.StatusCode = StatusCodes.Status403Forbidden; return(Task.CompletedTask); } } } } return(_next(context)); }
/// <inheritdoc /> public bool Match( ProtoContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection) { if (routeKey == null) { throw new ArgumentNullException(nameof(routeKey)); } if (values == null) { throw new ArgumentNullException(nameof(values)); } if (values.TryGetValue(routeKey, out var value) && value != null) { var valueString = Convert.ToString(value, CultureInfo.InvariantCulture); if (long.TryParse(valueString, NumberStyles.Integer, CultureInfo.InvariantCulture, out var longValue)) { return(longValue >= Min && longValue <= Max); } } return(false); }
public bool Match( ProtoContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection) { if (routeKey == null) { throw new ArgumentNullException(nameof(routeKey)); } if (values == null) { throw new ArgumentNullException(nameof(values)); } if (values.TryGetValue(routeKey, out var value)) { return(InnerConstraint.Match(httpContext, route, routeKey, values, routeDirection)); } return(true); }
// Internal for testing internal bool TryProcessTemplate( ProtoContext httpContext, RouteEndpoint endpoint, RouteValueDictionary values, RouteValueDictionary ambientValues, LinkOptions options, out (PathString path, QueryString query) result)
/// <summary> /// Executes the middleware. /// </summary> /// <param name="context">The <see cref="ProtoContext"/> for the current request.</param> /// <returns>A task that represents the execution of this middleware.</returns> public async Task Invoke(ProtoContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } PathString matchedPath; PathString remainingPath; if (context.Request.Path.StartsWithSegments(_options.PathMatch, out matchedPath, out remainingPath)) { // Update the path var path = context.Request.Path; var pathBase = context.Request.PathBase; context.Request.PathBase = pathBase.Add(matchedPath); context.Request.Path = remainingPath; try { await _options.Branch(context); } finally { context.Request.PathBase = pathBase; context.Request.Path = path; } } else { await _next(context); } }
/// <summary> /// Executes the middleware. /// </summary> /// <param name="context">The <see cref="ProtoContext"/> for the current request.</param> /// <returns>A task that represents the execution of this middleware.</returns> public async Task Invoke(ProtoContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } PathString matchedPath; PathString remainingPath; if (context.Request.Path.StartsWithSegments(_pathBase, out matchedPath, out remainingPath)) { var originalPath = context.Request.Path; var originalPathBase = context.Request.PathBase; context.Request.Path = remainingPath; context.Request.PathBase = originalPathBase.Add(matchedPath); try { await _next(context); } finally { context.Request.Path = originalPath; context.Request.PathBase = originalPathBase; } } else { await _next(context); } }
/// <inheritdoc /> public bool Match( ProtoContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection) { if (routeKey == null) { throw new ArgumentNullException(nameof(routeKey)); } if (values == null) { throw new ArgumentNullException(nameof(values)); } if (values.TryGetValue(routeKey, out var value) && value != null) { if (value is decimal) { return(true); } var valueString = Convert.ToString(value, CultureInfo.InvariantCulture); return(decimal.TryParse(valueString, NumberStyles.Number, CultureInfo.InvariantCulture, out _)); } return(false); }
/// <summary> /// Generates a URI with an absolute path based on the provided values. /// </summary> /// <param name="generator">The <see cref="LinkGenerator"/>.</param> /// <param name="httpContext">The <see cref="ProtoContext"/> associated with the current request.</param> /// <param name="endpointName">The endpoint name. Used to resolve endpoints.</param> /// <param name="values">The route values. Used to expand parameters in the route template. Optional.</param> /// <param name="pathBase"> /// An optional URI path base. Prepended to the path in the resulting URI. If not provided, the value of <see cref="ProtoRequest.PathBase"/> will be used. /// </param> /// <param name="fragment">An optional URI fragment. Appended to the resulting URI.</param> /// <param name="options"> /// An optional <see cref="LinkOptions"/>. Settings on provided object override the settings with matching /// names from <c>RouteOptions</c>. /// </param> /// <returns>A URI with an absolute path, or <c>null</c>.</returns> public static string GetPathByName( this LinkGenerator generator, ProtoContext httpContext, string endpointName, object values, PathString?pathBase = default, FragmentString fragment = default, LinkOptions options = default) { if (generator == null) { throw new ArgumentNullException(nameof(generator)); } if (httpContext == null) { throw new ArgumentNullException(nameof(httpContext)); } if (endpointName == null) { throw new ArgumentNullException(nameof(endpointName)); } return(generator.GetPathByAddress <string>( httpContext, endpointName, new RouteValueDictionary(values), ambientValues: null, pathBase, fragment, options)); }
/// <inheritdoc /> public bool Match( ProtoContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection) { if (routeKey == null) { throw new ArgumentNullException(nameof(routeKey)); } if (values == null) { throw new ArgumentNullException(nameof(values)); } if (values.TryGetValue(routeKey, out var value) && value != null) { // In routing the empty string is equivalent to null, which is equivalent to an unset value. var valueString = Convert.ToString(value, CultureInfo.InvariantCulture); return(!string.IsNullOrEmpty(valueString)); } return(false); }
private void EnsureOptions(ProtoContext context) { if (_options == null) { _options = context.RequestServices.GetRequiredService <IOptions <RouteOptions> >().Value; } }
public override string GetPathByAddress <TAddress>( ProtoContext httpContext, TAddress address, RouteValueDictionary values, RouteValueDictionary ambientValues = default, PathString?pathBase = default, FragmentString fragment = default, LinkOptions options = null) { if (httpContext == null) { throw new ArgumentNullException(nameof(httpContext)); } var endpoints = GetEndpoints(address); if (endpoints.Count == 0) { return(null); } return(GetPathByEndpoints( httpContext, endpoints, values, ambientValues, pathBase ?? httpContext.Request.PathBase, fragment, options)); }
public async Task Invoke(ProtoContext context) { if (string.Equals(context.Request.Method, "POST", StringComparison.OrdinalIgnoreCase)) { if (_options.FormFieldName != null) { if (context.Request.HasFormContentType) { var form = await context.Request.ReadFormAsync(); var methodType = form[_options.FormFieldName]; if (!string.IsNullOrEmpty(methodType)) { context.Request.Method = methodType; } } } else { var xProtoMethodOverrideValue = context.Request.Headers[xProtoMethodOverride]; if (!string.IsNullOrEmpty(xProtoMethodOverrideValue)) { context.Request.Method = xProtoMethodOverrideValue; } } } await _next(context); }
public StaticFileContext(ProtoContext context, StaticFileOptions options, PathString matchUrl, ILogger logger, IFileProvider fileProvider, IContentTypeProvider contentTypeProvider) { _context = context; _options = options; _matchUrl = matchUrl; _request = context.Request; _response = context.Response; _logger = logger; _requestHeaders = _request.GetTypedHeaders(); _responseHeaders = _response.GetTypedHeaders(); _fileProvider = fileProvider; _contentTypeProvider = contentTypeProvider; _method = null; _isGet = false; _isHead = false; _subPath = PathString.Empty; _contentType = null; _fileInfo = null; _length = 0; _lastModified = new DateTimeOffset(); _etag = null; _ifMatchState = PreconditionState.Unspecified; _ifNoneMatchState = PreconditionState.Unspecified; _ifModifiedSinceState = PreconditionState.Unspecified; _ifUnmodifiedSinceState = PreconditionState.Unspecified; _range = null; _isRangeRequest = false; }
private string GetPathByEndpoints( ProtoContext httpContext, List <RouteEndpoint> endpoints, RouteValueDictionary values, RouteValueDictionary ambientValues, PathString pathBase, FragmentString fragment, LinkOptions options) { for (var i = 0; i < endpoints.Count; i++) { var endpoint = endpoints[i]; if (TryProcessTemplate( httpContext: httpContext, endpoint: endpoint, values: values, ambientValues: ambientValues, options: options, result: out var result)) { var uri = UriHelper.BuildRelative( pathBase, result.path, result.query, fragment); Log.LinkGenerationSucceeded(_logger, endpoints, uri); return(uri); } } Log.LinkGenerationFailed(_logger, endpoints); return(null); }
/// <summary> /// Creates a new instance of <see cref="VirtualPathContext"/>. /// </summary> /// <param name="httpContext">The <see cref="Proto.ProtoContext"/> associated with the current request.</param> /// <param name="ambientValues">The set of route values associated with the current request.</param> /// <param name="values">The set of new values provided for virtual path generation.</param> public VirtualPathContext( ProtoContext httpContext, RouteValueDictionary ambientValues, RouteValueDictionary values) : this(httpContext, ambientValues, values, null) { }
public override Task MatchAsync(ProtoContext httpContext, EndpointSelectorContext context) { if (httpContext == null) { throw new ArgumentNullException(nameof(httpContext)); } if (context == null) { throw new ArgumentNullException(nameof(context)); } var path = httpContext.Request.Path.Value; for (var i = 0; i < Matchers.Length; i++) { if (Matchers[i].TryMatch(path)) { context.Endpoint = Matchers[i].Endpoint; context.RouteValues = new RouteValueDictionary(); } } return(Task.CompletedTask); }
/// <summary> /// Generates a URI with an absolute path based on the provided values and <see cref="ProtoContext"/>. /// </summary> /// <typeparam name="TAddress">The address type.</typeparam> /// <param name="httpContext">The <see cref="ProtoContext"/> associated with the current request.</param> /// <param name="address">The address value. Used to resolve endpoints.</param> /// <param name="values">The route values. Used to expand parameters in the route template. Optional.</param> /// <param name="ambientValues">The values associated with the current request. Optional.</param> /// <param name="pathBase"> /// An optional URI path base. Prepended to the path in the resulting URI. If not provided, the value of <see cref="ProtoRequest.PathBase"/> will be used. /// </param> /// <param name="fragment">An optional URI fragment. Appended to the resulting URI.</param> /// <param name="options"> /// An optional <see cref="LinkOptions"/>. Settings on provided object override the settings with matching /// names from <c>RouteOptions</c>. /// </param> /// <returns>A URI with an absolute path, or <c>null</c>.</returns> public abstract string GetPathByAddress <TAddress>( ProtoContext httpContext, TAddress address, RouteValueDictionary values, RouteValueDictionary ambientValues = default, PathString?pathBase = default, FragmentString fragment = default, LinkOptions options = default);
public void ModelInjectionTest() { p = new ProtobufContext(); p.Add(m1); p.ExecutorInterface((List <member>)p.ModelsList.ElementAt(0)); ProtoContext c = p.Context; var s = c.members.ElementAt(0).FirstName; }
public bool Match(ProtoContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection) { return(true); }