Ich glaube, ich bin in ein Kaninchenloch gefallen und vermute, dass es eine viel einfachere Lösung gibt als die, die ich versuche. Grundsätzlich möchte ich in meiner .net Core MVC App eine Streaming-Videodatei von einer externen API abrufen.Wie wird eine Antwort von einem Remote-Server in .net-Core weitergeleitet?
Also das bedeutet, für alle Anfragen an meine Aktion möchte ich eine externe API-Funktion über die Leitung aufrufen. Ich muss der Anfrage einen Header hinzufügen, aber alle anderen Header, die angefordert wurden, weiterleiten, und dann, wenn ich wieder von der API gehört habe, werde ich die Antwort in ihrer Gesamtheit an den Verbraucher weiterleiten. Es ist im Grunde wie eine Weiterleitung ohne den StatusCode und fügt der umgeleiteten Quelle eine Kopfzeile hinzu.
Die Art, wie ich es mache, ist wie folgt. In meinem Controller, nenne ich eine ForwardedResponseResult:
var client = await this.FileAssetsApiContext.GetHttpClient();
//Copy the Headers
foreach (var header in Request.Headers)
{
header.Value.ToList().ForEach(p => {
if (client.DefaultRequestHeaders.Contains(header.Key))
{
client.DefaultRequestHeaders.Remove(header.Key);
client.DefaultRequestHeaders.Add(header.Key, p);
}
else
{
client.DefaultRequestHeaders.Add(header.Key, p);
}});
}
var fullPath = Url.Combine(VideosRootPath, path);
var response = await client.GetAsync(url);
return new ForwardedResponseResult(response);
Und dann habe ich eine Weiterleitungsklasse:
public class ForwardedResponseResult : ActionResult
{
public override void ExecuteResult(ActionContext context)
{
throw new NotImplementedException();
}
public ForwardedResponseResult(HttpResponseMessage httpResponseMessage)
{
this.HttpResponseMessage = httpResponseMessage;
}
public override async Task ExecuteResultAsync(ActionContext context)
{
var responseToCopy = this.HttpResponseMessage;
var responseToCopyHeaders = responseToCopy.Headers.ToArray();
var responseToCopyContentHeaders = responseToCopy.Content.Headers.ToArray();
var streamToCopy = await responseToCopy.Content.ReadAsStreamAsync();
var responseToReturnTo = context.HttpContext.Response;
var streamToCopyTo = responseToReturnTo.Body;
var headers = responseToCopy.Headers.ToArray();
var contentHeaders = responseToCopy.Content.Headers.ToArray();
var headersTo = responseToReturnTo.Headers.ToArray();
foreach (var header in responseToCopy.Headers)
{
header.Value.ToList().ForEach(p => responseToReturnTo.Headers.Add(header.Key, p));
}
responseToReturnTo.StatusCode = (int) responseToCopy.StatusCode;
foreach (var header in responseToCopy.Content.Headers)
{
header.Value.ToList().ForEach(p => responseToReturnTo.Headers.Add(header.Key, p));
}
//Copy to the output buffer
var remainingBytes = streamToCopy.Length;
while (remainingBytes > 0)
{
//var bufferSize = 1024;
var bufferSize = 8096;
var buffLen = remainingBytes > bufferSize ? bufferSize : remainingBytes;
var buffer = new byte[buffLen];
streamToCopy.Read(buffer, 0, (int)buffLen);
streamToCopyTo.Write(buffer, 0, (int)buffLen);
remainingBytes -= buffLen;
}
//streamToCopy.CopyTo(streamToCopyTo);
//await streamToCopyTo.FlushAsync();
}
public HttpResponseMessage HttpResponseMessage { get; }
}
Dies scheint massiv übertrieben, und die Leistung für Bereichsanforderungen ist schrecklich. Fehle ich etwas Offensichtliches? Gibt es eine Möglichkeit, dies einfacher zu tun?
Danke Stephen. Diese Änderung funktioniert viel besser. Ich bin überrascht, dass es keine direkte Methode dafür gibt, aber zumindest funktioniert es –