J'ai une application Web qui communique entre deux applications Web différentes (un destinataire et un expéditeur, l'expéditeur communique avec mon application et mon application communique avec les deux).
Un scénario normal est que l'expéditeur envoie une HttpRequest à mon application, et je la reçois dans un HttpHandler. Cela envoie à son tour le HttpContext à une logique commerciale pour faire de la plomberie.
Une fois que mes classes commerciales ont fini de stocker des données (certains journaux, etc.), je souhaite relayer la même demande avec tous les en-têtes, les données du formulaire, etc. à l'application réceptrice. Cela doit être envoyé depuis la classe et non depuis le HttpHandler.
La question est vraiment - comment puis-je prendre un objet HttpContext et transmettre/relayer exactement la même requête en modifiant uniquement l'URL de http://myserver.com/ à http: // receiver.com .
Tout exemple de code en c # préférable serait génial!
En fait, quelque chose comme ça a bien fonctionné
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: La méthode ReadToByteArray crée simplement un tableau d'octets à partir du flux
J'ai une méthode d'extension sur HttpResponseBase
pour copier une demande entrante dans une demande sortante.
Usage:
var externalRequest = (HttpWebRequest)WebRequest.Create("http://stackoverflow.com");
this.Request.CopyTo(externalRequest);
var externalResponse = (HttpWebResponse)externalRequest.GetResponse();
La 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();
}
}
Voici un bon code de relais dans VB.NET utilisant MVC.
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
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
HttpContext inclut la propriété Request, qui à son tour contient la collection Headers. Ce devrait être toutes les informations dont vous avez besoin.