1 /** 2 * Defines the `ESParams` type for use in the API 3 * 4 * Copyright: © 2015 David Monagle 5 * License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file. 6 * Authors: David Monagle 7 */ 8 module elasticsearch.api.parameters; 9 10 import vibe.utils.dictionarylist; 11 import elasticsearch.api.exceptions; 12 import core.exception; 13 14 import std.array; 15 import std.algorithm; 16 import std.string; 17 18 /// Common ES parameters 19 static enum ES_COMMON_PARAMETERS = [ 20 "ignore", 21 //"index", "type", "id", 22 //"body", 23 "node_id", 24 "name", 25 "field" 26 ]; 27 28 /// Common ES parameters used in queries 29 static enum ES_COMMON_QUERY_PARAMETERS = [ 30 "format", 31 "pretty", 32 "human" 33 ]; 34 35 /// ESParams is just an alias for a vibe.d dictionary list 36 alias ESParams = vibe.inet.message.InetHeaderMap; 37 38 bool hasField(const ref ESParams p, string key) { 39 return cast(bool)(key in p); 40 } 41 42 /// Filters the given `ESParams` to only include the given keys. Returns a new range containing the allowed keys 43 ESParams filterESParams(const ref ESParams p, string[] allowed ...) { 44 import std.algorithm; 45 46 ESParams returnParams; 47 48 foreach(key, value; p) { 49 if (allowed.canFind(key)) returnParams.addField(key, value); 50 } 51 52 return returnParams; 53 } 54 55 unittest { 56 ESParams p; 57 p["one"] = "Hello"; 58 p["two"] = "Goodbye"; 59 60 auto filtered = p.filterESParams("one"); 61 62 assert(filtered.hasField("one")); 63 assert(!filtered.hasField("two")); 64 } 65 66 /// Returns the value of the supplied `ESParams ` or returns the defaultValue if it doesn't exist 67 T valueOrDefault(T)(ESParams p, string key, T defaultValue) { 68 import std.conv; 69 70 if (key !in p) return defaultValue; 71 return p[key].to!T; 72 } 73 74 unittest { 75 ESParams p; 76 p["one"] = "1"; 77 78 assert(p.valueOrDefault("one", 2) == 1); 79 assert(p.valueOrDefault("two", 2) == 2); 80 } 81 82 /// Throws an argument exception if the given parameter is not included in `p` 83 void enforceParameter(const ref ESParams p, string name) { 84 enforce(p.hasField(name), new ArgumentException(p, name ~ " parameter is required")); 85 } 86 87 /// Sets a parameter to a default value if if does not exist 88 void defaultParameter(ref ESParams p, string name, string defaultValue) { 89 if(!p.hasField(name)) p[name] = defaultValue; 90 } 91 92 /// Returns a new list of params which will only included common parameters plus those `allowed` passed in parameters 93 ESParams validateAndExtract(const ref ESParams params, string[] allowed ...) { 94 return params.filterESParams(allowed ~ ES_COMMON_PARAMETERS ~ ES_COMMON_QUERY_PARAMETERS); 95 } 96 97 /// Escapes the given string for use with ES API 98 string esEscape(string value) { 99 import std.uri; 100 101 return encodeComponent(value); 102 } 103 104 /// Takes an array of strings representing a path and returns a clean path string 105 string esPathify(string[] path ...) { 106 auto stripped = array(path.map!((p) => p.strip)); 107 auto cleanPath = stripped.remove!((p) => !p.length); 108 auto returnString = cleanPath.join("/"); 109 return returnString.squeeze("/"); 110 } 111 112 unittest { 113 assert(esPathify("hello/", "", " world") == "hello/world"); 114 } 115 116 /// Create a list from the given arguments 117 string esListify(string[] list ...) { 118 auto cleanList = list.remove!((p) => !p.length); 119 auto escaped = array(cleanList.map!((l) => l.esEscape)); 120 121 return escaped.join(","); 122 } 123 124 unittest { 125 assert(esListify("A", "B") == "A,B"); 126 assert(esListify("one", "two^three") == "one,two%5Ethree"); 127 }