views:

1613

answers:

4

I have a web application that communicates between two different web applications (one receiver and one sender, the sender communicates with my application, and my application communicates with both).

A regular scenario is that the sender sends a HttpRequest to my application, and I receive it in an HttpHandler. This in turn sends the HttpContext to some businesslogic to do some plumbing.

After my business classes are finished storing data (some logging etc), I want to relay the same request with all the headers, form data etc to the receiver application. This must be sent from the class, and not the HttpHandler.

The question is really - how can I take a HttpContext object, and forward/relay the exact same request only modifying the URL from http://myserver.com/ to http://receiver.com.

Any code examples in preferable c# would be great!

+1  A: 

HttpContext includes the Request property, which in turn contains the Headers collection. It should be all the information you need.

John Saunders
HttpWebRequest relayingRequest = (HttpWebRequest)WebRequest.Create(relayUrl); relayingRequest.Headers.Add(context.Request.Headers);This does not work - I also need params, httpmethod etc. The request should be identical...
El Che
It's all there, in HttpContext.Request, almost "by definition". Consider that this is how a page or other handler knows what to do. There's a QueryString and Form property to Context.Request as well. Look up the properties, and you'll see.
John Saunders
Yeah I know they're all there, but remember that context.Request is not a System.Net.HttpWebRequest, but a System.Web.HttpRequest. I'm not sure it it's as easy as just looking up the props and getting them into the new request.
El Che
I _am_ sure. Why are you looking for something more complicated? Take a look, try it out, and see.
John Saunders
I'll check more tomorrow. It seems I need to read the inputstream from the original request and write it to the new one. Also I need to copy some of the properties like you say. Weird that there are no method to duplicate a request without this much hassle.
El Che
It's not something people have to do very often. This is something more often done at a lower level of the network infrastructure.
John Saunders
A: 

possiblly something like:

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("www.testing.test");
request.Headers = (WebHeaderCollection)Request.Headers;

Then call the get response

HttpWebResponse response  = (HttpWebResponse)request.GetResponse();

This will have the same HTTP headers as the original request.

d1k_is
Unable to cast object of type 'System.Web.HttpHeaderCollection' to type 'System.Net.WebHeaderCollection'.
El Che
+4  A: 

Actually, something like this worked well

        HttpRequest original = context.Request;
        HttpWebRequest newRequest = (HttpWebRequest)WebRequest.Create(newUrl;

        newRequest .ContentType = original.ContentType;
        newRequest .Method = original.HttpMethod;
        newRequest .UserAgent = original.UserAgent;

        byte[] originalStream = ReadToByteArray(original.InputStream, 1024);

        Stream reqStream = newRequest .GetRequestStream();
        reqStream.Write(originalStream, 0, originalStream.Length);
        reqStream.Close();


        newRequest .GetResponse();

edit: ReadToByteArray method just makes a byte array from the stream

El Che
+1  A: 

Here's some good relay code in VB.NET using MVC.

GLOBAL.ASAX.VB

Public Class MvcApplication
    Inherits System.Web.HttpApplication

    Shared Sub RegisterRoutes(ByVal routes As RouteCollection)
        routes.MapRoute("Default", "{*s}", New With {.controller = "Home", .action = "Index"})
    End Sub

    Sub Application_Start()
        RegisterRoutes(RouteTable.Routes)
    End Sub
End Class

HomeController.vb

Option Explicit On
Option Strict On

Imports System.Net

<HandleError()> _
Public Class HomeController
    Inherits System.Web.Mvc.Controller

    Function Index(ByVal s As String) As ActionResult
        Server.ScriptTimeout = 60 * 60
        If Request.QueryString.ToString <> "" Then s = s + "?" + Request.QueryString.ToString
        Dim req As HttpWebRequest = CType(WebRequest.Create("http://stackoverflow.com/" + s), HttpWebRequest)
        req.AllowAutoRedirect = False
        req.Method = Request.HttpMethod
        req.Accept = Request.Headers("Accept")
        req.Referer = Request.Headers("Referer")
        req.UserAgent = Request.UserAgent
        For Each h In Request.Headers.AllKeys
            If Not (New String() {"Connection", "Accept", "Host", "User-Agent", "Referer"}).Contains(h) Then
                req.Headers.Add(h, Request.Headers(h))
            End If
        Next
        If Request.HttpMethod <> "GET" Then
            Using st = req.GetRequestStream
                StreamCopy(Request.InputStream, st)
            End Using
        End If
        Dim resp As WebResponse = Nothing
        Try
            Try
                resp = req.GetResponse()
            Catch ex As WebException
                resp = ex.Response
            End Try

            If resp IsNot Nothing Then
                Response.StatusCode = CType(resp, HttpWebResponse).StatusCode
                For Each h In resp.Headers.AllKeys
                    If Not (New String() {"Content-Type"}).Contains(h) Then
                        Response.AddHeader(h, resp.Headers(h))
                    End If
                Next
                Response.ContentType = resp.ContentType

                Using st = resp.GetResponseStream
                    StreamCopy(st, Response.OutputStream)
                End Using
            End If
        Finally
            If resp IsNot Nothing Then resp.Close()
        End Try
        Return Nothing
    End Function
    Sub StreamCopy(ByVal input As IO.Stream, ByVal output As IO.Stream)
        Dim buf(0 To 16383) As Byte
        Using br = New IO.BinaryReader(input)
            Using bw = New IO.BinaryWriter(output)
                Do
                    Dim rb = br.Read(buf, 0, buf.Length)
                    If rb = 0 Then Exit Do
                    bw.Write(buf, 0, rb)
                Loop
            End Using
        End Using
    End Sub
End Class
Hafthor