40

我有一个 Web 应用程序在两个不同的 Web 应用程序之间进行通信(一个接收者和一个发送者,发送者与我的应用程序通信,我的应用程序与两者通信)。

一个常规的场景是发送者向我的应用程序发送一个 HttpRequest,而我在一个 HttpHandler 中接收它。这反过来将 HttpContext 发送到一些业务逻辑以进行一些管道操作。

在我的业务类完成存储数据(一些日志记录等)之后,我想将包含所有标头、表单数据等的相同请求中继到接收器应用程序。这必须从类发送,而不是 HttpHandler。

问题是真的 - 我怎样才能获取一个 HttpContext 对象,并转发/中继完全相同的请求,只需将 URL 从http://myserver.com/修改为http://receiver.com

最好的 c# 中的任何代码示例都会很棒!

4

5 回答 5

42

我有一个扩展方法HttpResponseBase可以将传入请求复制到传出请求。

用法:

    var externalRequest = (HttpWebRequest)WebRequest.Create("http://stackoverflow.com");
    this.Request.CopyTo(externalRequest);
    var externalResponse = (HttpWebResponse)externalRequest.GetResponse();

来源:

/// <summary>
/// Copies all headers and content (except the URL) from an incoming to an outgoing
/// request.
/// </summary>
/// <param name="source">The request to copy from</param>
/// <param name="destination">The request to copy to</param>
public static void CopyTo(this HttpRequestBase source, HttpWebRequest destination)
{
    destination.Method = source.HttpMethod;

    // Copy unrestricted headers (including cookies, if any)
    foreach (var headerKey in source.Headers.AllKeys)
    {
        switch (headerKey)
        {
            case "Connection":
            case "Content-Length":
            case "Date":
            case "Expect":
            case "Host":
            case "If-Modified-Since":
            case "Range":
            case "Transfer-Encoding":
            case "Proxy-Connection":
                // Let IIS handle these
                break;

            case "Accept":
            case "Content-Type":
            case "Referer":
            case "User-Agent":
                // Restricted - copied below
                break;

            default:
                destination.Headers[headerKey] = source.Headers[headerKey];
                break;
        }
    }

    // Copy restricted headers
    if (source.AcceptTypes.Any())
    {
        destination.Accept = string.Join(",", source.AcceptTypes);
    }
    destination.ContentType = source.ContentType;
    destination.Referer = source.UrlReferrer.AbsoluteUri;
    destination.UserAgent = source.UserAgent;

    // Copy content (if content body is allowed)
    if (source.HttpMethod != "GET"
        && source.HttpMethod != "HEAD"
        && source.ContentLength > 0)
    {
        var destinationStream = destination.GetRequestStream();
        source.InputStream.CopyTo(destinationStream);
        destinationStream.Close();
    }
}
于 2012-09-20T04:31:08.743 回答
28

实际上,这样的事情效果很好

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();

编辑:ReadToByteArray 方法只是从流中创建一个字节数组

于 2009-03-31T06:39:47.587 回答
4

这是使用 MVC 在 VB.NET 中的一些很好的中继代码。

全球.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

家庭控制器.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
于 2009-08-17T22:06:29.533 回答
1

HttpContext 包括 Request 属性,该属性又包含 Headers 集合。它应该是您需要的所有信息。

于 2009-03-30T13:43:53.473 回答
-1

可能是这样的:

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

然后调用get响应

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

这将具有与原始请求相同的 HTTP 标头。

于 2009-03-31T03:50:52.873 回答