You are here: Foswiki>Tasks Web>Item10824 (05 Jul 2015, GeorgeClark)Edit Attach

Item10824: HEAD requests should return early.

pencil
Priority: Enhancement
Current State: Closed
Released In: 2.0.0
Target Release: major
Applies To: Engine
Component: FoswikiUIView
Branches: master
Reported By: AndrewJones
Waiting For:
Last Change By: GeorgeClark
At the moment, when Foswiki receives a HEAD request, it will generate the entire page, as it does with a GET. So it will generate the HTML, execute plugins, etc.

However, all a HEAD request needs to do is check permissions and send the appropriate response. Generating the HTML is a waste of time, especially on pages with a big %SEARCH or using an expensive plugin.

To solve this, I did the following...

Index: View.pm
===================================================================
--- View.pm     (revision 11801)
+++ View.pm     (working copy)
@@ -186,6 +186,10 @@
         $revIt = new Foswiki::ListIterator( [1] );
     }
 
+    if($session->{request}->method eq 'HEAD'){
+        return $session->writeCompletePage( '', 'view', 'text/plain' );
+    }
+
     if ($raw) {
         $indexableView = 0;
         $logEntry .= ' raw=' . $raw;
(patch against 01x01)

This seems to be working fine. Foswiki checks authentication correctly, and returns the appropriate response. I have been using it for months on our internal wiki without any issues.

I want to check this in, but would like to have someone with more knowledge of the FW internals to check it over first.

Background

This became a problem for us as we use the Google Search Appliance. To do its authentication, it sends up to 15 HEAD requests to the 15 top results with the users credentials. When 15 requests hit our wiki at the same time, it becomes very slow...

-- AndrewJones - 01 Jun 2011

This seems simple enough. There are probably some ordering questions though.
  • If the page is in the PageCache, Should it just follow the normal path since it will be fast?
  • Or should we skip all cache processing for HEAD requests.

-- GeorgeClark - 30 May 2014

Revised patch
commit 8d50207a0b5ffbdeb633a36f72a6668f933aa188
Merge: 48197a0 2f14679
Author: George Clark <geonwiki@fenachrone.com>
Date:   Fri May 30 00:45:15 2014 -0400

    On master: Item10824 HEAD processing

diff --combined core/lib/Foswiki/UI/View.pm
index 9dd0403,9dd0403..4111431
--- a/core/lib/Foswiki/UI/View.pm
+++ b/core/lib/Foswiki/UI/View.pm
@@@ -73,6 -73,6 +73,8 @@@ sub view 
  
      my $cache    = $session->{cache};
      my $response = $session->{response};
++    my $method   = $session->{request}->method || '';
++
      my $cachedPage;
      $cachedPage = $cache->getPage( $web, $topic ) if $cache;
      if ($cachedPage) {
@@@ -285,10 -285,10 +287,14 @@@
              level    => 'info',
              action   => 'view',
              webTopic => $topicObject->web . '.' . $topicObject->topic,
--            extra    => $logEntry,
++            extra    => $logEntry . " ($method)"
          }
      );
  
++    if ( $method && $method eq 'HEAD' ) {
++        return $session->writeCompletePage( '', 'view', 'text/plain' );
++    }
++
      # Note; must enter all contexts before the template is read, as
      # TMPL:P is expanded on the fly in the template reader. :-(
      my ( $revTitle, $revArg ) = ( '', '' );

My concern is the positioning of this. Should it be ahead of the cache work, or following it.

-- GeorgeClark - 04 Aug 2014

Testing with

$.ajax({type:"HEAD", url: "http://.../bin/view ..."});

The above patch isn't complete yet. First, there's a cache collision between GET and HEAD which means a HEAD request to a cached page will still receive the cached HTML of a previous GET to the same url. We don't have the same problem with POST as they are excluded in Foswiki::PageCache::isCacheable(). HEAD requests should be excluded from being cached. There's no need to cache an empty reply.

diff --git a/lib/Foswiki/PageCache.pm b/lib/Foswiki/PageCache.pm
index 1a471f1..c6000fc 100644
--- a/lib/Foswiki/PageCache.pm
+++ b/lib/Foswiki/PageCache.pm
@@ -386,9 +386,9 @@ sub isCacheable {
 
     my $session = $Foswiki::Plugins::SESSION;
 
-    # POSTs aren't cacheable
+    # POSTs and HEADs aren't cacheable
     my $method = $session->{request}->method;
-    $isCacheable = 0 if $method && $method eq 'POST';
+    $isCacheable = 0 if $method && $method =~ /^(?:POST|HEAD)$/;
 
     if ($isCacheable) {
 

With this patch in place, where to check for HEAD in View.pm doesn't matter anymore. It must be located after the existence and access checks anyway.

-- MichaelDaum - 05 Aug 2014

I've implemented these patches along with some unit tests.

I don't think that the unit test is quite right, as even with the HEAD patch disabled, it still passes. However the patch is clearly working, as HEAD requests for a search page like System/Macros goes from 7+ seconds to around 500ms.

-- GeorgeClark - 23 Aug 2014
 

ItemTemplate edit

Summary HEAD requests should return early.
ReportedBy AndrewJones
Codebase 1.1.3, trunk
SVN Range
AppliesTo Engine
Component FoswikiUIView
Priority Enhancement
CurrentState Closed
WaitingFor
Checkins distro:1bfb7b47bbaf distro:b1f2b7cbb298
TargetRelease major
ReleasedIn 2.0.0
CheckinsOnBranches master
trunkCheckins
masterCheckins distro:1bfb7b47bbaf distro:b1f2b7cbb298
Release01x01Checkins
Topic revision: r9 - 05 Jul 2015, GeorgeClark
The copyright of the content on this website is held by the contributing authors, except where stated elsewhere. See Copyright Statement. Creative Commons License    Legal Imprint    Privacy Policy