IHttp Generic Handler (.ashx) for Images cache validator - asp.net-mvc-3

I have IHttp Generic Handler (.ashx) for images and I have sent cache expire time as 7 days but in Google page insight it says I should add cache validator.
following is my code. Please refer me something.
public void ProcessRequest(HttpContext context)
{
TimeSpan refresh = TimeSpan.FromDays(7);
context.Response.Cache.SetExpires(DateTime.Now.Add(refresh));
context.Response.Cache.SetMaxAge(refresh);
context.Response.Cache.SetCacheability(HttpCacheability.Public);
context.Response.CacheControl = HttpCacheability.Public.ToString();
context.Response.Cache.SetValidUntilExpires(true);
}
Thanks

After some research I found out that we can add Etag or SetLastModified or just Add a header into cache like below:
context.Response.Cache.SetETag(DateTime.Now.ToLongDateString());
context.Response.Cache.SetLastModified(DateTime.Now.ToLongDateString());
context.Response.AddHeader("Last-Modified", DateTime.Now.ToLongDateString());

Related

Get #RenderMapping to return external url

I am using liferay and I have a spring portlet.
The view is rendered fine. I have a link to the same page - if clicked, it should perform some logic and then (conditionaly) open a new tab with a external site:
What I have so far:
#Component
#RequestMapping(value = "VIEW")
...
#RenderMapping
public String view(Model model, PortletRequest request, PortletResponse response) throws Exception {
....
response.setProperty(ResourceResponse.HTTP_STATUS_CODE, String.valueOf(HttpServletResponse.SC_MOVED_TEMPORARILY));
final String redirect = "https://......";
response.setProperty("Location", redirect);
return "redirect:" + redirect;
.....
It does open a new tab, but it does not leave the portal context. It wont open the new location.
Any hints?
Given that you have access to try the following:
#RenderMapping
public String view(Model model, PortletRequest request, HttpServletResponse response) throws Exception {
final String redirect = "https://......";
response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
response.setHeader("Location", redirect);
return "";
}
Rendering a portlet always renders part of a page in a portal, thus you won't have access to the original HttpServletResponse without trickery. And even if you get access, the response might already be committed, the portal engine might have decided to deliver your content asynchronously - you're well shielded from the actual result. in short: you can't really think along any HTTP games.
You have a couple of other options though:
render JS that does the redirect
move your code to the portlet's Action phase, where state updates are expected (render phase is supposed to render, not to change state or make such decisions) - in the action phase you could issue a redirect, but it'll be hard to conditionally do so for opening in a new tab
move your code to the portlet's resource phase, trigger it asynchronously and decide in the frontend if you want to open a new tab or not, based on the return you get.
move your code to a REST service (continue as in the resource phase bullet point above)

Using HtmlUnit, is there a way to pause execution of Javascript, then resume?

In HtmlUnit for testing, I'm coming across a case where, on page load, it'd be useful to NOT execute the Javascript automatically, and instead wait for me to initiate and tell the Javascript to start executing?
My specific use-case is testing something which the Javascript does some tests, and then does a location replace to send the user on to another page. I want to check some headers which I'm returning for testing/validation, and then let the JS execute as usual.
My current thought is to have a flag I pass to the page when testing which will cause the JS to not automatically run, and wait until I call a JS function from within the Java code via webClient.getJavaScriptEngine().execute().
While not specifically being able to pause JavaScript before invoking, it may be worthwhile to use the WebConnectionWrapper class to inspect/modify the response data or outgoing requests, effectively giving you a chance to execute your own code before the JavaScript is invoked.
An example usage of this is as follows:
try (final WebClient webClient = new WebClient()) {
webClient.getOptions().setThrowExceptionOnScriptError(false);
// set more options
// create a WebConnectionWrapper with an (subclassed) getResponse() impl
new WebConnectionWrapper(webClient) {
public WebResponse getResponse(WebRequest request) throws IOException {
WebResponse response = super.getResponse(request);
if (request.getUrl().toExternalForm().contains("my_url")) {
String content = response.getContentAsString();
// intercept and/or change content
WebResponseData data = new WebResponseData(content.getBytes(),
response.getStatusCode(), response.getStatusMessage(), response.getResponseHeaders());
response = new WebResponse(data, request, response.getLoadTime());
}
return response;
}
};
// use the client as usual
HtmlPage page = webClient.getPage(uri);
}
The above code is from the official documentation here:
How to modify the outgoing request or incoming response?
The getResponse() method that you would override is called before each request is made and also allows you to modify the WebResponse object that is passed back to WebClient for its continued processing.
Sorry but at the moment (version 2.43.0) we have no such option. Feel free to open a issue on github for this.
I guess other test tools might also benefit from this function.

Get "time of upload started"

I'm developing a WebAPI service in which you can upload a file. The Action looks something like this:
[HttpPost]
public async Task<IHttpActionResult> PostAsync(byte[] content)
{
var now = DateTime.UtcNow;
}
The client which are using the WebAPI also provides a timestamp as header which is used together with some HMAC-stuff to authenticate. One part of the auth check is to validate the timestamp. We parse the timestamp and checks if it is +/- 5 minutes from now. If not then the auth fails.
It works great for all our API calls except this upload API (in some cases). The problem is that sometimes a user uploads a large file over a slow connection and therefore it takes more than 5 minutes to upload the file and the point in time where we check is AFTER the whole file has been uploaded.
Therefore:
Can we somehow do the HMAC check BEFORE the whole file is uploaded? (the file itself (HTTP Content) is not used in the HMAC check). Today we are using an ActionFilter.
Can I get the "time of request" (first byte arrived or whatever) in my Action code?
Thanks!
So, after some investigation I came up with a much better solution:
Use a HTTP Module to do the actual HMAC authentication.
After reading this blog post (http://blogs.msdn.com/b/tmarq/archive/2007/08/30/iis-7-0-asp-net-pipelines-modules-handlers-and-preconditions.aspx) I got a much better understanding of how IIS Works.
I decided to use a HTTP Module which is invoked before the MVC Action.
The code ended up like this:
public class HmacModule : IHttpModule
{
public void Init(HttpApplication context)
{
EventHandlerTaskAsyncHelper taskAsyncHelper = new EventHandlerTaskAsyncHelper(Authenticate);
context.AddOnBeginRequestAsync(taskAsyncHelper.BeginEventHandler, taskAsyncHelper.EndEventHandler);
}
private async Task Authenticate(object sender, EventArgs e)
{
var context = ((HttpApplication)sender).Context;
var request = context.Request;
var authResponse = await CheckAuthentication(request);
if (!authResponse.HasAccess)
{
context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
context.Response.StatusDescription = authResponse.ErrorMessage;
if (authResponse.Details != null)
context.Response.Write(authResponse.Details);
context.Response.End();
}
}
}
I hope this helps others in the same situation...

Sitecore and caching control

I am working on this Sitecore project and am using WebApi to perform some service calls. My methods are decorated with CacheOutput information like this:
[HttpGet]
[CacheOutput(ClientTimeSpan = 3600, ServerTimeSpan = 3600)]
I am testing these calls using DHC app on Google Chrome. I am sure that the ClientTimespan is set correctly but the response headers that i am getting back are not what i am expecting. I would expect that Cache-Control would have a max-age of 1hour as set by the ClientTimespan attribute but instead it is set to private.
I have been debugging everything possible and t turns out that Sitecore may be intercepting the response and setting this header value to private. I have also added the service url to the sitecore ignored url prefixes configuration but no help .
Does anyone have an idea how I can make Sitecore NOT change my Cache-Control headers?
This is default MVC behaviour and not directly related to Sitecore / Web API.
You can create a custom attribute that sets the Cache-Control header:
public class CacheControl : System.Web.Http.Filters.ActionFilterAttribute
{
public int MaxAge { get; set; }
public CacheControl()
{
MaxAge = 3600;
}
public override void OnActionExecuted(HttpActionExecutedContext context)
{
context.Response.Headers.CacheControl = new CacheControlHeaderValue()
{
Public = true,
MaxAge = TimeSpan.FromSeconds(MaxAge)
};
base.OnActionExecuted(context);
}
}
Which enables you to add the [CacheControl(MaxAge = n)] attribute to your methods.
Code taken from: Setting HTTP cache control headers in WebAPI (answer #2)
Or you can apply it globally throughout the application, as explained here: http://juristr.com/blog/2012/10/output-caching-in-aspnet-mvc/

Testing of the PhpBB forum

I am testing forum PhpBB with help of HTML unit. I want to add message in one of topic of PhpBB forum. I enter the message in textarea and click the submit button, but new page doesn't have my message. What seems to be the problem?
final ArrayList<HtmlForm> formList=(ArrayList<HtmlForm>) page.getByXPath("//form[#id='postform']");
final HtmlTextArea myMessage=formList.get(0).getTextAreaByName("message");
myMessage.type("text");
final HtmlSubmitInput submit_post = formList.get(0).getInputByName("post");
page=submit_post.click();
if (page.asText().contains("text")) {
System.out.println("right");
}
Thank you for help!
One way around this is to construct a custom http post request.
Use FIddler to capture the traffic and then replicate it with HTMLUnit. It should look something like below
public Page postMessage() throws Exception
{
URL url = new URL("YOURURL");
WebRequest requestSettings = new WebRequest(url, HttpMethod.POST);
requestSettings.setAdditionalHeader("Accept", "*/*");
requestSettings.setAdditionalHeader("Content-Type", "application/x-www-form-urlencoded");
requestSettings.setAdditionalHeader("Referer", "REFERER");
requestSettings.setAdditionalHeader("Accept-Language", "en-US,en;q=0.8");
requestSettings.setAdditionalHeader("Accept-Encoding", "gzip,deflate,sdch");
requestSettings
.setRequestBody("YOURPOSTREQUEST");
Page page = webClient.getPage(requestSettings);
return page;
}

Resources