How to retrieve an URL inside a .NET http handler? - asp.net

I'm hosting images on a server, within an ASP.NET application.
I wrote a custom http handler that resizes the image and also increment "image_view_count" in a DB.
Now, I would like to also do some logging to know where the image is used. For example:
Image abc.jpg is on my server at www.myserver.com/stuff/abc.jpg
Somebody uses it by linking it in a forum post located at www.forum.com/thread.php?id=1234
I would like to retrieve the www.forum.com/thread.php?id=1234 URL in my http handler. When I use Request.Url.ToString(), in the previous example, I receive www.myserver.com/stuff/abc.jpg.
How should I do this ? Is there an equivalent in managed code to location.href ?

I believe you're looking for the Referer header.
public void ProcessRequest(HttpContext context)
{
IServiceProvider provider = (IServiceProvider)context;
HttpWorkerRequest worker = (HttpWorkerRequest)provider.GetService(typeof(HttpWorkerRequest));
String referer = worker.GetKnownRequestHeader(HttpWorkerRequest.HeaderReferer);
}

Request.Url is the url for the current request - ie, the request to load your image.
You may be able to get what you want by checking the Referer, however this is not always reliable.

You can check referer to see where the image is used:
http://en.wikipedia.org/wiki/HTTP_referrer
C#
string referer = Request.UrlReferrer.ToString();
UrlReferrer can be null if the browser is not sending referer in request header.

Related

Error detail not sent by server AspnetBoilerPlate

enter image description here
In Aspnet Boilerplate, Swagger-UI is running at port no 5000 and the angular require port no 21021. so am facing problems.
I tried Changing port number in angular code but then it was displaying
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.".
So please help me to solve my issue
To solve the Response to preflight request doesn't pass access control check error you need to sent back the Access-Control-Allow-Origin header.
As I do not know which version you are running (either MVC or the Core version), I assume you are using the MVC version.
Override the Application_OnBeginRequest method in global.asax.cs:
Example:
protected void Application_OnBeginRequest(object sender, EventArgs e)
{
// Reading out response.
var response = HttpContext.Current.Response;
// Setting CORS headers.
response.AppendHeader("Access-Control-Allow-Origin", "*");
}
Keep in mind when sending back an * as Access-Control-Allow-Origin value. Every host can talk to your API. If you do not want the entire world to access your API simply specify a FQDN as value.

Spring #RestController not setting cookies with response

I have the following rest endpoint that I would like to send a cookie along with my ResponseEntity. However after succesfully sending the response, the cookie is nowhere to be found.
#RequestMapping(value = "myPath", method = RequestMethod.POST)
public ResponseEntity<?> createToken(HttpServletResponse response)
final String token = "a1b2c3d4e";
Cookie cookie = new Cookie("token", token);
response.addCookie(cookie);
// Return the token
return ResponseEntity.ok(new MyCustomResponse(token));
}
MyCustomResponse
class MyCustomResponse {
private final String token;
public MyCustomResponse(String token) {
this.token = token;
}
}
I have also tried creating the ResponseEntity manually and setting the cookie in the headers with the "Set-Cookie" header but same thing, no cookie.
edit: I have confirmed that the Set-Cookie header is in fact present in the response, however it is not actually being stored in the browser. I am using a static web-app running in WebStorm to access my rest endpoint running on a different port. This web app is just using JQuery's $ajax method to call the REST endpoint, nothing fancy. When I run the web app in WebStorm I am able to see the cookie it creates in my browser, so that confirms my browser is allowing cookie storage.
I figured it out. My web application I am using to access my rest api is running on a different local port than my rest api. This causes the AJAX request to fail CORS requirements, thus the cookie doesnt actually get set.
I found the solution here What can cause a cookie not to be set on the client?
edit: I should add that it was adding the xhrFields snippet to JQuery's $ajax method that fixed it for me, the other parts weren't necessary.
(posting the answer below in case it gets deleted)
I think I found the solution. Since during development, my server is at "localhost:30002" and my web app at "localhost:8003", they are considered different hosts regarding CORS. Therefore, all my requests to the server are covered by CORS security rules, especially Requests with credentials. "Credentials" include cookies as noted on that link, so the returned cookie was not accepted because I did not pass
xhrFields: {
withCredentials: true
}
to jQuery's $.ajax function. I also have to pass that option to subsequent CORS requests in order to send the cookie.
I added the header Access-Control-Allow-Credentials: true on the server side and changed the Access-Control-Allow-Origin header from wildcard to http://localhost:8003 (port number is significant!). That solution now works for me and the cookie gets stored.

Servlet retrieves XML from URL and returns XML response

On a project I am doing I have been forced into developing a server side part due to restrictions of the "Same Origin Policy" in browsers, that prevents the AJAX making requests to anything outside of the domain of the page.
Therefore I am building a Java Servlet that will act as the handler for the page and will retrieve XML's from external sites and return it back to the client page using AJAX
I will use GET parameters to instruct the servlet what URL to fetch XMLs from.
I am a beginner with Java, I could easily do this in PHP but sadly there are no environments availale to host PHP or Apache
Skeleton Code
public void doGet(HttpServletRequest agentRequest, HttpServletResponse agentResponse)
throws ServletException, IOException
{
agentResponse.setContentType("text/xml");
//determine if agentRequest is for templateList or templateDetails
//build URL for specific request
//if no parameters sent or invalid send error response
//fetch XML from URL
//output response XML to client
}
I do not want a full code solution, just references and ideas to get me in the right direction!
e.g. what java features to use for this, etc.
Thanks
As requested, some high-level ideas to get you started:
Firstly, get the external URL from the request parameter:
//equivalent of PHP $_GET["url"]
String externalUrl = agentRequest.getParameter("url");
Then you need to retrieve the response from the external URL. There are already various Q'a and A's on that topic, including How do I do a HTTP GET in Java?
Finally, you need to write the response into your response using the OutputStream supplied:
agentResponse.getOutputStream();

Async Web Service calls to IIS7 with Dynamic Compression don't work

We have some ASP.NET Web Services that fail under this perfect storm of conditions:
IIS7
Dynamic Compression is turned on
Web Service call is Asynchronous
If it is IIS 6, or we turn Dynamic Compression off or call the web service synchronously, it works fine.
It fails in the call to SoapHttpClientProtocol.EndInvoke(IAsyncResult asyncResult) with an 'Unexpected end of file' error.
Using Fiddler, I see that the response from IIS 6 has a transfer-encoding of 'chunked' and no content-length. The response from IIS 7 is NOT chunked and has a content-length. The end of file error occurs 1 character past the content length.
If I intercept the message in Fiddler and change it to chunked, there is no error. The answer could be to change it to chunked in IIS 7 (which I've tried to do and failed), but I don't feel like I should have to do this: I think it should just work!
I had to open an MSDN support ticket with Microsoft for this one, but got my answer.
The answer here is a simple client-side solution. My previous WebRequest method looked like this:
protected override WebRequest GetWebRequest(Uri uri)
{
var request = base.GetWebRequest(uri);
request.Headers.Add("Accept-Encoding", "gzip");
return request;
}
The better way is this:
protected override WebRequest GetWebRequest(Uri uri)
{
var request = (HttpWebRequest) base.GetWebRequest(uri);
request.AutomaticDecompression = DecompressionMethods.GZip;
return request;
}
I'm not entirely sure why this works: The headers on the request and response are exactly the same, but the client seems to be able to manage the response it gets back.
This seems to work with both IIS6 and IIS7, even though the IIS6 response is chunked and the IIS7 one isn't. If anyone can help explain exactly why this works, it might be helpful to the community.

Why do I get "Cannot redirect after HTTP headers have been sent" when I call Response.Redirect()?

When I call Response.Redirect(someUrl) I get the following HttpException:
Cannot redirect after HTTP headers have been sent.
Why do I get this? And how can I fix this issue?
According to the MSDN documentation for Response.Redirect(string url), it will throw an HttpException when "a redirection is attempted after the HTTP headers have been sent". Since Response.Redirect(string url) uses the Http "Location" response header (http://en.wikipedia.org/wiki/HTTP_headers#Responses), calling it will cause the headers to be sent to the client. This means that if you call it a second time, or if you call it after you've caused the headers to be sent in some other way, you'll get the HttpException.
One way to guard against calling Response.Redirect() multiple times is to check the Response.IsRequestBeingRedirected property (bool) before calling it.
// Causes headers to be sent to the client (Http "Location" response header)
Response.Redirect("http://www.stackoverflow.com");
if (!Response.IsRequestBeingRedirected)
// Will not be called
Response.Redirect("http://www.google.com");
Once you send any content at all to the client, the HTTP headers have already been sent. A Response.Redirect() call works by sending special information in the headers that make the browser ask for a different URL.
Since the headers were already sent, asp.net can't do what you want (modify the headers)
You can get around this by a) either doing the Redirect before you do anything else, or b) try using Response.Buffer = true before you do anything else, to make sure that no output is sent to the client until the whole page is done executing.
A Redirect can only happen if the first line in an HTTP message is "HTTP/1.x 3xx Redirect Reason".
If you already called Response.Write() or set some headers, it'll be too late for a redirect. You can try calling Response.Headers.Clear() before the Redirect to see if that helps.
Just check if you have set the buffering option to false (by default its true). For response.redirect to work,
Buffering should be true,
you should not have sent more data using response.write which exceeds the default buffer size (in which case it will flush itself causing the headers to be sent) therefore disallowing you to redirect.
Using
return RedirectPermanent(myUrl) worked for me
You can also use below mentioned code
Response.Write("<script type='text/javascript'>"); Response.Write("window.location = '" + redirect url + "'</script>");Response.Flush();
There is one simple answer for this:
You have been output something else, like text, or anything related to output from your page before you send your header. This affect why you get that error.
Just check your code for posible output or you can put the header on top of your method so it will be send first.
If you are trying to redirect after the headers have been sent (if, for instance, you are doing an error redirect from a partially-generated page), you can send some client Javascript (location.replace or location.href, etc.) to redirect to whatever URL you want. Of course, that depends on what HTML has already been sent down.
My Issue got resolved by adding the Exception Handler to handle
"Cannot redirect after HTTP headers have been sent". this Error as shown below code
catch (System.Threading.ThreadAbortException)
{
// To Handle HTTP Exception "Cannot redirect after HTTP headers have been sent".
}
catch (Exception e)
{//Here you can put your context.response.redirect("page.aspx");}
I solved the problem using:
Response.RedirectToRoute("CultureEnabled", RouteData.Values);
instead of Response.Redirect.
Be sure that you don't use Responses' methods like Response.Flush(); before your redirecting part.
Error
Cannot redirect after HTTP headers have been sent.
System.Web.HttpException (0x80004005): Cannot redirect after HTTP headers have been sent.
Suggestion
If we use asp.net mvc and working on same controller and redirect to different Action then you do not need to write.. Response.Redirect("ActionName","ControllerName"); its better to use only return RedirectToAction("ActionName"); or return View("ViewName");
The redirect function probably works by using the 'refresh' http header (and maybe using a 30X code as well). Once the headers have been sent to the client, there is not way for the server to append that redirect command, its too late.
If you get Cannot redirect after HTTP headers have been sent then try this below code.
HttpContext.Current.Server.ClearError();
// Response.Headers.Clear();
HttpContext.Current.Response.Redirect("/Home/Login",false);
There are 2 ways to fix this:
Just add a return statement after your Response.Redirect(someUrl);
( if the method signature is not "void", you will have to return that "type", of course )
as so:
Response.Redirect("Login.aspx");
return;
Note the return allows the server to perform the redirect...without it, the server wants to continue executing the rest of your code...
Make your Response.Redirect(someUrl) the LAST executed statement in the method that is throwing the exception. Replace your Response.Redirect(someUrl) with a string VARIABLE named "someUrl", and set it to the redirect location... as follows:
//......some code
string someUrl = String.Empty
.....some logic
if (x=y)
{
// comment (original location of Response.Redirect("Login.aspx");)
someUrl = "Login.aspx";
}
......more code
// MOVE your Response.Redirect to HERE (the end of the method):
Response.Redirect(someUrl);
return;

Resources