Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to forward HTTP response to client

I have a client (Xamarin) and two Web API servers, A and B. The client makes a request to A which uses the request parameters to make another request to B. How do I return the response that A receives from B to the client such that B's use of C is transparent to the client.

For example, if I make a request from A to B using HttpClient how do I forward the HttpResponseMessage to the client in a controller's action?

like image 229
Frank Ibem Avatar asked Jun 23 '17 20:06

Frank Ibem


People also ask

How are HTTP responses sent?

Send HTTP Response is a synchronous activity that sends a response to a previously received HTTP request. This activity is used in conjunction with the HTTP Receiver process starter activity and the Wait for HTTP Request activity. The default status line returned by this activity is " 200 OK ".

What is HTTP client in Web API?

What is HttpClient? HttpClient class provide a base class that is used to send HTTP request and receive HTTP response resources. HttpClient sends and receives data from Web API URL which is hosted on the local IIS server. HttpClient can process multiple requests concurrently. [Install HttpClient Library]

What are the components of HTTP response message?

HTTP Response broadly has 3 main components: Status Line. Headers. Body (Optional)


2 Answers

Look at aspnet/AspLabs repository for a good example of a transparent HTTP proxy. This proxy is a middleware handling client's requests to A and making its own requests to B.

To provide a complete answer, this is the part of its source code which is actually forwarding a HttpResponseMessage:

using (var responseMessage = await _httpClient.SendAsync(
    requestMessage, HttpCompletionOption.ResponseHeadersRead, context.RequestAborted))
{
    context.Response.StatusCode = (int)responseMessage.StatusCode;
    foreach (var header in responseMessage.Headers)
    {
        context.Response.Headers[header.Key] = header.Value.ToArray();
    }

    foreach (var header in responseMessage.Content.Headers)
    {
        context.Response.Headers[header.Key] = header.Value.ToArray();
    }

    // SendAsync removes chunking from the response. This removes the header so it doesn't expect a chunked response.
    context.Response.Headers.Remove("transfer-encoding");
    await responseMessage.Content.CopyToAsync(context.Response.Body);
}

There is full code copying a received HttpResponseMessage to the HttpContext.Response in the repository.

like image 114
Ilya Chumakov Avatar answered Sep 27 '22 20:09

Ilya Chumakov


I took IIya's answer and adapted it for asp.net MVC 5

 public async Task GetFile(CancellationToken cancellationToken)
    {
        var context = HttpContext;
        var _httpClient = StaticHttpClient.Instance;
        var requestMessage = new HttpRequestMessage()
        {
            RequestUri = new Uri("https://localhost:44305/api/files/123"),
        };
        using (var responseMessage = await _httpClient.SendAsync(
requestMessage, HttpCompletionOption.ResponseHeadersRead, cancellationToken))
        {
            Response.StatusCode = (int)responseMessage.StatusCode;
            foreach (var header in responseMessage.Headers)
            {
                Response.Headers[header.Key] = header.Value.First();
            }
            foreach (var header in responseMessage.Content.Headers)
            {
                Response.Headers[header.Key] = header.Value.First();
            }
            Response.Headers.Remove("transfer-encoding");
            //Response.BinaryWrite(await responseMessage.Content.ReadAsByteArrayAsync());
            await responseMessage.Content.CopyToAsync(Response.OutputStream);
            Response.Flush();
            Response.Close();
            context.ApplicationInstance.CompleteRequest();
        }
    }
like image 24
ToDevAndBeyond Avatar answered Sep 27 '22 22:09

ToDevAndBeyond