HttpWebRequest.Address vs HttpWebResponse.ResponseUri - c#

Whats the difference between these two properties?
To put into context, I am determining if a redirect occurs if our ResponseUri != RequestUri.
While a redirect occurs regardless the url http://adage.com/adages/article?article_id=140560 will provide a different ResponseUri (http://adage.com/adages/post.php) than the Address (http://adage.com/adages/post?article_id=140560).
It appears the ResponseUri takes the Content-Location header and uses it while the Address maintains the correct location.
Would it be correct to compare the RequestUri to the HttpWebRequest.Address to check for redirects?

Yes, comparing request.RequestUri and request.Address is the way to go. At least in Mono response.ResponseUri is the same as request.Address.

I know this is an old question, but I found it while researching this topic and noticed it wasn't actually answered correctly.
While HttpWebRequest.Address and HttpWebResponse.ResponseUri should always be the same, here is the difference:
HttpWebResponse.Address will return the Uri of the page actually responding
HttpWebResponse.ResponseUri will return the value of the Content-Location header (if present). While the documentation doesn't explicitly state what happens if the Content-Location header is not present, it is assumed it will use the same value as Address.
Remember HTTP headers can be forged, so Microsoft recommends using Address instead of ResponseUri for security reasons.
http://msdn.microsoft.com/en-us/library/system.net.httpwebresponse.responseuri.aspx

Have you thought about setting request.AllowAutoRedirect=false and then reissuing the request on a redirect?
The Uri comparison should also work fine, although I am not sure of all the edge cases

Related

.NET 4.6 HttpResponse.PushPromise methods to manage http/2 PUSH_PROMISE header

I am a bit confused about PUSH PROMISE http/2 header handling in .NET4.6.
When I look HttpResponse.PushPromise there are two overloads:
One that accepts path to resource public void PushPromise(string path) - am assuming resource is then read and binary sent across to client.
Second public void PushPromise(string path, string method, NameValueCollection headers) that accepts sting method and NameValueCollection headers which I am failing to understand.
Why would I want to pass method (assuming HttpMethod like GET, POST, etc) and collection of headers inside PUSH PROMISE header?
From reading the HTTP/2 spec (Section 8.2), here is what I gather:
Passing the method
PUSH_PROMISE frames are required to be cacheable and safe. You have the option of using GET and HEAD, as those are the only two http methods that are defined as both safe and cacheable.
Passing headers
Since PUSH_PROMISE frames are required to be cacheable, this could be used to add specific Cache-Control directives to the promise. Section 8.2.2 of the spec states that a client has the option to download the promised stream and can refuse it, which I imagine a client would do if it found that it had an up-to-date version of the resource in its cache.
Controlling caching is the most obvious reason I can see for why you might pass headers, but there may be other reasons as well. If you're writing a custom client, you may use certain X-Headers to provide other hints (that aren't related to caching) to the client so it can decide whether or not it wants to accept the promised stream.
You'll want to pass headers for anything that will cause your response to vary (i.e. anything in your Vary response header). The biggest one I've found is compression.
Read those headers from the original client request and include them with your push promise, e.g.:
var headers = new NameValueCollection { { "accept-encoding", this.Request.Headers["accept-encoding"] } };
this.Response.PushPromise("~/Scripts/jquery.js", "GET", headers);`

HttpWebRequest vs Webclient (Special scenario)

I know this question has been answered before in this thread, but I couldn't seem to find the details.
In my scenario, I am building a console application which will keep an eye on html page source for any changes. If any update/change occurs, I will perform further operations. Moreover, I'll also perform a request after every 1 second, or as soon as the previous request finishes.
I can't seem to figure out should I use HttpWebRequest or WebClient for downloading the html page source and perform comparison? What do you think would be an ideal solution in my case? Speed and reliability both :)
I'd go with HttpWebRequst because it's not as abstracted and lets you fiddle with HTTP params quite a bit. It gives you the option to not download the entire page if the server returns "file not changed", for example.
If you add some parameters to your request like IfModifiedSince (it might be HEAD or GET request) the server may return the response code 304 - NOT MODIFIED. Refer to description of caching in HTTP for further explanation.
The point is to make sure that you only download the full page when it's actually modified since the last time you fetched it. Most of the time it won't be changed (I suppose, can't know for sure without knowing your domain), so you only need to get a lightweight response from server which simply states "nothing changed here".
Update: code sample demonstrating the use of IfModifiedSince property:
bool IsResourceModified(string url, DateTime dateTime) {
try {
var request = (HttpWebRequest)HttpWebRequest.Create(new Uri(url));
request.IfModifiedSince = dateTime;
request.Method = "HEAD";
var response = (HttpWebResponse)request.GetResponse();
return true;
}
catch(WebException ex) {
if(ex.Status != WebExceptionStatus.ProtocolError)
throw;
var response = (HttpWebResponse)ex.Response;
if(response.StatusCode != HttpStatusCode.NotModified)
throw;
return false;
}
}
This method should return true if the page was modifed since the dateTime date and false if it wasn't. GetResponse method will throw a WebException if you make a HEAD-request and the server returns 304 - NOT MODIFIED (which is kinda unfortunate). We have to make sure that it's not some other web connection problem, that's why I check the status of web exception and the HTTP status in response. If anything else caused an exception we just throw it further.
Console.WriteLine(IsResourceModified("http://example.com", new DateTime(2009)));
Console.WriteLine(IsResourceModified("http://example.com", DateTime.Now));
This sample code produces the output:
True
False
Note: make sure to read Jim Mischel's addition to this answer as he gives few good advices on this technique.
I was going to leave this as a comment to #Dyppl's response, but it became too long.
Dyppl's response is generally good advice, and the way that I would approach this problem. However, there are a few things you should keep in mind.
First, there's no reason to do a HEAD request, followed by a GET if the page has been modified. You can do a GET with the IfModifiedSince header set, and the server will either return the entire page or a 304. Doing the HEAD first, followed by the 'GET`, ends up making two requests to the server, which defeats much of the purpose of the conditional request.
Second, you should set the IfModifiedSince property to the LastModified value returned by the previous response (i.e. HttpWebResponse.LastModified) because the server's time might not be synchronized with your computer. Also, I've found that a large percentage of sites, particularly those with generated content (like WordPress blogs) lie. They always return the current date/time in the LastModified header. As a result, there is no benefit to doing the If-Modified-Since check on those sites.
If you know that the site lies and always returns the current date/time, you can keep track of the ContentLength header that's returned from the page when you download it. Then, when you want to check to see if the page has changed, do a HEAD request and check the returned ContentLength header with the saved value. If they match, then it's unlikely that the page has changed. If they don't match, then do a GET request to update your copy of the page and keep the new ContentLength.
This technique does have the disadvantage of requiring two requests if the page has changed. It's also not 100% reliable on all servers. Some will return a different ContentLength for the HEAD request, and some don't return a valid ContentLength at all. That said, I've found it to be effective for a large number of sites.

Getting the HTTP Referrer in ASP.NET

I'm looking for a quick, easy and reliable way of getting the browser's HTTP Referrer in ASP.Net (C#). I know the HTTP Referrer itself is unreliable, but I do want a reliable way of getting the referrer if it is present.
You could use the UrlReferrer property of the current request:
Request.UrlReferrer
This will read the Referer HTTP header from the request which may or may not be supplied by the client (user agent).
Request.Headers["Referer"]
Explanation
The Request.UrlReferrer property will throw a System.UriFormatException if the referer HTTP header is malformed (which can happen since it is not usually under your control).
Therefore, the Request.UrlReferrer property is not 100% reliable - it may contain data that cannot be parsed into a Uri class. To ensure the value is always readable, use Request.Headers["Referer"] instead.
As for using Request.ServerVariables as others here have suggested, per MSDN:
Request.ServerVariables Collection
The ServerVariables collection retrieves the values of predetermined environment variables and request header information.
Request.Headers Property
Gets a collection of HTTP headers.
Request.Headers is a better choice than Request.ServerVariables, since Request.ServerVariables contains all of the environment variables as well as the headers, where Request.Headers is a much shorter list that only contains the headers.
So the most reliable solution is to use the Request.Headers collection to read the value directly. Do heed Microsoft's warnings about HTML encoding the value if you are going to display it on a form, though.
Use the Request.UrlReferrer property.
Underneath the scenes it is just checking the ServerVariables("HTTP_REFERER") property.
Like this: HttpRequest.UrlReferrer Property
Uri myReferrer = Request.UrlReferrer;
string actual = myReferrer.ToString();
I'm using .Net Core 2 mvc,
this one work for me ( to get the previews page) :
HttpContext.Request.Headers["Referer"];
Since Google takes you to this post when searching for C# Web API Referrer here's the deal: Web API uses a different type of Request from normal MVC Request called HttpRequestMessage which does not include UrlReferrer. Since a normal Web API request does not include this information, if you really need it, you must have your clients go out of their way to include it. Although you could make this be part of your API Object, a better way is to use Headers.
First, you can extend HttpRequestMessage to provide a UrlReferrer() method:
public static string UrlReferrer(this HttpRequestMessage request)
{
return request.Headers.Referrer == null ? "unknown" : request.Headers.Referrer.AbsoluteUri;
}
Then your clients need to set the Referrer Header to their API Request:
// Microsoft.AspNet.WebApi.Client
client.DefaultRequestHeaders.Referrer = new Uri(url);
And now the Web API Request includes the referrer data which you can access like this from your Web API:
Request.UrlReferrer();
string referrer = HttpContext.Current.Request.UrlReferrer.ToString();
Sometime you must to give all the link like this
System.Web.HttpContext.Current.Request.UrlReferrer.ToString();
(in option when "Current" not founded)
Using .NET Core or .NET 5 I would recommend this:
httpContext.Request.Headers.TryGetValue("Referer", out var refererHeader)
Belonging to other reply, I have added condition clause for getting null.
string ComingUrl = "";
if (Request.UrlReferrer != null)
{
ComingUrl = System.Web.HttpContext.Current.Request.UrlReferrer.ToString();
}
else
{
ComingUrl = "Direct"; // Your code
}

How to set WebClient Content-Type Header?

To conect to a third party service I need to make a Https Post. One of the requisites set is to sent a custom content type.
I'm using WebClient, but I can't find how to set it. I've tried making a new class and overriding the CreateRequest Method, but that make request crash.
Is there any way to do that without having to rewrite CopyHeadersTo method?
EDIT CopyHeaderTo is a method I've seen using .NET Reflector. It's invoked from GetWebRequest and sets all Request Headers, including Content-Type, from private properties.
You could try adding to the Headers collection.
myWebClient.Headers.Add("Content-Type","application/xxx");
webclient.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
Well, I just missed Request.ContentType property. If GetWebRequest method is overridden, setting ContentType to whatever value desired does it.
Still, connection to third party is not working. Go figure.
I encounter this too. And found that you must use Client Http, otherwise Browser Http will block change of Content-Type for security reason. This MSDN link explain that.
WebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp);
WebRequest.RegisterPrefix("https://", WebRequestCreator.ClientHttp);
client.Headers["Content-Type"] = "application/json";

Determine Final Destination of a Shortened URL

I'm trying to find the best way (in code) to determine the final destination of a shortened URL. For instance http://tinyurl.com redirects to an eBay auction. I'm trying to get the URL for the eBay auction. I'm trying to do this from within .NET so I can compare multiple URLs to ensure that there is no duplicates.
TIA
While I spent a minute writing the code to ensure that it worked the answer was already delivered, but I post the code anyway:
private static string GetRealUrl(string url)
{
WebRequest request = WebRequest.Create(url);
request.Method = WebRequestMethods.Http.Head;
WebResponse response = request.GetResponse();
return response.ResponseUri.ToString();
}
This will work as long as the short url service does a regular redirect.
You should issue a HEAD request to the url using a HttpWebRequest instance. In the returned HttpWebResponse, check the ResponseUri.
Just make sure the AllowAutoRedirect is set to true on the HttpWebRequest instance (it is true by default).
One way would be to read the URL and get the result code from it. If it's a 301 (permanent redirect) then follow where it's taking you. Continue to do this until you reach a 200 (OK). When using tinyurl it could happen that you will go through several 301 until you reach a 200.
Assuming you don't want to actually follow the link, for TinyURL you can append /info to the end of the url:
http://tinyurl.com/unicycles/info
and it gives you a page showing where that tinyurl links to, which I assume would be easy to parse using xpath or similar.
Most other URL shortening services have similar features, but they all work differently.

Categories