]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Cache Manager migration support
authorAmos Jeffries <squid3@treenet.co.nz>
Fri, 30 Dec 2011 16:01:37 +0000 (05:01 +1300)
committerAmos Jeffries <squid3@treenet.co.nz>
Fri, 30 Dec 2011 16:01:37 +0000 (05:01 +1300)
 * Add a little bit of XHR script to the CGI cachemgr front page which
probes each of the managed proxies for http:// and https:// capabilities
and produces web links to their internal managers.

 * Reserve the template name MGR_INDEX for use by cachemgr scripts.
But do not distribute any preset template. This allows manager apps to
provide their own static template with linked scripts and objects.

 * The error page system is updated to create a blanket message
indicating missing template instead of aborting Squid if a template is
not even installed.

src/cache_manager.cc
src/err_type.h
src/errorpage.cc
src/mgr/BasicActions.cc
src/mgr/BasicActions.h
tools/cachemgr.cc

index 49535b29d78915a0fed5d97d483ce3341ec4432e..88f195786c7ca45a5425d54806de387802223b0d 100644 (file)
@@ -203,7 +203,7 @@ CacheManager::ParseUrl(const char *url)
         t = sscanf(url, "https://%[^/]/squid-internal-mgr/%[^?]%n?%s", host, request, &pos, params);
     }
     if (t < 2)
-        xstrncpy(request, "menu", MAX_URL);
+        xstrncpy(request, "index", MAX_URL);
 
 #if _SQUID_OS2_
     if (t == 2 && request[0] == '\0') {
@@ -211,7 +211,7 @@ CacheManager::ParseUrl(const char *url)
          * emx's sscanf insists of returning 2 because it sets request
          * to null
          */
-        xstrncpy(request, "menu", MAX_URL);
+        xstrncpy(request, "index", MAX_URL);
     }
 #endif
 
@@ -399,6 +399,26 @@ CacheManager::Start(const Comm::ConnectionPointer &client, HttpRequest * request
            client << " requesting '" <<
            actionName << "'" );
 
+    // special case: /squid-internal-mgr/ index page
+    if (!strcmp(cmd->profile->name, "index")) {
+        ErrorState err(MGR_INDEX, HTTP_OK, request);
+        err.url = xstrdup(entry->url());
+        HttpReply *rep = err.BuildHttpReply();
+        if (strncmp(rep->body.content(),"Internal Error:", 15) == 0)
+            rep->sline.status = HTTP_NOT_FOUND;
+        // Allow cachemgr and other XHR scripts access to our version string
+        if (request->header.has(HDR_ORIGIN)) {
+            rep->header.putExt("Access-Control-Allow-Origin",request->header.getStr(HDR_ORIGIN));
+#if HAVE_AUTH_MODULE_BASIC
+            rep->header.putExt("Access-Control-Allow-Credentials","true");
+#endif
+            rep->header.putExt("Access-Control-Expose-Headers","Server");
+        }
+        entry->replaceHttpReply(rep);
+        entry->complete();
+        return;
+    }
+
     if (UsingSmp() && IamWorkerProcess()) {
         // is client the right connection to pass here?
         AsyncJob::Start(new Mgr::Forwarder(client, cmd->params, request, entry));
index e919310c108314684e366f0f7c481037e6d5a5c9..a8c28ae7ea70e4a5613800584b51b8221b9db5ed 100644 (file)
@@ -52,6 +52,9 @@ typedef enum {
     /* ICAP Errors */
     ERR_ICAP_FAILURE,
 
+    /* Cache Manager */
+    MGR_INDEX,
+
     /* Squid problem */
     ERR_GATEWAY_FAILURE,
 
index 1197445c52a2054b3cbb3e169d1a2cf7195c48c7..39e10c6c0284c09a350f04f0a7a4814ce51384f8 100644 (file)
@@ -298,8 +298,11 @@ TemplateFile::loadDefault()
     }
 
     /* giving up if failed */
-    if (!loaded())
-        fatal("failed to find or read error text file.");
+    if (!loaded()) {
+        debugs(1, DBG_CRITICAL, "WARNING: failed to find or read error text file " << templateName);
+        parse("Internal Error: Missing Template ", 33, '\0');
+        parse(templateName.termedBuf(), templateName.size(), '\0');
+    }
 
     return true;
 }
index f98a9c7251b99a2845bcda36328aba960d53353b..1d0a8909a8b33424b8e32d6f93179ffc6d62eff9 100644 (file)
 #include "Store.h"
 
 
+Mgr::IndexAction::Pointer
+Mgr::IndexAction::Create(const Command::Pointer &cmd)
+{
+    return new IndexAction(cmd);
+}
+
+Mgr::IndexAction::IndexAction(const Command::Pointer &cmd): Action(cmd)
+{
+    debugs(16, 5, HERE);
+}
+
+void
+Mgr::IndexAction::dump(StoreEntry* entry)
+{
+    debugs(16, 5, HERE);
+}
+
 Mgr::MenuAction::Pointer
 Mgr::MenuAction::Create(const Command::Pointer &cmd)
 {
@@ -128,9 +145,10 @@ Mgr::OfflineToggleAction::dump(StoreEntry* entry)
 void
 Mgr::RegisterBasics()
 {
+    RegisterAction("index", "Cache Manager Interface", &Mgr::IndexAction::Create, 0, 1);
+    RegisterAction("menu", "Cache Manager Menu", &Mgr::MenuAction::Create, 0, 1);
     RegisterAction("offline_toggle", "Toggle offline_mode setting", &Mgr::OfflineToggleAction::Create, 1, 1);
     RegisterAction("shutdown", "Shut Down the Squid Process", &Mgr::ShutdownAction::Create, 1, 1);
     RegisterAction("reconfigure", "Reconfigure Squid", &Mgr::ReconfigureAction::Create, 1, 1);
     RegisterAction("rotate", "Rotate Squid Logs", &Mgr::RotateAction::Create, 1, 1);
-    RegisterAction("menu", "Cache Manager Menu", &Mgr::MenuAction::Create, 0, 1);
 }
index ffe8008579671c2cc964a1133f7cc784d210a1d0..495e5bff2bd76881cdb2b857961336c2b6340694 100644 (file)
 namespace Mgr
 {
 
+/// A dummy action placeholder for the no-action requests
+/// a templated Cache Manager index ('home') page.
+/// Display output is produced directly by the receiving worker
+/// without invoking the co-ordinator or action Job.
+class IndexAction: public Action
+{
+public:
+    static Pointer Create(const CommandPointer &cmd);
+    /* Action API */
+    virtual void dump(StoreEntry *entry);
+
+protected:
+    IndexAction(const CommandPointer &cmd);
+};
+
+
 /// returns available Cache Manager actions and their access requirements
 class MenuAction: public Action
 {
index e8c7060b2a29036c6a3bea00f3d22ef997db81d2..a8c3930ee6fd59c783290d521165c79f4a828626 100644 (file)
@@ -274,13 +274,40 @@ auth_html(const char *host, int port, const char *user_name)
     if (!host || !strlen(host))
         host = "";
 
+    fp = fopen("cachemgr.conf", "r");
+
+    if (fp == NULL)
+        fp = fopen(DEFAULT_CACHEMGR_CONFIG, "r");
+
+    if (fp == NULL)
+        printf("X-Error: message=\"Unable to open config %s\"", DEFAULT_CACHEMGR_CONFIG);
+
     printf("Content-Type: text/html\r\n\r\n");
 
     printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n");
 
     printf("<HTML><HEAD><TITLE>Cache Manager Interface</TITLE>\n");
 
-    printf("<STYLE type=\"text/css\"><!--BODY{background-color:#ffffff;font-family:verdana,sans-serif}--></STYLE></HEAD>\n");
+    printf("<STYLE type=\"text/css\"><!--BODY{background-color:#ffffff;font-family:verdana,sans-serif}--></STYLE>\n");
+
+    printf("<script type=\"text/javascript\">\n");
+    printf("function TS(t, s) {\n");
+    printf(" var x = new XMLHttpRequest();\n");
+    printf(" x.open('GET', 'http' + s + '://' + t + '/squid-internal-mgr/', true);\n");
+    printf(" x.onreadystatechange=function() {\n");
+    printf("  if (x.readyState==4) {\n");
+    printf("   if ((x.status>=200 && x.status <= 299) || x.status==401) {\n");
+    printf("    var v = x.getResponseHeader('Server');\n");
+    printf("    if (v.substring(0,8) == 'squid/3.' && (v[8]=='H' || parseInt(v.substring(8)) >= 2)) {\n");
+    printf("     var d = document.getElementById('H' + s + 'mgr');\n");
+    printf("     if (d.innerHTML == '') d.innerHTML = '<h2>HTTP' + (s=='s'?'S':'') + ' Managed Proxies</h2>';\n");
+    printf("     d.innerHTML = d.innerHTML + '<p>Host: <a href=\"http' + s + '://' + t + '/squid-internal-mgr/\">' + t + '</a></p>';\n");
+    printf(" }}}}\n");
+    printf(" x.send(null);\n");
+    printf("}\n");
+    printf("</script>\n");
+
+    printf("</HEAD>\n");
 
     printf("<BODY><H1>Cache Manager Interface</H1>\n");
 
@@ -290,16 +317,15 @@ auth_html(const char *host, int port, const char *user_name)
 
     printf("<HR noshade size=\"1px\">\n");
 
+    printf("<div id=\"Hsmgr\"></div>\n");
+    printf("<div id=\"Hmgr\"></div>\n");
+    printf("<div id=\"Cmgr\">\n");
+    printf("<h2>CGI Managed Proxies</h2>\n");
     printf("<FORM METHOD=\"POST\" ACTION=\"%s\">\n", script_name);
 
     printf("<TABLE BORDER=\"0\" CELLPADDING=\"10\" CELLSPACING=\"1\">\n");
 
 
-    fp = fopen("cachemgr.conf", "r");
-
-    if (fp == NULL)
-        fp = fopen(DEFAULT_CACHEMGR_CONFIG, "r");
-
     if (fp != NULL) {
         int servers = 0;
         char config_line[BUFSIZ];
@@ -331,9 +357,8 @@ auth_html(const char *host, int port, const char *user_name)
             if (!comment || !*comment)
                 comment = server;
 
-            if (!servers) {
-                printf("<TR><TH ALIGN=\"left\">Cache Server:</TH><TD><SELECT NAME=\"server\">\n");
-            }
+            if (!servers)
+                printf("<TR><TH ALIGN=\"left\">Cache Server:</TH><TD><SELECT id=\"server\" NAME=\"server\">\n");
 
             printf("<OPTION VALUE=\"%s\"%s>%s</OPTION>\n", server, (servers || *host) ? "" : " SELECTED", comment);
             servers++;
@@ -377,7 +402,14 @@ auth_html(const char *host, int port, const char *user_name)
 
     printf("<INPUT TYPE=\"submit\" VALUE=\"Continue...\">\n");
 
-    printf("</FORM>\n");
+    printf("</FORM></div>\n");
+
+    printf("<script type=\"text/javascript\">\n");
+    printf("var s = document.getElementById(\"server\");\n");
+    printf("for (var i = 0; i < s.childElementCount; i++) {\n");
+    printf(" TS(s.children[i].value, '');\n");
+    printf(" TS(s.children[i].value, 's');\n");
+    printf("}</script>\n");
 
     print_trailer();
 }