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
Relaying a request in asp.net (Forwarding a request)
提问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 HttpResponseBase
to 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();
}
}