public override Task ExecuteAsync(VclHandler handler, RequestContext requestContext, VclContext vclContext) { var nextState = handler.VclSynth(vclContext); SwitchState(handler, nextState); return(Task.CompletedTask); }
public override Task ExecuteAsync(VclHandler handler, VclContext vclContext) { // Handle case where we exceed number of backend retries if (++handler._backendAttempt >= handler.MaxBackendRetries) { SwitchState(handler, VclBackendAction.Abandon); return(Task.CompletedTask); } // Setup BE request parameters vclContext.BackendRequest = new VclBackendRequest { Method = vclContext.Request.Method, Uri = vclContext.Request.Url }; foreach (var entry in vclContext.Request.Headers) { vclContext.BackendRequest.Headers.Add(entry.Key, entry.Value); } // TODO: Handle translation of certain request METHOD values // TODO: Handle filtering out certain HTTP headers // TODO: Handle adding/modifying certain HTTP headers // Enter fetch state SwitchState(handler, VclBackendAction.Fetch); return(Task.CompletedTask); }
public override Task ExecuteAsync(VclHandler handler, RequestContext requestContext, VclContext vclContext) { // Copy information from object into response vclContext.Response = new VclResponse { StatusCode = vclContext.Object.StatusCode, StatusDescription = vclContext.Object.StatusDescription, }; foreach (var header in vclContext.Object.Headers) { vclContext.Response.Headers.Add(header.Key, header.Value); } if (vclContext.Object.Body != null) { vclContext.Response.CopyBodyFrom(vclContext.Object.Body); } // Get result of calling extended code var nextState = handler.VclDeliver(vclContext); // Translate official supported action into internal code if (nextState == VclFrontendAction.Deliver) { nextState = VclFrontendAction.DeliverContent; } SwitchState(handler, nextState); return(Task.CompletedTask); }
public override Task ExecuteAsync(VclHandler handler, VclContext vclContext) { // Disconnect backend request/response objects (unless we are in pipe mode) vclContext.BackendRequest = null; vclContext.BackendResponse = null; return(Task.CompletedTask); }
public override Task ExecuteAsync(VclHandler handler, RequestContext requestContext, VclContext vclContext) { // Allow VCL to tweak receive parameters var nextState = handler.VclReceive(vclContext); SwitchState(handler, nextState); return(Task.CompletedTask); }
protected virtual void SwitchState(VclHandler handler, VclFrontendAction frontendAction) { if (!ValidTransitionStates.Contains(frontendAction)) { throw new InvalidOperationException($"Invalid attempt to transition front-end from {State} to {frontendAction}."); } handler.Logger?.LogDebug($"Client state transition from {State} to {frontendAction}"); handler._currentFrontendState = VclFrontendHandlerStateFactory.Get(frontendAction); }
public override Task ExecuteAsync(VclHandler handler, RequestContext requestContext, VclContext vclContext) { // Get result of calling extended code var nextState = handler.VclError(vclContext); // Translate official supported action into internal code if (nextState == VclFrontendAction.Deliver) { nextState = VclFrontendAction.DeliverContent; } SwitchState(handler, nextState); return(Task.CompletedTask); }
public override Task ExecuteAsync(VclHandler handler, RequestContext requestContext, VclContext vclContext) { // Attempt to do a lookup given the hash code var result = handler.Cache.Get <VclObject>($"VclObject:{vclContext.Request.Hash}"); if (result == null) { SwitchState(handler, VclFrontendAction.Miss); } else { vclContext.Object = result; SwitchState(handler, VclFrontendAction.Hit); } return(Task.CompletedTask); }
public override Task ExecuteAsync(VclHandler handler, RequestContext requestContext, VclContext vclContext) { // Setup real response requestContext.Response.StatusCode = vclContext.Response.StatusCode; requestContext.Response.ReasonPhrase = vclContext.Response.StatusDescription; foreach (var header in vclContext.Response.Headers) { requestContext.Response.Headers.Add(header.Key, new StringValues(header.Value)); } // Copy content body if we have one vclContext.Response.Body?.CopyTo(requestContext.Response.Body); // TODO: Setup cache TTL value (this uses kernel caching in HTTP.SYS driver) //requestContext.Response.CacheTtl = TimeSpan.FromSeconds(vclContext.Response.) SwitchState(handler, VclFrontendAction.Done); return(Task.CompletedTask); }
public override Task ExecuteAsync(VclHandler handler, VclContext vclContext) { var result = handler.VclBackendResponse(vclContext); if (result != VclBackendAction.Deliver) { SwitchState(handler, result); } // Create an object from the response vclContext.Object = new VclObject { StatusCode = vclContext.BackendResponse.StatusCode, StatusDescription = vclContext.BackendResponse.StatusDescription, DoEsiProcessing = vclContext.BackendResponse.DoEsiProcessing, Uncacheable = vclContext.BackendResponse.Uncacheable, Ttl = vclContext.BackendResponse.Ttl, }; foreach (var header in vclContext.BackendResponse.Headers) { vclContext.Object.Headers.Add(header.Key, header.Value); } if (vclContext.BackendResponse.Body != null) { vclContext.Object.CopyBodyFrom(vclContext.BackendResponse.Body); } // Handle caching the object if we are allowed to if (!vclContext.Object.Uncacheable) { handler.Cache.Set( $"VclObject:{vclContext.Request.Hash}", vclContext.Object, TimeSpan.FromSeconds(vclContext.Object.Ttl)); } SwitchState(handler, result); return(Task.CompletedTask); }
public override async Task ExecuteAsync(VclHandler handler, RequestContext requestContext, VclContext vclContext) { // Instruct backend request to execute var result = await handler .ProcessBackendFetchAsync(vclContext) .ConfigureAwait(false); // Detect error state and force request restart if (result == VclBackendAction.Abandon) { SwitchState(handler, VclFrontendAction.Restart); return; } // If the result is cachable then do it now if (!vclContext.BackendResponse.Uncacheable) { } SwitchState(handler, VclFrontendAction.Deliver); }
public override Task ExecuteAsync(VclHandler handler, RequestContext requestContext, VclContext vclContext) { // Update restart count and abort with hard error if we exceed max-retries vclContext.Request.Restarts++; if (vclContext.Request.Restarts >= handler.MaxFrontendRetries) { vclContext.Response = new VclResponse { StatusCode = 500, StatusDescription = "IMProxy request failed" }; SwitchState(handler, VclFrontendAction.Synth); return(Task.CompletedTask); } vclContext.Local.Ip = requestContext.Request.LocalIpAddress; vclContext.Remote.Ip = requestContext.Request.RemoteIpAddress; vclContext.Client.Ip = requestContext.Request.RemoteIpAddress; vclContext.Client.Port = requestContext.Request.RemotePort; vclContext.Server.HostName = Environment.MachineName; vclContext.Server.Identity = "foobar"; vclContext.Server.Ip = requestContext.Request.LocalIpAddress; vclContext.Server.Port = requestContext.Request.LocalPort; vclContext.Request.Method = requestContext.Request.Method; vclContext.Request.Url = requestContext.Request.RawUrl; vclContext.Request.CanGzip = requestContext.Request.Headers["Accept-Encoding"].Equals("gzip") || requestContext.Request.Headers["Accept-Encoding"].Equals("x-gzip"); vclContext.Request.ProtocolVersion = requestContext.Request.ProtocolVersion.ToString(2); foreach (var header in requestContext.Request.Headers) { vclContext.Request.Headers.Add(header.Key, header.Value.ToString()); } SwitchState(handler, VclFrontendAction.Receive); return(Task.CompletedTask); }
public override Task ExecuteAsync(VclHandler handler, VclContext vclContext) { return(Task.CompletedTask); }
public abstract Task ExecuteAsync(VclHandler handler, RequestContext requestContext, VclContext vclContext);
public override async Task ExecuteAsync(VclHandler handler, VclContext vclContext) { var result = handler.VclBackendFetch(vclContext); if (result != VclBackendAction.Fetch) { SwitchState(handler, result); return; } // Issue request to backend var httpClient = new HttpClient(); var backendRequest = new HttpRequestMessage { Method = new HttpMethod(vclContext.BackendRequest.Method), RequestUri = new Uri(vclContext.BackendRequest.Uri) }; foreach (var entry in vclContext.BackendRequest.Headers) { backendRequest.Headers.Add(entry.Key, entry.Value); } // Get raw response from backend var backendResponse = await httpClient .SendAsync(backendRequest) .ConfigureAwait(false); // Setup VCL backend response vclContext.BackendResponse = new VclBackendResponse { StatusCode = (int)backendResponse.StatusCode, StatusDescription = backendResponse.ReasonPhrase }; foreach (var item in backendResponse.Headers) { vclContext.BackendResponse.Headers.Add(item.Key, string.Join(",", item.Value)); } // Detect backend error if (!backendResponse.IsSuccessStatusCode) { SwitchState(handler, VclBackendAction.Error); return; } // If we have a content body in the response then copy it now // TODO: May need to steal VirtualStream code that uses MemoryStream until content // exceeds certain size where it switches to a temporary file if (backendResponse.Content != null) { using (var contentBodyStream = await backendResponse.Content.ReadAsStreamAsync()) { vclContext.BackendResponse.CopyBodyFrom(contentBodyStream); } } // Setup response TTL value if (backendResponse.Headers.CacheControl.SharedMaxAge != null) { vclContext.BackendResponse.Ttl = (int)backendResponse.Headers.CacheControl.SharedMaxAge.Value.TotalSeconds; } else if (backendResponse.Headers.CacheControl.MaxAge != null) { vclContext.BackendResponse.Ttl = (int)backendResponse.Headers.CacheControl.MaxAge.Value.TotalSeconds; } else if (backendResponse.Headers.TryGetValues("Expires", out var expiryValues)) { var expiryDate = DateTime.Parse(expiryValues.First()); vclContext.BackendResponse.Ttl = (int)(expiryDate - DateTime.UtcNow).TotalSeconds; } else { vclContext.BackendResponse.Ttl = handler.DefaultTtl; } // Switch state SwitchState(handler, VclBackendAction.Response); }
public abstract Task ExecuteAsync(VclHandler handler, VclContext vclContext);