C# 在 asp.net 中中继请求(转发请求)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/697177/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 13:52:23  来源:igfitidea点击:

Relaying a request in asp.net (Forwarding a request)

c#.nethttpcommunicationforwarding

提问by El Che

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).

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

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.

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

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.

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

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

Any code examples in preferable c# would be great!

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

采纳答案by El Che

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

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

回答by John Saunders

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

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

回答by dkarzon

possiblly something like:

可能是这样的:

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

Then call the get response

然后调用get响应

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

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

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

回答by Hafthor

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

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

GLOBAL.ASAX.VB

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

家庭控制器.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

回答by diachedelic

I have an extension method on HttpResponseBaseto copy an incoming request to an outgoing request.

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

Usage:

用法:

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

Source:

来源:

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