Note that this changes the URL, and only allows for exact flushing now.
Fixes #3003.
Cache Access
============
-**TODO**: Peek at the cache, clear the cache, possibly dump it into a file?
+**TODO**: Not yet implemented: Peek at the cache, clear the cache, possibly read cache?
+
+URL: /api/v1/servers/:server\_id/cache/flush?domain=:domain
+--------------------------------------------
+
+Allowed methods: `PUT` (Execute)
+
+#### PUT (Execute)
+
+Flush the cache for a given domain name `:domain`. Response body:
+
+ {
+ "count": 10,
+ "result": "Flushed cache."
+ }
+
+Implementation detail: On Authoritative servers, this clears the packet cache.
+On Recursors, this clears the positive, negative and packet cache.
-**TODO**: Not yet implemented.
Logging & Statistics
====================
#### GET (Query)
-Query the log, filtered by `:search_term`. Response body:
+Query the log, filtered by `:search_term` (query parameter). Response body:
[
"<log_line>",
resp->setBody(doc);
}
-void apiServerFlushCache(HttpRequest* req, HttpResponse* resp) {
+void apiServerCacheFlush(HttpRequest* req, HttpResponse* resp) {
if(req->method != "PUT")
throw HttpMethodNotAllowedException();
+ DNSName canon = apiNameToDNSName(req->getvars["domain"]);
+
extern PacketCache PC;
- int count;
- if(req->getvars["domain"].empty())
- count = PC.purge();
- else
- count = PC.purge(req->getvars["domain"]);
+ int count = PC.purgeExact(canon);
map<string, string> object;
object["count"] = lexical_cast<string>(count);
{
try {
if(::arg().mustDo("api")) {
+ d_ws->registerApiHandler("/api/v1/servers/localhost/cache/flush", &apiServerCacheFlush);
d_ws->registerApiHandler("/api/v1/servers/localhost/config", &apiServerConfig);
- d_ws->registerApiHandler("/api/v1/servers/localhost/flush-cache", &apiServerFlushCache);
d_ws->registerApiHandler("/api/v1/servers/localhost/search-log", &apiServerSearchLog);
d_ws->registerApiHandler("/api/v1/servers/localhost/search-data", &apiServerSearchData);
d_ws->registerApiHandler("/api/v1/servers/localhost/statistics", &apiServerStatistics);
resp->setBody(doc);
}
-static void apiServerFlushCache(HttpRequest* req, HttpResponse* resp) {
+static void apiServerCacheFlush(HttpRequest* req, HttpResponse* resp) {
if(req->method != "PUT")
throw HttpMethodNotAllowedException();
- DNSName canon(req->getvars["domain"]);
+ DNSName canon = apiNameToDNSName(req->getvars["domain"]);
+
int count = broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeCache, canon, false));
+ count += broadcastAccFunction<uint64_t>(boost::bind(pleaseWipePacketCache, canon, false));
count += broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeAndCountNegCache, canon, false));
map<string, string> object;
object["count"] = lexical_cast<string>(count);
// legacy dispatch
d_ws->registerApiHandler("/jsonstat", boost::bind(&RecursorWebServer::jsonstat, this, _1, _2));
- d_ws->registerApiHandler("/api/v1/servers/localhost/flush-cache", &apiServerFlushCache);
+ d_ws->registerApiHandler("/api/v1/servers/localhost/cache/flush", &apiServerCacheFlush);
d_ws->registerApiHandler("/api/v1/servers/localhost/config/allow-from", &apiServerConfigAllowFrom);
d_ws->registerApiHandler("/api/v1/servers/localhost/config", &apiServerConfig);
d_ws->registerApiHandler("/api/v1/servers/localhost/search-log", &apiServerSearchLog);
--- /dev/null
+from test_helper import ApiTestCase, is_auth, is_recursor
+
+
+class Servers(ApiTestCase):
+
+ def test_flush(self):
+ r = self.session.put(self.url("/api/v1/servers/localhost/cache/flush?domain=example.org."))
+ self.assert_success_json(r)
+ data = r.json()
+ self.assertIn('count', data)
+
+ def test_flush_root(self):
+ r = self.session.put(self.url("/api/v1/servers/localhost/cache/flush?domain=."))
+ self.assert_success_json(r)
+ data = r.json()
+ self.assertIn('count', data)
+ self.assertEqual(data['result'], 'Flushed cache.')
+
+ def test_flush_no_domain(self):
+ r = self.session.put(
+ self.url("/api/v1/servers/localhost/cache/flush"))
+ self.assertEquals(r.status_code, 422)
+
+ def test_flush_unqualified(self):
+ r = self.session.put(
+ self.url("/api/v1/servers/localhost/cache/flush?domain=bar"))
+ self.assertEquals(r.status_code, 422)
self.assert_success_json(r)
data = dict([(r['name'], r['value']) for r in r.json()])
self.assertIn('uptime', data)
-
- def test_flush_cache(self):
- r = self.session.put(self.url("/api/v1/servers/localhost/flush-cache?domain=example.org."))
- self.assert_success_json(r)
- data = r.json()
- self.assertIn('count', data)
-
- def test_flush_complete_cache(self):
- r = self.session.put(self.url("/api/v1/servers/localhost/flush-cache"))
- self.assert_success_json(r)
- data = r.json()
- self.assertIn('count', data)
- self.assertEqual(data['result'], 'Flushed cache.')