How to pass through http call with HTTP Handler
Background:
We are using the Facebook API and receive back URLs for profile image thumbnails. Unfortunately the protocol is restricted to just HTTP and it doesn't support HTTPS. The page on our site that hosts the thumbnails is always delivered via HTTPS, and if we use HTTP for the thumbnails the user will receive security warnings from their browser.
Solution:
Build an HTTP Handler that "passes through" the image from the Facebook URL, but allow the handler to be called via HTTPS. Before I started coding I thought I could something like this:
Response.OutputStream = WebRequest.Create(FacebookUrlForThumbnail)
but I ended up having to save the image to an object in memory than write the image to the Response.OutputStream using the image save function.
Current Code:
Public Class FBImageHttpHandler
Implements System.Web.IHttpHandler
Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
Dim profilePath As String = context.Request.QueryString("profilepath")
Dim request As WebRequest = Nothing
Dim image As System.Drawing.Bitmap = Nothing
Dim errorMessage As String
Dim profileDomain As开发者_Go百科 String
Try
profileDomain = "http://[Facebook-Image-Domain].com/"
If profilePath.ToLower.EndsWith(".jpg") = True Then
request = WebRequest.Create(profileDomain & profilePath)
If (request.GetResponse().ContentLength > 0) Then
context.Response.ContentType = "image/jpeg"
image = New System.Drawing.Bitmap(request.GetResponse().GetResponseStream())
image.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg)
End If
End If
Catch ex As Exception
' Ignore Error
' Log Error - Removed Logging Code
Finally
If request IsNot Nothing Then
request = Nothing
End If
If image IsNot Nothing Then
image.Dispose()
image = Nothing
End If
End Try
End Sub
ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
Get
Return False
End Get
End Property
End Class
This seems inefficient but I can't find a way of using the HTTP Handler as I orginally intended. Is there way of accomplishing the goal without creating the image memory and just "passing through" the call?
There is no point in creating a Bitmap
just to save it to a different stream.
Instead, you should copy the GetResponseStream()
directly to context.Response.OutputStream
.
In .Net 4.0, you can do this using Stream.CopyTo
; in earlier versions, you'll need to copy it by hand.
For improved performance, disable buffering so that the client can start receiving content immediately.
Also, you should set your Content-Type
and caching headers from the headers received in the HttpWebResponse.
What you describe as "passing through" (and your example) is commonly refered to as a 'reverse proxy' solution, and I see no problem with it in principle.
You could look at existing solutions. There are a few code examples on the web (much like your own) http://www.codeproject.com/KB/IP/reverseproxy.aspx
A quick google search suggest that if you're just 'forwarding' the requests, it may be possible to do this at the IIS level, requiring you to write little to no code to (I have not tried this out myself) http://blogs.iis.net/carlosag/archive/2010/04/01/setting-up-a-reverse-proxy-using-iis-url-rewrite-and-arr.aspx
Also consider caching the images, if you are worried about performance.
I would guess that you could skip the image part, and just proxy the stream in binary format. That is likely as good as it will get, you'll always have to use some amount of memory as a buffer, read a chunk, write a chunk.
精彩评论