The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
Changes 072
MANIFEST 16
META.json 56
META.yml 56
Makefile.PL 89
README 11
lib/Search/Elasticsearch/Bulk.pm 22
lib/Search/Elasticsearch/Client/0_90/Direct/Cluster.pm 22
lib/Search/Elasticsearch/Client/0_90/Direct/Indices.pm 22
lib/Search/Elasticsearch/Client/0_90/Direct.pm 311
lib/Search/Elasticsearch/Client/Direct/Cat.pm 323
lib/Search/Elasticsearch/Client/Direct/Cluster.pm 43
lib/Search/Elasticsearch/Client/Direct/Indices.pm 663
lib/Search/Elasticsearch/Client/Direct/Nodes.pm 23
lib/Search/Elasticsearch/Client/Direct/Snapshot.pm 319
lib/Search/Elasticsearch/Client/Direct.pm 6160
lib/Search/Elasticsearch/Cxn/Factory.pm 33
lib/Search/Elasticsearch/Cxn/HTTPTiny.pm 649
lib/Search/Elasticsearch/Cxn/Hijk.pm 313
lib/Search/Elasticsearch/Cxn/LWP.pm 353
lib/Search/Elasticsearch/CxnPool/Sniff.pm 22
lib/Search/Elasticsearch/CxnPool/Static/NoPing.pm 22
lib/Search/Elasticsearch/CxnPool/Static.pm 22
lib/Search/Elasticsearch/Error.pm 22
lib/Search/Elasticsearch/Logger/LogAny.pm 33
lib/Search/Elasticsearch/Role/API/0_90.pm 1817
lib/Search/Elasticsearch/Role/API.pm 58191
lib/Search/Elasticsearch/Role/Bulk.pm 22
lib/Search/Elasticsearch/Role/Client/Direct.pm 23
lib/Search/Elasticsearch/Role/Client.pm 22
lib/Search/Elasticsearch/Role/Cxn/HTTP.pm 426
lib/Search/Elasticsearch/Role/Cxn.pm 33
lib/Search/Elasticsearch/Role/CxnPool/Sniff.pm 22
lib/Search/Elasticsearch/Role/CxnPool/Static/NoPing.pm 22
lib/Search/Elasticsearch/Role/CxnPool/Static.pm 22
lib/Search/Elasticsearch/Role/CxnPool.pm 22
lib/Search/Elasticsearch/Role/Is_Sync.pm 22
lib/Search/Elasticsearch/Role/Logger.pm 22
lib/Search/Elasticsearch/Role/Scroll.pm 1917
lib/Search/Elasticsearch/Role/Serializer/JSON.pm 22
lib/Search/Elasticsearch/Role/Serializer.pm 22
lib/Search/Elasticsearch/Role/Transport.pm 22
lib/Search/Elasticsearch/Scroll.pm 3037
lib/Search/Elasticsearch/Serializer/JSON/Cpanel.pm 22
lib/Search/Elasticsearch/Serializer/JSON/PP.pm 22
lib/Search/Elasticsearch/Serializer/JSON/XS.pm 33
lib/Search/Elasticsearch/Serializer/JSON.pm 22
lib/Search/Elasticsearch/TestServer.pm 22
lib/Search/Elasticsearch/Transport.pm 22
lib/Search/Elasticsearch/Util/API/Path.pm 22
lib/Search/Elasticsearch/Util/API/QS.pm 2642
lib/Search/Elasticsearch/Util.pm 22
lib/Search/Elasticsearch.pm 22
t/60_Cxn/40_fork_httptiny.t 05
t/60_Cxn/41_fork_lwp.t 05
t/60_Cxn/42_fork_hijk.t 05
t/60_Cxn/43_fork_netcurl.t 05
t/70_Helper/50_scroll.t 2425
t/lib/es_sync.pl 13
t/lib/es_sync_fork.pl 042
t/lib/index_test_data.pl 02
t/release-no-tabs.t 16
62 files changed (This is a version diff) 306992
@@ -1,5 +1,77 @@
 Revision history for Search::Elasticsearch
 
+1.16    2014-11-15
+        Added dependency on Pod::Simple, which was causing
+        installation on perl 5.8 to fail
+
+        Added params:
+        * percolate_preference and percolate_routing to percolate()
+
+        Bug fix:
+        * the index param is now required for indices.delete()
+
+1.15    2014-11-05
+        Enhancements:
+         *  All backends (except Hijk) now default to not verifying
+            SSL identities, but accept ssl_options to allow
+            backend-specific configuration
+         *  Improved Mojo exceptions
+
+        Bug fix:
+         *  is_https() didn't work
+
+        Changed:
+         *  index param to put_alias() is now required
+
+        Added methods:
+         *  index.get()
+         *  search_exists()
+         *  indices.upgrade()
+         *  indices.get_upgrade()
+         *  snapshot.verify_repository()
+
+        Added parameters:
+         *  query_cache to search(), clear_cache(), stats()
+         *  wait_if_ongoing to flush()
+         *  script_id and scripted_upsert to update()
+         *  version and version_type to put_script(), get_script(),
+            delete_script(), put_template(), get_template(), and
+            delete_template()
+         *  op_type to put_script() and put_template()
+         *  metric to cluster_reroute()
+         *  realtime to termvector() and mtermvector()
+         *  dfs to termvector()
+
+        Removed parameters:
+         *  filter_metadata from cluster_reroute()
+         *  search_query_hint from mlt()
+
+        Bumped versions:
+            JSON::XS        2.26
+            Package::Stash  0.34
+            Log::Any        0.15
+
+
+1.14    2014-07-24
+        Added support for indexed scripts and indexed templates.
+
+1.13    2014-06-13
+        Breaking change:
+            The Scroll helper used to pass the scroll ID to
+            scroll() and clear_scroll() in the query string by default,
+            with the scroll_in_body parameter to change the behaviour.
+            This was causing frequent errors with long scroll IDs, so
+            the new default behaviour is to pass the scroll ID in the
+            body, with the scroll_in_qs parameter to change that
+            behaviour.
+        All Search::Elasticsearch HTTP backends are now fork safe.
+        Added track_scores param to search()
+        Added create param to indices.put_template()
+        Removed index_templates param from cluster.state()
+        Removed indices_boost param from search()
+        Added percolate_format param to percolate()
+        Added cat.fielddata()
+
 1.12    2014-05-09
         Fixed bug when trying to reindex from a subref
         Added search_shards()
@@ -1,4 +1,4 @@
-# This file was automatically generated by Dist::Zilla::Plugin::Manifest v5.015.
+# This file was automatically generated by Dist::Zilla::Plugin::Manifest v5.020.
 Changes
 LICENSE
 MANIFEST
@@ -110,6 +110,10 @@ t/50_Cxn_Pool/70_live.t
 t/60_Cxn/10_basic.t
 t/60_Cxn/20_process_response.t
 t/60_Cxn/30_http.t
+t/60_Cxn/40_fork_httptiny.t
+t/60_Cxn/41_fork_lwp.t
+t/60_Cxn/42_fork_hijk.t
+t/60_Cxn/43_fork_netcurl.t
 t/70_Helper/10_bulk_add_action.t
 t/70_Helper/20_bulk_helpers.t
 t/70_Helper/30_bulk_flush.t
@@ -121,6 +125,7 @@ t/lib/LogCallback.pl
 t/lib/MockCxn.pm
 t/lib/default_cxn.pl
 t/lib/es_sync.pl
+t/lib/es_sync_fork.pl
 t/lib/index_test_data.pl
 t/release-eol.t
 t/release-no-tabs.t
@@ -4,7 +4,7 @@
       "Clinton Gormley <drtech@cpan.org>"
    ],
    "dynamic_config" : 0,
-   "generated_by" : "Dist::Zilla version 5.015, CPAN::Meta::Converter version 2.140640",
+   "generated_by" : "Dist::Zilla version 5.020, CPAN::Meta::Converter version 2.140640",
    "license" : [
       "apache_2_0"
    ],
@@ -21,7 +21,8 @@
       },
       "configure" : {
          "requires" : {
-            "ExtUtils::MakeMaker" : "6.30"
+            "ExtUtils::MakeMaker" : "0",
+            "Pod::Simple" : "3.28"
          }
       },
       "develop" : {
@@ -46,19 +47,19 @@
             "Hijk" : "0.12",
             "IO::Select" : "0",
             "IO::Socket" : "0",
-            "IO::Socket::SSL" : "0",
             "IO::Uncompress::Inflate" : "0",
             "JSON::MaybeXS" : "1.002002",
             "JSON::PP" : "0",
             "LWP::UserAgent" : "0",
             "List::Util" : "0",
-            "Log::Any" : "0",
+            "Log::Any" : "0.15",
             "Log::Any::Adapter" : "0",
             "MIME::Base64" : "0",
             "Module::Runtime" : "0",
             "Moo" : "1.003",
             "Moo::Role" : "0",
             "POSIX" : "0",
+            "Package::Stash" : "0.34",
             "Scalar::Util" : "0",
             "Sub::Exporter" : "0",
             "Time::HiRes" : "0",
@@ -97,6 +98,6 @@
          "web" : "https://github.com/elasticsearch/elasticsearch-perl"
       }
    },
-   "version" : "1.12"
+   "version" : "1.16"
 }
 
@@ -9,9 +9,10 @@ build_requires:
   Test::More: '0.98'
   lib: '0'
 configure_requires:
-  ExtUtils::MakeMaker: '6.30'
+  ExtUtils::MakeMaker: '0'
+  Pod::Simple: '3.28'
 dynamic_config: 0
-generated_by: 'Dist::Zilla version 5.015, CPAN::Meta::Converter version 2.140640'
+generated_by: 'Dist::Zilla version 5.020, CPAN::Meta::Converter version 2.140640'
 license: apache
 meta-spec:
   url: http://module-build.sourceforge.net/META-spec-v1.4.html
@@ -30,19 +31,19 @@ requires:
   Hijk: '0.12'
   IO::Select: '0'
   IO::Socket: '0'
-  IO::Socket::SSL: '0'
   IO::Uncompress::Inflate: '0'
   JSON::MaybeXS: '1.002002'
   JSON::PP: '0'
   LWP::UserAgent: '0'
   List::Util: '0'
-  Log::Any: '0'
+  Log::Any: '0.15'
   Log::Any::Adapter: '0'
   MIME::Base64: '0'
   Module::Runtime: '0'
   Moo: '1.003'
   Moo::Role: '0'
   POSIX: '0'
+  Package::Stash: '0.34'
   Scalar::Util: '0'
   Sub::Exporter: '0'
   Time::HiRes: '0'
@@ -55,4 +56,4 @@ requires:
 resources:
   bugtracker: https://github.com/elasticsearch/elasticsearch-perl/issues
   repository: git://github.com/elasticsearch/elasticsearch-perl.git
-version: '1.12'
+version: '1.16'
@@ -1,11 +1,11 @@
 
-# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v5.015.
+# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v5.020.
 use strict;
 use warnings;
 
 
 
-use ExtUtils::MakeMaker 6.30;
+use ExtUtils::MakeMaker ;
 
 
 
@@ -16,7 +16,8 @@ my %WriteMakefileArgs = (
     "Test::More" => "0.98"
   },
   "CONFIGURE_REQUIRES" => {
-    "ExtUtils::MakeMaker" => "6.30"
+    "ExtUtils::MakeMaker" => 0,
+    "Pod::Simple" => "3.28"
   },
   "DISTNAME" => "Search-Elasticsearch",
   "EXE_FILES" => [],
@@ -33,19 +34,19 @@ my %WriteMakefileArgs = (
     "Hijk" => "0.12",
     "IO::Select" => 0,
     "IO::Socket" => 0,
-    "IO::Socket::SSL" => 0,
     "IO::Uncompress::Inflate" => 0,
     "JSON::MaybeXS" => "1.002002",
     "JSON::PP" => 0,
     "LWP::UserAgent" => 0,
     "List::Util" => 0,
-    "Log::Any" => 0,
+    "Log::Any" => "0.15",
     "Log::Any::Adapter" => 0,
     "MIME::Base64" => 0,
     "Module::Runtime" => 0,
     "Moo" => "1.003",
     "Moo::Role" => 0,
     "POSIX" => 0,
+    "Package::Stash" => "0.34",
     "Scalar::Util" => 0,
     "Sub::Exporter" => 0,
     "Time::HiRes" => 0,
@@ -63,7 +64,7 @@ my %WriteMakefileArgs = (
     "Test::More" => "0.98",
     "lib" => 0
   },
-  "VERSION" => "1.12",
+  "VERSION" => "1.16",
   "test" => {
     "TESTS" => "t/*.t t/10_Basic/*.t t/20_Serializer/*.t t/30_Logger/*.t t/40_Transport/*.t t/50_Cxn_Pool/*.t t/60_Cxn/*.t t/70_Helper/*.t t/90_Client_Spec/*.t"
   }
@@ -81,13 +82,12 @@ my %FallbackPrereqs = (
   "Hijk" => "0.12",
   "IO::Select" => 0,
   "IO::Socket" => 0,
-  "IO::Socket::SSL" => 0,
   "IO::Uncompress::Inflate" => 0,
   "JSON::MaybeXS" => "1.002002",
   "JSON::PP" => 0,
   "LWP::UserAgent" => 0,
   "List::Util" => 0,
-  "Log::Any" => 0,
+  "Log::Any" => "0.15",
   "Log::Any::Adapter" => 0,
   "Log::Any::Adapter::Callback" => 0,
   "MIME::Base64" => 0,
@@ -95,6 +95,7 @@ my %FallbackPrereqs = (
   "Moo" => "1.003",
   "Moo::Role" => 0,
   "POSIX" => 0,
+  "Package::Stash" => "0.34",
   "Scalar::Util" => 0,
   "Sub::Exporter" => 0,
   "Test::Deep" => 0,
@@ -2,7 +2,7 @@ NAME
     Search::Elasticsearch - The official client for Elasticsearch
 
 VERSION
-    version 1.12
+    version 1.16
 
 SYNOPSIS
         use Search::Elasticsearch;
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Bulk;
-$Search::Elasticsearch::Bulk::VERSION = '1.12';
+$Search::Elasticsearch::Bulk::VERSION = '1.16';
 use Moo;
 with 'Search::Elasticsearch::Role::Bulk',
     'Search::Elasticsearch::Role::Is_Sync';
@@ -107,7 +107,7 @@ Search::Elasticsearch::Bulk - A helper module for the Bulk API and for reindexin
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 SYNOPSIS
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Client::0_90::Direct::Cluster;
-$Search::Elasticsearch::Client::0_90::Direct::Cluster::VERSION = '1.12';
+$Search::Elasticsearch::Client::0_90::Direct::Cluster::VERSION = '1.16';
 use Moo;
 with 'Search::Elasticsearch::Role::API::0_90';
 with 'Search::Elasticsearch::Role::Client::Direct';
@@ -17,7 +17,7 @@ Search::Elasticsearch::Client::0_90::Direct::Cluster - A client for running clus
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Client::0_90::Direct::Indices;
-$Search::Elasticsearch::Client::0_90::Direct::Indices::VERSION = '1.12';
+$Search::Elasticsearch::Client::0_90::Direct::Indices::VERSION = '1.16';
 use Moo;
 with 'Search::Elasticsearch::Role::API::0_90';
 with 'Search::Elasticsearch::Role::Client::Direct';
@@ -17,7 +17,7 @@ Search::Elasticsearch::Client::0_90::Direct::Indices - A client for running inde
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Client::0_90::Direct;
-$Search::Elasticsearch::Client::0_90::Direct::VERSION = '1.12';
+$Search::Elasticsearch::Client::0_90::Direct::VERSION = '1.16';
 use Moo;
 with 'Search::Elasticsearch::Role::API::0_90';
 with 'Search::Elasticsearch::Role::Client::Direct';
@@ -43,6 +43,15 @@ sub _index {
 }
 
 #===================================
+around 'clear_scroll' => sub {
+#===================================
+    my $orig = shift;
+    my ( $self, $params ) = parse_params(@_);
+    $params->{scroll_id}||=delete $params->{body};
+    $orig->( $self, $params );
+};
+
+#===================================
 sub _build__bulk_class {
 #===================================
     my $self = shift;
@@ -110,7 +119,7 @@ Search::Elasticsearch::Client::0_90::Direct - Thin client with full support for
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 SYNOPSIS
 
@@ -1050,7 +1059,6 @@ Query string parameters:
     C<routing>,
     C<search_from>,
     C<search_indices>,
-    C<search_query_hint>,
     C<search_scroll>,
     C<search_size>,
     C<search_source>,
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Client::Direct::Cat;
-$Search::Elasticsearch::Client::Direct::Cat::VERSION = '1.12';
+$Search::Elasticsearch::Client::Direct::Cat::VERSION = '1.16';
 use Moo;
 with 'Search::Elasticsearch::Role::API';
 with 'Search::Elasticsearch::Role::Client::Direct';
@@ -28,7 +28,7 @@ Search::Elasticsearch::Client::Direct::Cat - A client for running cat debugging
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -133,6 +133,26 @@ Query string parameters:
 See the L<cat count docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cat-count.html>
 for more information.
 
+=head2 C<fielddata()>
+
+    say $e->cat->fielddata(
+        fields => 'field' | \@fields    # optional
+    );
+
+Shows the amount of memory used by each of the specified `fields` (or all
+fields) loaded into fielddata.
+
+Query string parameters:
+    C<bytes>,
+    C<h>,
+    C<help>,
+    C<local>,
+    C<master_timeout>,
+    C<v>
+
+See the L<cat fielddata docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cat-fielddata.html>
+for more information.
+
 =head2 C<health()>
 
     say $e->cat->health();
@@ -175,7 +195,7 @@ for more information.
 
 =head2 C<master()>
 
-    say $e->cat->indices();
+    say $e->cat->master();
 
 Displays the master’s node ID, bound IP address, and node name.
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Client::Direct::Cluster;
-$Search::Elasticsearch::Client::Direct::Cluster::VERSION = '1.12';
+$Search::Elasticsearch::Client::Direct::Cluster::VERSION = '1.16';
 use Moo;
 with 'Search::Elasticsearch::Role::API';
 with 'Search::Elasticsearch::Role::Client::Direct';
@@ -29,7 +29,7 @@ Search::Elasticsearch::Client::Direct::Cluster - A client for running cluster-le
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -138,7 +138,6 @@ parameter.
 
 Query string parameters:
     C<flat_settings>,
-    <index_templates>,
     C<local>,
     C<master_timeout>
 
@@ -189,8 +188,8 @@ which changes should be made. For instance:
 Query string parameters:
     C<dry_run>,
     C<explain>,
-    C<filter_metadata>,
     C<master_timeout>,
+    C<metric>,
     C<timeout>
 
 See the L<reroute docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cluster-reroute.html>
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Client::Direct::Indices;
-$Search::Elasticsearch::Client::Direct::Indices::VERSION = '1.12';
+$Search::Elasticsearch::Client::Direct::Indices::VERSION = '1.16';
 use Moo;
 with 'Search::Elasticsearch::Role::API';
 with 'Search::Elasticsearch::Role::Client::Direct';
@@ -17,7 +17,7 @@ Search::Elasticsearch::Client::Direct::Indices - A client for running index-leve
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -51,6 +51,25 @@ Query string parameters:
 See the L<create index docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-create-index.html>
 for more information.
 
+=head2 C<get()>
+
+    $response = $e->indices->get(
+        index   => 'index'   | \@indices    # optional
+        feature => 'feature' | \@features   # optional
+    );
+
+Returns the aliases, settings, mappings, and warmers for the specified indices.
+The C<feature> parameter can be set to none or more of: C<_settings>, C<_mappings>,
+C<_warmers> and C<_aliases>.
+
+See the L<get index docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-get-index.html>.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<local>
+
 =head2 C<exists()>
 
     $bool = $e->indices->exists(
@@ -144,6 +163,7 @@ Query string parameters:
     C<id>,
     C<id_cache>,
     C<ignore_unavailable>,
+    C<query_cache>,
     C<recycler>
 
 See the L<clear_cache docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-clearcache.html>
@@ -183,7 +203,8 @@ Query string parameters:
     C<expand_wildcards>,
     C<force>,
     C<full>,
-    C<ignore_unavailable>
+    C<ignore_unavailable>,
+    C<wait_if_ongoing>
 
 See the L<flush index docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-flush.html>
 for more information.
@@ -202,7 +223,6 @@ Query string parameters:
     C<allow_no_indices>,
     C<expand_wildcards>,
     C<flush>,
-    C<force>,
     C<ignore_unavailable>,
     C<max_num_segments>,
     C<only_expunge_deletes>,
@@ -211,6 +231,41 @@ Query string parameters:
 See the L<optimize index docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-optimize.html>
 for more information.
 
+=head2 C<get_upgrade()>
+
+    $response = $e->indices->get_upgrade(
+        index => 'index' | \@indices    # optional
+    );
+
+The C<get_upgrade()> method returns information about which indices need to be
+upgraded, which can be done with the C<upgrade()> method.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<human>,
+    C<ignore_unavailable>
+
+See the L<upgrade docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-upgrade.html>
+for more information.
+
+=head2 C<upgrade()>
+
+    $response = $e->indices->upgrade(
+        index => 'index' | \@indices    # optional
+    );
+
+The C<upgrade()> method upgrades all segments in the specified indices to the latest format.
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<wait_for_completion>
+
+See the L<upgrade docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-upgrade.html>
+for more information.
+
 =head1 MAPPING METHODS
 
 =head2 C<put_mapping()>
@@ -359,7 +414,7 @@ for more information.
 =head2 C<get_aliases()>
 
     $result = $e->indices->get_aliases(
-        index   => 'index' | \@indices      # optional
+        index   => 'index' | \@indices,     # optional
         alias   => 'alias' | \@aliases      # optional
     );
 
@@ -376,7 +431,7 @@ for more information.
 =head2 C<put_alias()>
 
     $response = $e->indices->put_alias(
-        index => 'index' | \@indices        # optional,
+        index => 'index' | \@indices,       # required
         name  => 'alias',                   # required
 
         body  => { alias defn }             # optional
@@ -515,6 +570,7 @@ for more information.
 The C<put_template()> method is used to create or update index templates.
 
 Query string parameters:
+    C<create>,
     C<flat_settings>,
     C<master_timeout>,
     C<order>,
@@ -659,6 +715,7 @@ Allowed metrics are:
     C<indexing>,
     C<merge>,
     C<percolate>,
+    C<query_cache>,
     C<refresh>,
     C<search>,
     C<segments>,
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Client::Direct::Nodes;
-$Search::Elasticsearch::Client::Direct::Nodes::VERSION = '1.12';
+$Search::Elasticsearch::Client::Direct::Nodes::VERSION = '1.16';
 use Moo;
 with 'Search::Elasticsearch::Role::API';
 with 'Search::Elasticsearch::Role::Client::Direct';
@@ -17,7 +17,7 @@ Search::Elasticsearch::Client::Direct::Nodes - A client for running node-level r
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -109,6 +109,7 @@ Allowed index metrics are:
     C<indexing>,
     C<merge>,
     C<percolate>,
+    C<query_cache>,
     C<refresh>,
     C<search>,
     C<segments>,
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Client::Direct::Snapshot;
-$Search::Elasticsearch::Client::Direct::Snapshot::VERSION = '1.12';
+$Search::Elasticsearch::Client::Direct::Snapshot::VERSION = '1.16';
 use Moo;
 with 'Search::Elasticsearch::Role::API';
 with 'Search::Elasticsearch::Role::Client::Direct';
@@ -17,7 +17,7 @@ Search::Elasticsearch::Client::Direct::Snapshot - A client for managing snapshot
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -40,7 +40,8 @@ Create a repository for backups.
 
 Query string parameters:
     C<master_timeout>,
-    C<timeout>
+    C<timeout>,
+    C<verify>
 
 See the L<"snapshot/restore docs"|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-snapshot.html>
 for more information.
@@ -60,6 +61,21 @@ Query string parameters:
 See the L<"snapshot/restore docs"|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-snapshot.html>
 for more information.
 
+=head2 C<verify_repository()>
+
+    $e->snapshot->verify_repository(
+        repository  => 'repository' # required
+    );
+
+Verify existing repository.
+
+Query string parameters:
+    C<master_timeout>,
+    C<timeout>
+
+See the L<"snapshot/restore docs"|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-snapshot.html>
+for more information.
+
 =head2 C<delete_repository()>
 
     $e->snapshot->delete_repository(
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Client::Direct;
-$Search::Elasticsearch::Client::Direct::VERSION = '1.12';
+$Search::Elasticsearch::Client::Direct::VERSION = '1.16';
 use Moo;
 with 'Search::Elasticsearch::Role::API';
 with 'Search::Elasticsearch::Role::Client::Direct';
@@ -34,13 +34,15 @@ sub index {
     $self->_index( 'index', $params );
 }
 
+my $index_with_id = { %{ __PACKAGE__->api->{index} }, method => 'PUT' };
+
 #===================================
 sub _index {
 #===================================
     my ( $self, $name, $params ) = @_;
     my $defn = $self->api->{index};
-    unless ( defined $params->{id} and length $params->{id} ) {
-        $defn = { %$defn, method => 'POST' };
+    if ( defined $params->{id} and length $params->{id} ) {
+        $defn = $index_with_id;
     }
     $self->perform_request( { %$defn, name => $name }, $params );
 }
@@ -116,7 +118,7 @@ Search::Elasticsearch::Client::Direct - Thin client with full support for Elasti
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 SYNOPSIS
 
@@ -576,6 +578,8 @@ Query string parameters:
     C<retry_on_conflict>,
     C<routing>,
     C<script>,
+    C<script_id>,
+    C<scripted_upsert>,
     C<timeout>,
     C<timestamp>,
     C<ttl>,
@@ -600,6 +604,7 @@ offsets and payloads for the specified document, assuming that termvectors
 have been enabled.
 
 Query string parameters:
+    C<dfs>,
     C<field_statistics>,
     C<fields>,
     C<offsets>,
@@ -607,6 +612,7 @@ Query string parameters:
     C<payloads>,
     C<positions>,
     C<preference>,
+    C<realtime>,
     C<routing>,
     C<term_statistics>
 
@@ -827,6 +833,7 @@ Query string parameters:
     C<payloads>,
     C<positions>,
     C<preference>,
+    C<realtime>,
     C<routing>,
     C<term_statistics>
 
@@ -889,11 +896,11 @@ Query string parameters:
     C<fields>,
     C<from>,
     C<ignore_unavailable>,
-    C<indices_boost>,
     C<lenient>,
     C<lowercase_expanded_terms>,
     C<preference>,
     C<q>,
+    C<query_cache>,
     C<routing>,
     C<scroll>,
     C<search_type>,
@@ -906,6 +913,7 @@ Query string parameters:
     C<suggest_size>,
     C<suggest_text>,
     C<timeout>,
+    C<track_scores>,
     C<version>
 
 See the L<search reference|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-body.html>
@@ -913,6 +921,31 @@ for more information.
 
 Also see L<Search::Elasticsearch::Transport/send_get_body_as>.
 
+=head2 C<search_exists()>
+
+The C<search_exists()> method is a quick version of search which can be
+used to find out whether there are matching search results or not.
+It doesn't return any results itself.
+
+    $results = $e->search_exists(
+        index   => 'index' | \@indices,     # optional
+        type    => 'type'  | \@types,       # optional
+
+        body    => { search params }        # optional
+    );
+
+Query string parameters:
+    C<allow_no_indices>,
+    C<expand_wildcards>,
+    C<ignore_unavailable>,
+    C<min_score>,
+    C<preference>,
+    C<routing>,
+    C<source>
+
+See the L<search exists reference|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-exists.html>
+for more information.
+
 =head2 C<count()>
 
     $results = $e->count(
@@ -1167,7 +1200,10 @@ Query string parameters:
     C<allow_no_indices>,
     C<expand_wildcards>,
     C<ignore_unavailable>,
+    C<percolate_format>,
     C<percolate_index>,
+    C<percolate_preference>,
+    C<percolate_routing>,
     C<percolate_type>,
     C<preference>,
     C<routing>,
@@ -1315,7 +1351,6 @@ Query string parameters:
     C<routing>,
     C<search_from>,
     C<search_indices>,
-    C<search_query_hint>,
     C<search_scroll>,
     C<search_size>,
     C<search_source>,
@@ -1326,6 +1361,125 @@ Query string parameters:
 See the L<mlt docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-more-like-this.html>
 for more information.
 
+=HEAD1 INDEXED SCRIPT METHODS
+
+If dynamic scripting is enabled, Elasticsearch allows you to store scripts in an internal index known as
+C<.scripts> and reference them by id. The methods to manage indexed scripts are as follows:
+
+=head2 C<put_script()>
+
+    $result  = $e->put_script(
+        lang => 'lang',     # required
+        id   => 'id',       # required
+        body => { script }  # required
+    );
+
+The C<put_script()> method is used to store a script in the C<.scripts> index. For instance:
+
+    $result  = $e->put_scripts(
+        lang => 'groovy',
+        id   => 'hello_world',
+        body => {
+          script => q(return "hello world");
+        }
+    );
+
+Query string parameters:
+    C<op_type>,
+    C<version>,
+    C<version_type>
+
+See the L<indexed scripts docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-scripting.html#_indexed_scripts> for more.
+
+=head2 C<get_script()>
+
+    $script = $e->get_script(
+        lang => 'lang',     # required
+        id   => 'id',       # required
+    );
+
+Retrieve the indexed script from the C<.scripts> index.
+
+Query string parameters:
+    C<version>,
+    C<version_type>
+
+See the L<indexed scripts docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-scripting.html#_indexed_scripts> for more.
+
+=head2 C<delete_script()>
+
+    $script = $e->delete_script(
+        lang => 'lang',     # required
+        id   => 'id',       # required
+    );
+
+Delete the indexed script from the C<.scripts> index.
+
+Query string parameters:
+    C<version>,
+    C<version_type>
+
+See the L<indexed scripts docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-scripting.html#_indexed_scripts> for more.
+
+=HEAD1 INDEXED SEARCH TEMPLATE METHODS
+
+Mustache templates can be used to create search requests.  These templates can
+be stored in the C<.scripts> index and retrieved by ID. The methods to
+manage indexed scripts are as follows:
+
+=head2 C<put_template()>
+
+    $result  = $e->put_template(
+        id   => 'id',                       # required
+        body => { template } || "template"  # required
+    );
+
+The C<put_template()> method is used to store a template in the C<.scripts> index.
+For instance:
+
+    $result  = $e->put_template(
+        id   => 'hello_world',
+        body => {
+          template => {
+            query => {
+              match => {
+                title => "hello world"
+              }
+            }
+          }
+      }
+    );
+
+Query string parameters: None
+
+See the L<indexed search template docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-template.html#_pre_registered_template> for more.
+
+=head2 C<get_template()>
+
+    $script = $e->get_template(
+        id   => 'id',       # required
+    );
+
+Retrieve the indexed template from the C<.scripts> index.
+
+Query string parameters:
+    C<version>,
+    C<version_type>
+
+See the L<indexed search template docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-template.html#_pre_registered_template> for more.
+
+=head2 C<delete_template()>
+
+    $script = $e->delete_template(
+        id   => 'id',       # required
+    );
+
+Delete the indexed template from the C<.scripts> index.
+
+Query string parameters: None
+
+See the L<indexed search template docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-template.html#_pre_registered_template> for more.
+
 =head1 BENCHMARK METHODS
 
 =head2 C<benchmark()>
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Cxn::Factory;
-$Search::Elasticsearch::Cxn::Factory::VERSION = '1.12';
+$Search::Elasticsearch::Cxn::Factory::VERSION = '1.16';
 use Moo;
 use Search::Elasticsearch::Util qw(parse_params load_plugin);
 use namespace::clean;
@@ -48,13 +48,13 @@ Search::Elasticsearch::Cxn::Factory - Used by CxnPools to create new Cxn instanc
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
 This class is used by the L<Search::Elasticsearch::Role::CxnPool> implementations
 to create new L<Search::Elasticsearch::Role::Cxn>-based instances. It holds on
-to all the configuration options passed to L<Elasticsearhch/new()> so
+to all the configuration options passed to L<Elasticsearch/new()> so
 that new Cxns can use them.
 
 It contains no user serviceable parts.
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Cxn::HTTPTiny;
-$Search::Elasticsearch::Cxn::HTTPTiny::VERSION = '1.12';
+$Search::Elasticsearch::Cxn::HTTPTiny::VERSION = '1.16';
 use Moo;
 with 'Search::Elasticsearch::Role::Cxn::HTTP',
     'Search::Elasticsearch::Role::Cxn',
@@ -58,10 +58,8 @@ sub _build_handle {
 #===================================
     my $self = shift;
     my %args = ( default_headers => $self->default_headers );
-    if ( $self->is_https ) {
-        require IO::Socket::SSL;
-        $args{SSL_options}{SSL_verify_mode}
-            = IO::Socket::SSL::SSL_VERIFY_NONE();
+    if ( $self->is_https && $self->has_ssl_options ) {
+        $args{SSL_options} = $self->ssl_options;
     }
 
     return HTTP::Tiny->new( %args, %{ $self->handle_args } );
@@ -83,7 +81,7 @@ Search::Elasticsearch::Cxn::HTTPTiny - A Cxn implementation which uses HTTP::Tin
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -131,6 +129,51 @@ From L<Search::Elasticsearch::Role::Cxn>
 
 =back
 
+=head1 SSL/TLS
+
+L<Search::Elasticsearch::Cxn::HTTPTiny> uses L<IO::Socket::SSL> to support
+HTTPS.  By default, no validation of the remote host is performed.
+
+This behaviour can be changed by passing the C<ssl_options> parameter
+with any options accepted by L<IO::Socket::SSL>. For instance, to check
+that the remote host has a trusted certificate, and to avoid man-in-the-middle
+attacks, you could do the following:
+
+    use Search::Elasticsearch;
+    use IO::Socket::SSL;
+
+    my $es = Search::Elasticsearch->new(
+        nodes => [
+            "https://node1.mydomain.com:9200",
+            "https://node2.mydomain.com:9200",
+        ],
+        ssl_options => {
+            SSL_verify_mode     => SSL_VERIFY_PEER,
+            SSL_ca_file         => '/path/to/cacert.pem',
+            SSL_verifycn_scheme => 'http',
+        }
+    );
+
+If you want your client to present its own certificate to the remote
+server, then use:
+
+    use Search::Elasticsearch;
+    use IO::Socket::SSL;
+
+    my $es = Search::Elasticsearch->new(
+        nodes => [
+            "https://node1.mydomain.com:9200",
+            "https://node2.mydomain.com:9200",
+        ],
+        ssl_options => {
+            SSL_verify_mode     => SSL_VERIFY_PEER,
+            SSL_ca_file         => '/path/to/cacert.pem',
+            SSL_verifycn_scheme => 'http',
+            SSL_cert_file       => '/path/to/client.pem',
+            SSL_key_file        => '/path/to/client.pem',
+        }
+    );
+
 =head1 METHODS
 
 =head2 C<perform_request()>
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Cxn::Hijk;
-$Search::Elasticsearch::Cxn::Hijk::VERSION = '1.12';
+$Search::Elasticsearch::Cxn::Hijk::VERSION = '1.16';
 use Moo;
 with 'Search::Elasticsearch::Role::Cxn::HTTP',
     'Search::Elasticsearch::Role::Cxn',
@@ -10,7 +10,7 @@ use Try::Tiny;
 use namespace::clean;
 
 has 'connect_timeout' => ( is => 'ro', default => 2 );
-has '_socket_cache' => ( is => 'ro', default => sub { {} } );
+has '_socket_cache' => ( is => 'rw', default => sub { {} } );
 
 my $Cxn_Error = qr/ Connection.(?:timed.out|re(?:set|fused))
                        | connect:.timeout
@@ -74,6 +74,12 @@ sub perform_request {
 }
 
 #===================================
+sub clear_handle {
+#===================================
+    my $self = shift;
+    $self->_socket_cache( {} );
+}
+#===================================
 sub error_from_text {
 #===================================
     local $_ = $_[2];
@@ -108,7 +114,7 @@ Search::Elasticsearch::Cxn::Hijk - A Cxn implementation which uses Hijk
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -163,6 +169,10 @@ From L<Search::Elasticsearch::Role::Cxn>
 
 =back
 
+=head1 SSL/TLS
+
+L<Search::Elasticsearch::Cxn::Hijk> does not support HTTPS.
+
 =head1 METHODS
 
 =head2 C<perform_request()>
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Cxn::LWP;
-$Search::Elasticsearch::Cxn::LWP::VERSION = '1.12';
+$Search::Elasticsearch::Cxn::LWP::VERSION = '1.16';
 use Moo;
 with 'Search::Elasticsearch::Role::Cxn::HTTP',
     'Search::Elasticsearch::Role::Cxn',
@@ -70,7 +70,10 @@ sub _build_handle {
         parse_head => 0
     );
     if ( $self->is_https ) {
-        $args{ssl_opts} = { verify_hostname => 0 };
+        $args{ssl_opts}
+            = $self->has_ssl_options
+            ? $self->ssl_options
+            : { verify_hostname => 0 };
     }
     return LWP::UserAgent->new( %args, %{ $self->handle_args } );
 }
@@ -91,7 +94,7 @@ Search::Elasticsearch::Cxn::LWP - A Cxn implementation which uses LWP
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -138,6 +141,53 @@ From L<Search::Elasticsearch::Role::Cxn>
 
 =back
 
+=head1 SSL/TLS
+
+L<Search::Elasticsearch::Cxn::LWP> uses L<IO::Socket::SSL> to support
+HTTPS.  By default, no validation of the remote host is performed.
+
+This behaviour can be changed by passing the C<ssl_options> parameter
+with any options accepted by L<IO::Socket::SSL>. For instance, to check
+that the remote host has a trusted certificate, and to avoid man-in-the-middle
+attacks, you could do the following:
+
+    use Search::Elasticsearch;
+    use IO::Socket::SSL;
+
+    my $es = Search::Elasticsearch->new(
+        cxn   => 'LWP',
+        nodes => [
+            "https://node1.mydomain.com:9200",
+            "https://node2.mydomain.com:9200",
+        ],
+        ssl_options => {
+            SSL_verify_mode     => SSL_VERIFY_PEER,
+            SSL_ca_file         => '/path/to/cacert.pem',
+            SSL_verifycn_scheme => 'http',
+        }
+    );
+
+If you want your client to present its own certificate to the remote
+server, then use:
+
+    use Search::Elasticsearch;
+    use IO::Socket::SSL;
+
+    my $es = Search::Elasticsearch->new(
+        cxn   => 'LWP',
+        nodes => [
+            "https://node1.mydomain.com:9200",
+            "https://node2.mydomain.com:9200",
+        ],
+        ssl_options => {
+            SSL_verify_mode     => SSL_VERIFY_PEER,
+            SSL_ca_file         => '/path/to/cacert.pem',
+            SSL_verifycn_scheme => 'http',
+            SSL_cert_file       => '/path/to/client.pem',
+            SSL_key_file        => '/path/to/client.pem',
+        }
+    );
+
 =head1 METHODS
 
 =head2 C<perform_request()>
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::CxnPool::Sniff;
-$Search::Elasticsearch::CxnPool::Sniff::VERSION = '1.12';
+$Search::Elasticsearch::CxnPool::Sniff::VERSION = '1.16';
 use Moo;
 with 'Search::Elasticsearch::Role::CxnPool::Sniff',
     'Search::Elasticsearch::Role::Is_Sync';
@@ -81,7 +81,7 @@ Search::Elasticsearch::CxnPool::Sniff - A CxnPool for connecting to a local clus
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 SYNOPSIS
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::CxnPool::Static::NoPing;
-$Search::Elasticsearch::CxnPool::Static::NoPing::VERSION = '1.12';
+$Search::Elasticsearch::CxnPool::Static::NoPing::VERSION = '1.16';
 use Moo;
 with 'Search::Elasticsearch::Role::CxnPool::Static::NoPing',
     'Search::Elasticsearch::Role::Is_Sync';
@@ -18,7 +18,7 @@ Search::Elasticsearch::CxnPool::Static::NoPing - A CxnPool for connecting to a r
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 SYNOPSIS
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::CxnPool::Static;
-$Search::Elasticsearch::CxnPool::Static::VERSION = '1.12';
+$Search::Elasticsearch::CxnPool::Static::VERSION = '1.16';
 use Moo;
 with 'Search::Elasticsearch::Role::CxnPool::Static',
     'Search::Elasticsearch::Role::Is_Sync';
@@ -50,7 +50,7 @@ Search::Elasticsearch::CxnPool::Static - A CxnPool for connecting to a remote cl
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 SYNOPSIS
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Error;
-$Search::Elasticsearch::Error::VERSION = '1.12';
+$Search::Elasticsearch::Error::VERSION = '1.16';
 use Moo;
 
 our $DEBUG = 0;
@@ -158,7 +158,7 @@ Search::Elasticsearch::Error - Errors thrown by Search::Elasticsearch
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -1,11 +1,11 @@
 package Search::Elasticsearch::Logger::LogAny;
-$Search::Elasticsearch::Logger::LogAny::VERSION = '1.12';
+$Search::Elasticsearch::Logger::LogAny::VERSION = '1.16';
 use Moo;
 with 'Search::Elasticsearch::Role::Logger';
 use Search::Elasticsearch::Util qw(parse_params to_list);
 use namespace::clean;
 
-use Log::Any();
+use Log::Any 0.15 ();
 use Log::Any::Adapter();
 
 #===================================
@@ -44,7 +44,7 @@ Search::Elasticsearch::Logger::LogAny - A Log::Any-based Logger implementation
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::API::0_90;
-$Search::Elasticsearch::Role::API::0_90::VERSION = '1.12';
+$Search::Elasticsearch::Role::API::0_90::VERSION = '1.16';
 use Moo::Role;
 
 use Search::Elasticsearch::Util qw(throw);
@@ -249,7 +249,7 @@ sub api {
             "min_word_len",           "mlt_fields",
             "percent_terms_to_match", "routing",
             "search_from",            "search_indices",
-            "search_query_hint",      "search_scroll",
+            "search_scroll",
             "search_size",            "search_source",
             "search_type",            "search_types",
             "stop_words",
@@ -310,21 +310,20 @@ sub api {
             [ {}, "_search" ],
         ],
         qs => [
-            "_source",         "_source_exclude",
-            "_source_include", "analyze_wildcard",
-            "analyzer",        "default_operator",
-            "df",              "explain",
-            "fields",          "from",
-            "ignore_indices",  "indices_boost",
-            "lenient",         "lowercase_expanded_terms",
-            "preference",      "q",
-            "routing",         "scroll",
-            "search_type",     "size",
-            "sort",            "source",
-            "stats",           "suggest_field",
-            "suggest_mode",    "suggest_size",
-            "suggest_text",    "timeout",
-            "version",
+            "_source",                  "_source_exclude",
+            "_source_include",          "analyze_wildcard",
+            "analyzer",                 "default_operator",
+            "df",                       "explain",
+            "fields",                   "from",
+            "ignore_indices",           "lenient",
+            "lowercase_expanded_terms", "preference",
+            "q",                        "routing",
+            "scroll",                   "search_type",
+            "size",                     "sort",
+            "source",                   "stats",
+            "suggest_field",            "suggest_mode",
+            "suggest_size",             "suggest_text",
+            "timeout",                  "version",
         ],
     },
 
@@ -953,7 +952,7 @@ Search::Elasticsearch::Role::API::0_90 - This class contains the spec for the El
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::API;
-$Search::Elasticsearch::Role::API::VERSION = '1.12';
+$Search::Elasticsearch::Role::API::VERSION = '1.16';
 use Moo::Role;
 
 use Search::Elasticsearch::Util qw(throw);
@@ -159,6 +159,22 @@ sub api {
         ],
     },
 
+    'delete_script' => {
+        doc    => "modules-scripting",
+        method => "DELETE",
+        parts  => { id => { required => 1 }, lang => { required => 1 } },
+        paths => [ [ { id => 2, lang => 1 }, "_scripts", "{lang}", "{id}" ] ],
+        qs => [ "version", "version_type" ],
+    },
+
+    'delete_template' => {
+        doc    => "search-template",
+        method => "DELETE",
+        parts  => { id => {} },
+        paths  => [ [ { id => 2 }, "_search", "template", "{id}" ] ],
+        qs     => [],
+    },
+
     'exists' => {
         doc    => "docs-get",
         method => "HEAD",
@@ -223,6 +239,13 @@ sub api {
         ],
     },
 
+    'get_script' => {
+        doc   => "modules-scripting",
+        parts => { id => { required => 1 }, lang => { required => 1 } },
+        paths => [ [ { id => 2, lang => 1 }, "_scripts", "{lang}", "{id}" ] ],
+        qs => [ "version", "version_type" ],
+    },
+
     'get_source' => {
         doc   => "docs-get",
         parts => {
@@ -244,6 +267,13 @@ sub api {
         ],
     },
 
+    'get_template' => {
+        doc   => "search-template",
+        parts => { id => { required => 1 } },
+        paths => [ [ { id => 2 }, "_search", "template", "{id}" ] ],
+        qs => [ "version", "version_type" ],
+    },
+
     'index' => {
         body   => { required => 1 },
         doc    => "docs-index_",
@@ -318,10 +348,9 @@ sub api {
             "min_word_length",        "mlt_fields",
             "percent_terms_to_match", "routing",
             "search_from",            "search_indices",
-            "search_query_hint",      "search_scroll",
-            "search_size",            "search_source",
-            "search_type",            "search_types",
-            "stop_words",
+            "search_scroll",          "search_size",
+            "search_source",          "search_type",
+            "search_types",           "stop_words",
         ],
     },
 
@@ -371,7 +400,8 @@ sub api {
             "ids",              "offsets",
             "parent",           "payloads",
             "positions",        "preference",
-            "routing",          "term_statistics",
+            "realtime",         "routing",
+            "term_statistics",
         ],
     },
 
@@ -392,10 +422,11 @@ sub api {
         ],
         qs => [
             "allow_no_indices",   "expand_wildcards",
-            "ignore_unavailable", "percolate_index",
-            "percolate_type",     "preference",
-            "routing",            "version",
-            "version_type",
+            "ignore_unavailable", "percolate_format",
+            "percolate_index",    "percolate_preference",
+            "percolate_routing",  "percolate_type",
+            "preference",         "routing",
+            "version",            "version_type",
         ],
     },
 
@@ -407,6 +438,24 @@ sub api {
         qs     => []
     },
 
+    'put_script' => {
+        body   => { required => 1 },
+        doc    => "modules-scripting",
+        method => "PUT",
+        parts => { id => { required => 1 }, lang => { required => 1 } },
+        paths => [ [ { id => 2, lang => 1 }, "_scripts", "{lang}", "{id}" ] ],
+        qs => [ "op_type", "version", "version_type" ],
+    },
+
+    'put_template' => {
+        body   => { required => 1 },
+        doc    => "search-template",
+        method => "PUT",
+        parts => { id => { required => 1 } },
+        paths => [ [ { id => 2 }, "_search", "template", "{id}" ] ],
+        qs => [],
+    },
+
     'scroll' => {
         body  => {},
         doc   => "search-request-scroll",
@@ -429,22 +478,44 @@ sub api {
             [ {}, "_search" ],
         ],
         qs => [
-            "_source",            "_source_exclude",
-            "_source_include",    "allow_no_indices",
-            "analyze_wildcard",   "analyzer",
-            "default_operator",   "df",
-            "expand_wildcards",   "explain",
-            "fields",             "from",
-            "ignore_unavailable", "indices_boost",
-            "lenient",            "lowercase_expanded_terms",
-            "preference",         "q",
-            "routing",            "scroll",
-            "search_type",        "size",
-            "sort",               "source",
-            "stats",              "suggest_field",
-            "suggest_mode",       "suggest_size",
-            "suggest_text",       "timeout",
-            "version",
+            "_source",                  "_source_exclude",
+            "_source_include",          "allow_no_indices",
+            "analyze_wildcard",         "analyzer",
+            "default_operator",         "df",
+            "expand_wildcards",         "explain",
+            "fields",                   "from",
+            "ignore_unavailable",       "lenient",
+            "lowercase_expanded_terms", "preference",
+            "q",                        "query_cache",
+            "routing",                  "scroll",
+            "search_type",              "size",
+            "sort",                     "source",
+            "stats",                    "suggest_field",
+            "suggest_mode",             "suggest_size",
+            "suggest_text",             "timeout",
+            "track_scores",             "version",
+        ],
+    },
+
+    'search_exists' => {
+        body   => {},
+        doc    => "exists",
+        method => "POST",
+        parts  => { index => { multi => 1 }, type => { multi => 1 } },
+        paths  => [
+            [   { index => 0, type => 1 }, "{index}",
+                "{type}", "_search",
+                "exists",
+            ],
+            [ { type => 1 }, "_all", "{type}", "_search", "exists" ],
+            [ { index => 0 }, "{index}", "_search", "exists" ],
+            [ {}, "_search", "exists" ],
+        ],
+        qs => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "min_score",
+            "preference",         "routing",
+            "source",
         ],
     },
 
@@ -516,10 +587,11 @@ sub api {
             ],
         ],
         qs => [
-            "field_statistics", "fields",
-            "offsets",          "parent",
-            "payloads",         "positions",
-            "preference",       "routing",
+            "dfs",       "field_statistics",
+            "fields",    "offsets",
+            "parent",    "payloads",
+            "positions", "preference",
+            "realtime",  "routing",
             "term_statistics",
         ],
     },
@@ -543,7 +615,8 @@ sub api {
             "lang",              "parent",
             "refresh",           "replication",
             "retry_on_conflict", "routing",
-            "script",            "timeout",
+            "script",            "script_id",
+            "scripted_upsert",   "timeout",
             "timestamp",         "ttl",
             "version",           "version_type",
         ],
@@ -579,6 +652,16 @@ sub api {
         qs => [ "h", "help", "local", "master_timeout", "v" ],
     },
 
+    'cat.fielddata' => {
+        doc   => "cat-fielddata",
+        parts => { fields => { multi => 1 } },
+        paths => [
+            [ { fields => 2 }, "_cat", "fielddata", "{fields}" ],
+            [ {}, "_cat", "fielddata" ],
+        ],
+        qs => [ "bytes", "h", "help", "local", "master_timeout", "v" ],
+    },
+
     'cat.health' => {
         doc   => "cat-health",
         parts => {},
@@ -702,11 +785,7 @@ sub api {
         method => "POST",
         parts  => {},
         paths  => [ [ {}, "_cluster", "reroute" ] ],
-        qs     => [
-            "dry_run",         "explain",
-            "filter_metadata", "master_timeout",
-            "timeout",
-        ],
+        qs => [ "dry_run", "explain", "master_timeout", "metric", "timeout" ],
     },
 
     'cluster.state' => {
@@ -760,7 +839,7 @@ sub api {
             "filter",           "filter_cache",
             "filter_keys",      "id",
             "id_cache",         "ignore_unavailable",
-            "recycler",
+            "query_cache",      "recycler",
         ],
     },
 
@@ -788,8 +867,8 @@ sub api {
     'indices.delete' => {
         doc    => "indices-delete-index",
         method => "DELETE",
-        parts  => { index => { multi => 1 } },
-        paths  => [ [ { index => 0 }, "{index}" ] ],
+        parts  => { index => { multi => 1, required => 1 } },
+        paths => [ [ { index => 0 }, "{index}" ] ],
         qs => [ "master_timeout", "timeout" ],
     },
 
@@ -839,7 +918,7 @@ sub api {
     },
 
     'indices.exists' => {
-        doc    => "indices-get-settings",
+        doc    => "indices-exists",
         method => "HEAD",
         parts  => { index => { multi => 1, required => 1 } },
         paths => [ [ { index => 0 }, "{index}" ] ],
@@ -855,8 +934,8 @@ sub api {
         parts  => { index => { multi => 1 }, name => { multi => 1 } },
         paths  => [
             [ { index => 0, name => 2 }, "{index}", "_alias", "{name}" ],
-            [ { name  => 1 }, "_alias",  "{name}" ],
             [ { index => 0 }, "{index}", "_alias" ],
+            [ { name  => 1 }, "_alias",  "{name}" ],
         ],
         qs => [
             "allow_no_indices",   "expand_wildcards",
@@ -893,9 +972,25 @@ sub api {
         paths =>
             [ [ { index => 0 }, "{index}", "_flush" ], [ {}, "_flush" ] ],
         qs => [
-            "allow_no_indices", "expand_wildcards",
-            "force",            "full",
-            "ignore_unavailable",
+            "allow_no_indices",   "expand_wildcards",
+            "force",              "full",
+            "ignore_unavailable", "wait_if_ongoing",
+        ],
+    },
+
+    'indices.get' => {
+        doc   => "indices-get-index",
+        parts => {
+            feature => { multi => 1 },
+            index   => { multi => 1, required => 1 }
+        },
+        paths => [
+            [ { feature => 1, index => 0 }, "{index}", "{feature}" ],
+            [ { index => 0 }, "{index}" ],
+        ],
+        qs => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "local",
         ],
     },
 
@@ -904,8 +999,8 @@ sub api {
         parts => { index => { multi => 1 }, name => { multi => 1 } },
         paths => [
             [ { index => 0, name => 2 }, "{index}", "_alias", "{name}" ],
-            [ { name  => 1 }, "_alias",  "{name}" ],
             [ { index => 0 }, "{index}", "_alias" ],
+            [ { name  => 1 }, "_alias",  "{name}" ],
             [ {}, "_alias" ],
         ],
         qs => [
@@ -919,8 +1014,8 @@ sub api {
         parts => { index => { multi => 1 }, name => { multi => 1 } },
         paths => [
             [ { index => 0, name => 2 }, "{index}", "_aliases", "{name}" ],
-            [ { name  => 1 }, "_aliases", "{name}" ],
             [ { index => 0 }, "{index}",  "_aliases" ],
+            [ { name  => 1 }, "_aliases", "{name}" ],
             [ {}, "_aliases" ],
         ],
         qs => [ "local", "timeout" ],
@@ -960,8 +1055,8 @@ sub api {
         parts => { index => { multi => 1 }, type => { multi => 1 } },
         paths => [
             [ { index => 0, type => 2 }, "{index}", "_mapping", "{type}" ],
-            [ { type  => 1 }, "_mapping", "{type}" ],
             [ { index => 0 }, "{index}",  "_mapping" ],
+            [ { type  => 1 }, "_mapping", "{type}" ],
             [ {}, "_mapping" ],
         ],
         qs => [
@@ -975,8 +1070,8 @@ sub api {
         parts => { index => { multi => 1 }, name => { multi => 1 } },
         paths => [
             [ { index => 0, name => 2 }, "{index}", "_settings", "{name}" ],
-            [ { name  => 1 }, "_settings", "{name}" ],
             [ { index => 0 }, "{index}",   "_settings" ],
+            [ { name  => 1 }, "_settings", "{name}" ],
             [ {}, "_settings" ],
         ],
         qs => [
@@ -994,6 +1089,17 @@ sub api {
         qs => [ "flat_settings", "local" ],
     },
 
+    'indices.get_upgrade' => {
+        doc   => "indices-upgrade",
+        parts => { index => { multi => 1 } },
+        paths =>
+            [ [ { index => 0 }, "{index}", "_upgrade" ], [ {}, "_upgrade" ] ],
+        qs => [
+            "allow_no_indices", "expand_wildcards",
+            "human",            "ignore_unavailable",
+        ],
+    },
+
     'indices.get_warmer' => {
         doc   => "indices-warmers",
         parts => {
@@ -1010,8 +1116,8 @@ sub api {
                 "{name}"
             ],
             [ { index => 0, name => 2 }, "{index}", "_warmer", "{name}" ],
-            [ { name  => 1 }, "_warmer", "{name}" ],
             [ { index => 0 }, "{index}", "_warmer" ],
+            [ { name  => 1 }, "_warmer", "{name}" ],
             [ {}, "_warmer" ],
         ],
         qs => [
@@ -1052,11 +1158,12 @@ sub api {
         body   => {},
         doc    => "indices-aliases",
         method => "PUT",
-        parts  => { index => { multi => 1 }, name => { required => 1 } },
-        paths  => [
-            [ { index => 0, name => 2 }, "{index}", "_alias", "{name}" ],
-            [ { name => 1 }, "_alias", "{name}" ],
-        ],
+        parts  => {
+            index => { multi    => 1, required => 1 },
+            name  => { required => 1 }
+        },
+        paths =>
+            [ [ { index => 0, name => 2 }, "{index}", "_alias", "{name}" ] ],
         qs => [ "master_timeout", "timeout" ],
     },
 
@@ -1098,7 +1205,11 @@ sub api {
         method => "PUT",
         parts => { name => { required => 1 } },
         paths => [ [ { name => 1 }, "_template", "{name}" ] ],
-        qs => [ "flat_settings", "master_timeout", "order", "timeout" ],
+        qs => [
+            "create",         "flat_settings",
+            "master_timeout", "order",
+            "timeout"
+        ],
     },
 
     'indices.put_warmer' => {
@@ -1179,8 +1290,8 @@ sub api {
         parts => { index => { multi => 1 }, metric => { multi => 1 } },
         paths => [
             [ { index => 0, metric => 2 }, "{index}", "_stats", "{metric}" ],
-            [ { metric => 1 }, "_stats",  "{metric}" ],
             [ { index  => 0 }, "{index}", "_stats" ],
+            [ { metric => 1 }, "_stats",  "{metric}" ],
             [ {}, "_stats" ],
         ],
         qs => [
@@ -1212,6 +1323,18 @@ sub api {
         qs => [ "master_timeout", "timeout" ],
     },
 
+    'indices.upgrade' => {
+        doc    => "indices-upgrade",
+        method => "POST",
+        parts  => { index => { multi => 1 } },
+        paths =>
+            [ [ { index => 0 }, "{index}", "_upgrade" ], [ {}, "_upgrade" ] ],
+        qs => [
+            "allow_no_indices",   "expand_wildcards",
+            "ignore_unavailable", "wait_for_completion",
+        ],
+    },
+
     'indices.validate_query' => {
         body  => {},
         doc   => "search-validate",
@@ -1330,7 +1453,7 @@ sub api {
         method => "PUT",
         parts => { repository => { required => 1 } },
         paths => [ [ { repository => 1 }, "_snapshot", "{repository}" ] ],
-        qs => [ "master_timeout", "timeout" ],
+        qs => [ "master_timeout", "timeout", "verify" ],
     },
 
     'snapshot.delete' => {
@@ -1415,6 +1538,16 @@ sub api {
         qs => ["master_timeout"],
     },
 
+    'snapshot.verify_repository' => {
+        doc    => "modules-snapshots",
+        method => "POST",
+        parts  => { repository => { required => 1 } },
+        paths  => [
+            [ { repository => 1 }, "_snapshot", "{repository}", "_verify" ],
+        ],
+        qs => [ "master_timeout", "timeout" ],
+    },
+
 #=== AUTOGEN - END ===
 
 );
@@ -1435,7 +1568,7 @@ Search::Elasticsearch::Role::API - This class contains the spec for the Elastics
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::Bulk;
-$Search::Elasticsearch::Role::Bulk::VERSION = '1.12';
+$Search::Elasticsearch::Role::Bulk::VERSION = '1.16';
 use Moo::Role;
 requires 'add_action', 'flush';
 
@@ -255,7 +255,7 @@ Search::Elasticsearch::Role::Bulk - Provides common functionality to L<Elasticse
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 AUTHOR
 
@@ -1,9 +1,10 @@
 package Search::Elasticsearch::Role::Client::Direct;
-$Search::Elasticsearch::Role::Client::Direct::VERSION = '1.12';
+$Search::Elasticsearch::Role::Client::Direct::VERSION = '1.16';
 use Moo::Role;
 with 'Search::Elasticsearch::Role::Client';
 use Search::Elasticsearch::Util::API::Path qw(path_handler);
 use Try::Tiny;
+use Package::Stash 0.34 ();
 use namespace::clean;
 
 #===================================
@@ -119,7 +120,7 @@ Search::Elasticsearch::Role::Client::Direct - Request parsing for Direct clients
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::Client;
-$Search::Elasticsearch::Role::Client::VERSION = '1.12';
+$Search::Elasticsearch::Role::Client::VERSION = '1.16';
 use Moo::Role;
 use namespace::clean;
 
@@ -28,7 +28,7 @@ Search::Elasticsearch::Role::Client - Provides common functionality for Client i
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::Cxn::HTTP;
-$Search::Elasticsearch::Role::Cxn::HTTP::VERSION = '1.12';
+$Search::Elasticsearch::Role::Cxn::HTTP::VERSION = '1.16';
 use Moo::Role;
 
 use URI();
@@ -11,7 +11,9 @@ has 'is_https'           => ( is => 'ro' );
 has 'userinfo'           => ( is => 'ro' );
 has 'max_content_length' => ( is => 'ro' );
 has 'default_headers'    => ( is => 'ro' );
-has 'handle'             => ( is => 'lazy' );
+has 'ssl_options'        => ( is => 'ro', predicate => 'has_ssl_options' );
+has 'handle'             => ( is => 'lazy', clearer => 1 );
+has '_pid'               => ( is => 'rw', default => $$ );
 
 #===================================
 sub protocol     {'http'}
@@ -70,7 +72,7 @@ sub BUILDARGS {
     }
 
     $params->{scheme}          = $scheme;
-    $params->{is_http}         = $scheme eq 'https';
+    $params->{is_https}        = $scheme eq 'https';
     $params->{host}            = $host;
     $params->{port}            = $port;
     $params->{path}            = $path;
@@ -109,6 +111,16 @@ before 'perform_request' => sub {
 };
 
 #===================================
+before 'handle' => sub {
+#===================================
+    my $self = shift;
+    if ( $$ != $self->_pid ) {
+        $self->clear_handle;
+        $self->_pid($$);
+    }
+};
+
+#===================================
 around 'process_response' => sub {
 #===================================
     my ( $orig, $self, $params, $code, $msg, $body, $headers ) = @_;
@@ -155,7 +167,7 @@ Search::Elasticsearch::Role::Cxn::HTTP - Provides common functionality to HTTP C
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -205,6 +217,16 @@ C<userinfo> and C<use_https>:
         nodes       => [ 'search1', 'search2' ]
     )
 
+=head2 C<ssl_options>
+
+By default, all backends that support HTTPS disable verification of
+the host they are connecting to.  Use C<ssl_options> to configure
+the type of verification that you would like the client to perform,
+or to configure the client to present its own certificate.
+
+The values accepted by C<ssl_options> depend on the C<Cxn> class.  See the
+documentation for the C<Cxn> class that you are using.
+
 =head2 C<max_content_length>
 
 By default, Elasticsearch nodes accept a maximum post body of 100MB or
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::Cxn;
-$Search::Elasticsearch::Role::Cxn::VERSION = '1.12';
+$Search::Elasticsearch::Role::Cxn::VERSION = '1.16';
 use Moo::Role;
 use Search::Elasticsearch::Util qw(throw);
 use List::Util qw(min);
@@ -137,7 +137,7 @@ sub process_response {
 
     my $error_type = $Code_To_Error{$code};
     unless ($error_type) {
-        if ( defined $body ) {
+        if ( defined $body and length $body ) {
             $msg  = $body;
             $body = undef;
         }
@@ -183,7 +183,7 @@ Search::Elasticsearch::Role::Cxn - Provides common functionality to Cxn implemen
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::CxnPool::Sniff;
-$Search::Elasticsearch::Role::CxnPool::Sniff::VERSION = '1.12';
+$Search::Elasticsearch::Role::CxnPool::Sniff::VERSION = '1.16';
 use Moo::Role;
 with 'Search::Elasticsearch::Role::CxnPool';
 requires 'next_cxn', 'sniff';
@@ -88,7 +88,7 @@ Search::Elasticsearch::Role::CxnPool::Sniff - A CxnPool role for connecting to a
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 CONFIGURATION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::CxnPool::Static::NoPing;
-$Search::Elasticsearch::Role::CxnPool::Static::NoPing::VERSION = '1.12';
+$Search::Elasticsearch::Role::CxnPool::Static::NoPing::VERSION = '1.16';
 use Moo::Role;
 with 'Search::Elasticsearch::Role::CxnPool';
 
@@ -79,7 +79,7 @@ Search::Elasticsearch::Role::CxnPool::Static::NoPing - A CxnPool for connecting
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 AUTHOR
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::CxnPool::Static;
-$Search::Elasticsearch::Role::CxnPool::Static::VERSION = '1.12';
+$Search::Elasticsearch::Role::CxnPool::Static::VERSION = '1.16';
 use Moo::Role;
 with 'Search::Elasticsearch::Role::CxnPool';
 requires 'next_cxn';
@@ -39,7 +39,7 @@ Search::Elasticsearch::Role::CxnPool::Static - A CxnPool role for connecting to
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 METHODS
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::CxnPool;
-$Search::Elasticsearch::Role::CxnPool::VERSION = '1.12';
+$Search::Elasticsearch::Role::CxnPool::VERSION = '1.16';
 use Moo::Role;
 use Search::Elasticsearch::Util qw(parse_params);
 use List::Util qw(shuffle);
@@ -134,7 +134,7 @@ Search::Elasticsearch::Role::CxnPool - Provides common functionality to the CxnP
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::Is_Sync;
-$Search::Elasticsearch::Role::Is_Sync::VERSION = '1.12';
+$Search::Elasticsearch::Role::Is_Sync::VERSION = '1.16';
 use Moo::Role;
 use namespace::clean;
 
@@ -19,7 +19,7 @@ Search::Elasticsearch::Role::Is_Sync - A role to mark classes which should be us
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 AUTHOR
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::Logger;
-$Search::Elasticsearch::Role::Logger::VERSION = '1.12';
+$Search::Elasticsearch::Role::Logger::VERSION = '1.16';
 use Moo::Role;
 
 use URI();
@@ -139,7 +139,7 @@ Search::Elasticsearch::Role::Logger - Provides common functionality to Logger im
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::Scroll;
-$Search::Elasticsearch::Role::Scroll::VERSION = '1.12';
+$Search::Elasticsearch::Role::Scroll::VERSION = '1.16';
 use Moo::Role;
 requires '_clear_scroll';
 use Search::Elasticsearch::Util qw(parse_params throw);
@@ -7,18 +7,18 @@ use Scalar::Util qw(weaken blessed);
 use namespace::clean;
 
 has 'es' => ( is => 'ro', required => 1 );
-has 'scroll'         => ( is => 'ro' );
-has 'scroll_in_body' => ( is => 'ro' );
-has 'total'          => ( is => 'rwp' );
-has 'max_score'      => ( is => 'rwp' );
-has 'facets'         => ( is => 'rwp' );
-has 'aggregations'   => ( is => 'rwp' );
-has 'suggest'        => ( is => 'rwp' );
-has 'took'           => ( is => 'rwp' );
-has 'total_took'     => ( is => 'rwp' );
-has 'search_params'  => ( is => 'ro' );
-has 'is_finished'    => ( is => 'rwp', default => '' );
-has '_scroll_id'     => ( is => 'rwp', clearer => 1, predicate => 1 );
+has 'scroll'        => ( is => 'ro' );
+has 'scroll_in_qs'  => ( is => 'ro' );
+has 'total'         => ( is => 'rwp' );
+has 'max_score'     => ( is => 'rwp' );
+has 'facets'        => ( is => 'rwp' );
+has 'aggregations'  => ( is => 'rwp' );
+has 'suggest'       => ( is => 'rwp' );
+has 'took'          => ( is => 'rwp' );
+has 'total_took'    => ( is => 'rwp' );
+has 'search_params' => ( is => 'ro' );
+has 'is_finished'   => ( is => 'rwp', default => '' );
+has '_scroll_id'    => ( is => 'rwp', clearer => 1, predicate => 1 );
 
 #===================================
 sub finish {
@@ -29,18 +29,16 @@ sub finish {
     $self->_clear_scroll;
 }
 
-
-
 #===================================
 sub scroll_request {
 #===================================
     my $self = shift;
     my %args = ( scroll => $self->scroll );
-    if ( $self->scroll_in_body ) {
-        $args{body} = $self->_scroll_id;
+    if ( $self->scroll_in_qs ) {
+        $args{scroll_id} = $self->_scroll_id;
     }
     else {
-        $args{scroll_id} = $self->_scroll_id;
+        $args{body} = $self->_scroll_id;
     }
     $self->es->scroll(%args);
 }
@@ -68,7 +66,7 @@ Search::Elasticsearch::Role::Scroll - Provides common functionality to L<Elastic
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 AUTHOR
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::Serializer::JSON;
-$Search::Elasticsearch::Role::Serializer::JSON::VERSION = '1.12';
+$Search::Elasticsearch::Role::Serializer::JSON::VERSION = '1.16';
 use Moo::Role;
 requires 'JSON';
 
@@ -103,7 +103,7 @@ Search::Elasticsearch::Role::Serializer::JSON - A Serializer role for JSON modul
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::Serializer;
-$Search::Elasticsearch::Role::Serializer::VERSION = '1.12';
+$Search::Elasticsearch::Role::Serializer::VERSION = '1.16';
 use Moo::Role;
 
 requires qw(encode decode encode_pretty encode_bulk mime_type);
@@ -20,7 +20,7 @@ Search::Elasticsearch::Role::Serializer - An interface for Serializer modules
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Role::Transport;
-$Search::Elasticsearch::Role::Transport::VERSION = '1.12';
+$Search::Elasticsearch::Role::Transport::VERSION = '1.16';
 use Moo::Role;
 
 requires qw(perform_request);
@@ -72,7 +72,7 @@ Search::Elasticsearch::Role::Transport - Transport role providing interface betw
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 AUTHOR
 
@@ -1,7 +1,7 @@
 package Search::Elasticsearch::Scroll;
-$Search::Elasticsearch::Scroll::VERSION = '1.12';
+$Search::Elasticsearch::Scroll::VERSION = '1.16';
 use Moo;
-use Search::Elasticsearch::Util qw(parse_params);
+use Search::Elasticsearch::Util qw(parse_params throw);
 use namespace::clean;
 
 has '_buffer' => ( is => 'ro' );
@@ -13,25 +13,30 @@ with 'Search::Elasticsearch::Role::Is_Sync',
 sub BUILDARGS {
 #===================================
     my ( $class, $params ) = parse_params(@_);
-    my $es             = delete $params->{es};
-    my $scroll         = $params->{scroll} ||= '1m';
-    my $scroll_in_body = delete $params->{scroll_in_body};
-    my $results        = $es->search($params);
+    my $es = delete $params->{es};
+    my $scroll = $params->{scroll} ||= '1m';
+
+    throw( 'Param',
+        'The (scroll_in_body) parameter has been replaced by (scroll_in_qs)' )
+        if exists $params->{scroll_in_body};
+
+    my $scroll_in_qs = delete $params->{scroll_in_qs};
+    my $results      = $es->search($params);
 
     my $total = $results->{hits}{total};
 
     return {
-        es             => $es,
-        scroll         => $scroll,
-        scroll_in_body => $scroll_in_body,
-        aggregations   => $results->{aggregations},
-        facets         => $results->{facets},
-        suggest        => $results->{suggest},
-        took           => $results->{took},
-        total_took     => $results->{took},
-        total          => $total,
-        max_score      => $results->{hits}{max_score},
-        _buffer        => $results->{hits}{hits},
+        es           => $es,
+        scroll       => $scroll,
+        scroll_in_qs => $scroll_in_qs,
+        aggregations => $results->{aggregations},
+        facets       => $results->{facets},
+        suggest      => $results->{suggest},
+        took         => $results->{took},
+        total_took   => $results->{took},
+        total        => $total,
+        max_score    => $results->{hits}{max_score},
+        _buffer      => $results->{hits}{hits},
         $total
         ? ( _scroll_id => $results->{_scroll_id} )
         : ( is_finished => 1 )
@@ -105,9 +110,10 @@ sub _clear_scroll {
     my $scroll_id = $self->_scroll_id or return;
     $self->_clear_scroll_id;
 
-    my %args = $self->scroll_in_body
-        ? ( body => $scroll_id )
-        : ( scroll_id => $scroll_id );
+    my %args
+        = $self->scroll_in_qs
+        ? ( scroll_id => $scroll_id )
+        : ( body => $scroll_id );
     eval { $self->es->clear_scroll(%args) };
 }
 
@@ -123,7 +129,7 @@ Search::Elasticsearch::Scroll - A helper module for scrolled searches
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 SYNOPSIS
 
@@ -274,7 +280,7 @@ are memory constrained, you will need to take this into account.
     my $es = Search::Elasticsearch->new(...);
     my $scroll = $es->scroll_helper(
         scroll         => '1m',            # optional
-        scroll_in_body => 0|1,             # optional
+        scroll_in_qs   => 0|1,             # optional
         %search_params
     );
 
@@ -283,7 +289,7 @@ L<Search::Elasticsearch::Scroll> class and calls L</new()>,
 passing in any arguments.
 
 You can specify a C<scroll> duration (which defaults to C<"1m">) and
-C<scroll_in_body> (which defaults to C<false>). Any other parameters are
+C<scroll_in_qs> (which defaults to C<false>). Any other parameters are
 passed directly to L<Search::Elasticsearch::Client::Direct/search()>.
 
 The C<scroll> duration tells Elasticearch how long it should keep the scroll
@@ -292,13 +298,14 @@ all results, just long enough to process a single B<batch> of results.
 The expiry gets renewed for another C<scroll> period every time new
 a new batch of results is retrieved from the cluster.
 
-By default, the C<scroll_id> is passed in the
-L<scroll|Search::Elasticsearch::Client::Direct/scroll()> request as part
-of the query string. When querying very many indices, the scroll ID can become
-too long for intervening proxies.  To send it in the request body instead,
-set C<scroll_in_body> to a true value.  To send it in the request body
-as a C<POST> request, also set
-L<send_get_body_as|Search::Elasticsearch::Transport/send_get_body_as> to
+By default, the C<scroll_id> is passed as the C<body> to the
+L<scroll|Search::Elasticsearch::Client::Direct/scroll()> request.
+To send it in the query string instead, set C<scroll_in_qs> to a true value,
+but be aware: when querying very many indices, the scroll ID can become
+too long for intervening proxies.
+
+The C<scroll> request uses C<GET> by default.  To use C<POST> instead,
+set L<send_get_body_as|Search::Elasticsearch::Transport/send_get_body_as> to
 C<POST>.
 
 =head2 C<next()>
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Serializer::JSON::Cpanel;
-$Search::Elasticsearch::Serializer::JSON::Cpanel::VERSION = '1.12';
+$Search::Elasticsearch::Serializer::JSON::Cpanel::VERSION = '1.16';
 use Cpanel::JSON::XS;
 use Moo;
 
@@ -20,7 +20,7 @@ Search::Elasticsearch::Serializer::JSON::Cpanel - A JSON Serializer using Cpanel
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 SYNOPSIS
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Serializer::JSON::PP;
-$Search::Elasticsearch::Serializer::JSON::PP::VERSION = '1.12';
+$Search::Elasticsearch::Serializer::JSON::PP::VERSION = '1.16';
 use Moo;
 use JSON::PP;
 
@@ -23,7 +23,7 @@ Search::Elasticsearch::Serializer::JSON::PP - A JSON Serializer using JSON::PP
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 SYNOPSIS
 
@@ -1,7 +1,7 @@
 package Search::Elasticsearch::Serializer::JSON::XS;
-$Search::Elasticsearch::Serializer::JSON::XS::VERSION = '1.12';
+$Search::Elasticsearch::Serializer::JSON::XS::VERSION = '1.16';
 use Moo;
-use JSON::XS;
+use JSON::XS 2.26;
 
 has 'JSON' => ( is => 'ro', default => sub { JSON::XS->new->utf8(1) } );
 
@@ -19,7 +19,7 @@ Search::Elasticsearch::Serializer::JSON::XS - A JSON Serializer using JSON::XS
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 SYNOPSIS
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Serializer::JSON;
-$Search::Elasticsearch::Serializer::JSON::VERSION = '1.12';
+$Search::Elasticsearch::Serializer::JSON::VERSION = '1.16';
 use Moo;
 use JSON::MaybeXS 1.002002 ();
 
@@ -24,7 +24,7 @@ Search::Elasticsearch::Serializer::JSON - The default JSON Serializer, using JSO
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 SYNOPSIS
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::TestServer;
-$Search::Elasticsearch::TestServer::VERSION = '1.12';
+$Search::Elasticsearch::TestServer::VERSION = '1.16';
 use Moo;
 use Search::Elasticsearch();
 use POSIX 'setsid';
@@ -174,7 +174,7 @@ Search::Elasticsearch::TestServer - A helper class to launch Elasticsearch nodes
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 SYNOPSIS
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Transport;
-$Search::Elasticsearch::Transport::VERSION = '1.12';
+$Search::Elasticsearch::Transport::VERSION = '1.16';
 use Moo;
 
 use URI();
@@ -73,7 +73,7 @@ Search::Elasticsearch::Transport - Provides interface between the client class a
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Util::API::Path;
-$Search::Elasticsearch::Util::API::Path::VERSION = '1.12';
+$Search::Elasticsearch::Util::API::Path::VERSION = '1.16';
 use strict;
 use warnings;
 use Any::URI::Escape qw(uri_escape);
@@ -66,7 +66,7 @@ Search::Elasticsearch::Util::API::Path - A utility class for converting path tem
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Util::API::QS;
-$Search::Elasticsearch::Util::API::QS::VERSION = '1.12';
+$Search::Elasticsearch::Util::API::QS::VERSION = '1.16';
 use strict;
 use warnings;
 
@@ -20,21 +20,22 @@ our %Handler = (
 );
 
 our %Params = (
-    active_only      => { type => 'bool' },
-    all              => { type => 'bool' },
-    allow_no_indices => { type => 'bool' },
-    analyze_wildcard => { type => 'bool' },
-    analyzer         => { type => 'string' },
-    boost_terms      => { type => 'number' },
-    bytes            => { type => 'enum', options => [ 'b', 'k', 'm', 'g' ] },
+    active_only       => { type => 'bool' },
+    all               => { type => 'bool' },
+    allow_no_indices  => { type => 'bool' },
+    analyze_wildcard  => { type => 'bool' },
+    analyzer          => { type => 'string' },
+    boost_terms       => { type => 'number' },
+    bytes             => { type => 'enum', options => [ 'b', 'k', 'm', 'g' ] },
     char_filters      => { type => 'list' },
     clear             => { type => 'bool' },
     completion        => { type => 'bool' },
     completion_fields => { type => 'list' },
-    consistency       => {
+    consistency => {
         options => [ 'one', 'quorum', 'all' ],
         type    => 'enum'
     },
+    create           => { type => 'bool' },
     default_operator => {
         default => 'OR',
         options => [ 'AND', 'OR' ],
@@ -43,6 +44,7 @@ our %Params = (
     delay            => { type => 'duration' },
     detailed         => { type => 'bool' },
     df               => { type => 'string' },
+    dfs              => { type => 'bool' },
     docs             => { type => 'bool' },
     dry_run          => { type => 'bool' },
     exit             => { type => 'bool' },
@@ -97,7 +99,6 @@ our %Params = (
     index_templates    => { type => 'list' },
     indexing           => { type => 'bool' },
     indices            => { type => 'bool' },
-    indices_boost      => { type => 'list' },
     interval           => { type => 'duration' },
     jvm                => { type => 'bool' },
     lang               => { type => 'string' },
@@ -114,18 +115,25 @@ our %Params = (
     max_query_terms          => { type => 'number' },
     max_word_len             => { type => 'number' },     # depr 0.90
     max_word_length          => { type => 'number' },
-    merge                    => { type => 'bool' },
-    min_doc_freq             => { type => 'number' },
-    min_score                => { type => 'number' },
-    min_term_freq            => { type => 'number' },
-    min_word_len             => { type => 'number' },     # depr 0.90
-    min_word_length          => { type => 'number' },
-    mlt_fields               => { type => 'list' },
-    name                     => { type => 'list' },
-    network                  => { type => 'bool' },
-    offsets                  => { type => 'bool' },
-    only_expunge_deletes     => { type => 'bool' },
-    op_type                  => {
+    metric                   => {
+        type    => 'enum',
+        options => [
+            "_all",          "blocks",      "metadata", "nodes",
+            "routing_table", "master_node", "version"
+        ]
+    },
+    merge                => { type => 'bool' },
+    min_doc_freq         => { type => 'number' },
+    min_score            => { type => 'number' },
+    min_term_freq        => { type => 'number' },
+    min_word_len         => { type => 'number' },    # depr 0.90
+    min_word_length      => { type => 'number' },
+    mlt_fields           => { type => 'list' },
+    name                 => { type => 'list' },
+    network              => { type => 'bool' },
+    offsets              => { type => 'bool' },
+    only_expunge_deletes => { type => 'bool' },
+    op_type              => {
         default => 'index',
         options => [ 'index', 'create' ],
         type    => 'enum'
@@ -136,7 +144,10 @@ our %Params = (
     payloads               => { type => 'bool' },
     percent_terms_to_match => { type => 'number' },
     percolate              => { type => 'string' },
+    percolate_format       => { type => 'string' },
     percolate_index        => { type => 'string' },
+    percolate_preference   => { type => 'string' },
+    percolate_routing      => { type => 'list' },
     percolate_type         => { type => 'string' },
     plugin                 => { type => 'bool' },
     positions              => { type => 'bool' },
@@ -145,6 +156,7 @@ our %Params = (
     pri                    => { type => 'bool' },
     process                => { type => 'bool' },
     q                      => { type => 'string' },
+    query_cache            => { type => 'bool' },
     realtime               => { type => 'bool' },
     recovery               => { type => 'bool' },
     recycler               => { type => 'bool' },
@@ -156,13 +168,14 @@ our %Params = (
     },
     retry_on_conflict => { type => 'number' },
     routing           => { type => 'string' },
-    script            => { type => 'string', },
+    script            => { type => 'string' },
+    script_id         => { type => 'string' },
+    scripted_upsert   => { type => 'bool' },
     scroll            => { type => 'duration' },
     scroll_id         => { type => 'string' },
     search            => { type => 'bool' },
     search_from       => { type => 'number' },
     search_indices    => { type => 'list' },
-    search_query_hint => { type => 'string' },
     search_scroll     => { type => 'string' },
     search_size       => { type => 'number' },
     search_source     => { type => 'string' },
@@ -202,6 +215,7 @@ our %Params = (
     timeout         => { type => 'duration' },
     timestamp       => { type => 'datetime' },
     tokenizer       => { type => 'string' },
+    track_scores    => { type => 'bool' },
     transport       => { type => 'bool' },
     ts              => { type => 'bool' },
     ttl             => { type => 'duration' },
@@ -209,6 +223,7 @@ our %Params = (
     types           => { type => 'list' },
     v               => { type => 'bool' },
     verbose         => { type => 'bool' },
+    verify          => { type => 'bool' },
     version         => { type => 'number' },
     version_type    => {
         type    => 'enum',
@@ -224,7 +239,8 @@ our %Params = (
         options => [ 'green', 'yellow', 'red' ],
         type    => 'enum'
     },
-    warmer => { type => 'bool' }
+    wait_if_ongoing => { type => 'bool' },
+    warmer          => { type => 'bool' }
 );
 
 #===================================
@@ -253,7 +269,7 @@ Search::Elasticsearch::Util::API::QS - A utility class for query string paramete
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 DESCRIPTION
 
@@ -1,5 +1,5 @@
 package Search::Elasticsearch::Util;
-$Search::Elasticsearch::Util::VERSION = '1.12';
+$Search::Elasticsearch::Util::VERSION = '1.16';
 use Moo;
 use Search::Elasticsearch::Error();
 use Scalar::Util qw(blessed);
@@ -119,7 +119,7 @@ Search::Elasticsearch::Util - A utility class for internal use by Search::Elasti
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 AUTHOR
 
@@ -5,7 +5,7 @@ use Moo 1.003;
 use Search::Elasticsearch::Util qw(parse_params load_plugin);
 use namespace::clean;
 
-our $VERSION = '1.12';
+our $VERSION = '1.16';
 
 my %Default_Plugins = (
     client      => [ 'Search::Elasticsearch::Client',       'Direct' ],
@@ -53,7 +53,7 @@ Search::Elasticsearch - The official client for Elasticsearch
 
 =head1 VERSION
 
-version 1.12
+version 1.16
 
 =head1 SYNOPSIS
 
@@ -0,0 +1,5 @@
+use lib 't/lib';
+
+$ENV{ES_CXN} = 'HTTPTiny';
+do "es_sync_fork.pl" or die $!;
+
@@ -0,0 +1,5 @@
+use lib 't/lib';
+
+$ENV{ES_CXN} = 'LWP';
+do "es_sync_fork.pl" or die $!;
+
@@ -0,0 +1,5 @@
+use lib 't/lib';
+
+$ENV{ES_CXN} = 'Hijk';
+do "es_sync_fork.pl" or die $!;
+
@@ -0,0 +1,5 @@
+use lib 't/lib';
+
+$ENV{ES_CXN} = 'NetCurl';
+do "es_sync_fork.pl" or die $!;
+
@@ -70,12 +70,12 @@ SKIP: {
                 aggs   => { color => { terms => { field => 'color' } } },
             }
         },
-        total        => 50,
-        max_score    => num( 1.6, 0.2 ),
-        aggregations => $es_version ge '1' ? bool(1) : undef,
-        facets       => bool(1),
-        suggest      => bool(1),
-        steps        => [
+        total     => 50,
+        max_score => num( 1.6, 0.5 ),
+        aggs      => bool(1),
+        facets    => bool(1),
+        suggest   => bool(1),
+        steps     => [
             next        => [1],
             next_50     => [49],
             is_finished => 1,
@@ -83,9 +83,9 @@ SKIP: {
     );
 
     test_scroll(
-        "Scroll in body",
-        {   scroll_in_body => 1,
-            body           => {
+        "Scroll in qs",
+        {   scroll_in_qs => 1,
+            body         => {
                 query   => { term => { color => 'red' } },
                 suggest => {
                     mysuggest =>
@@ -95,12 +95,12 @@ SKIP: {
                 aggs   => { color => { terms => { field => 'color' } } },
             }
         },
-        total        => 50,
-        max_score    => num( 1.6, 0.2 ),
-        aggregations => $es_version ge '1' ? bool(1) : undef,
-        facets       => bool(1),
-        suggest      => bool(1),
-        steps        => [
+        total     => 50,
+        max_score => num( 1.6, 0.5 ),
+        aggs      => bool(1),
+        facets    => bool(1),
+        suggest   => bool(1),
+        steps     => [
             next        => [1],
             next_50     => [49],
             is_finished => 1,
@@ -116,15 +116,13 @@ SKIP: {
                         { text => 'green', term => { field => 'color' } }
                 },
                 facets => { color => { terms => { field => 'color' } } },
-                aggs   => { color => { terms => { field => 'color' } } },
             }
         },
-        total        => 100,
-        max_score    => 0,
-        aggregations => $es_version ge '1' ? bool(1) : undef,
-        facets       => bool(1),
-        suggest      => bool(1),
-        steps        => [
+        total     => 100,
+        max_score => 0,
+        facets    => bool(1),
+        suggest   => bool(1),
+        steps     => [
             buffer_size => 0,
             next        => [1],
             buffer_size => 49,
@@ -162,7 +160,8 @@ $es->indices->delete( index => 'test' );
 sub test_scroll {
 #===================================
     my ( $title, $params, %tests ) = @_;
-    delete $params->{body}{aggs} unless $es_version ge '1';
+    delete $params->{body}{ $es_version ge '1' ? 'facets' : 'aggs' };
+
     subtest $title => sub {
         isa_ok my $s
             = Search::Elasticsearch::Scroll->new( es => $es, %$params ),
@@ -170,8 +169,10 @@ sub test_scroll {
 
         is $s->total,             $tests{total},     "$title - total";
         cmp_deeply $s->max_score, $tests{max_score}, "$title - max_score";
-        cmp_deeply $s->facets,    $tests{facets},    "$title - facets";
         cmp_deeply $s->suggest,   $tests{suggest},   "$title - suggest";
+        $es_version ge 1
+            ? cmp_deeply $s->aggregations, $tests{aggs}, "$title - aggs"
+            : cmp_deeply $s->facets, $tests{facets}, "$title - facets";
 
         my $i     = 1;
         my @steps = @{ $tests{steps} };
@@ -13,6 +13,7 @@ my $api = $version =~ /^0.90/ ? '0_90::Direct' : 'Direct';
 my $body     = $ENV{ES_BODY}     || 'GET';
 my $cxn      = $ENV{ES_CXN}      || do "default_cxn.pl" || die $!;
 my $cxn_pool = $ENV{ES_CXN_POOL} || 'Static';
+my $timeout  = $ENV{ES_TIMEOUT}  || 30;
 
 my $es;
 if ( $ENV{ES} ) {
@@ -22,7 +23,8 @@ if ( $ENV{ES} ) {
         cxn              => $cxn,
         cxn_pool         => $cxn_pool,
         client           => $api,
-        send_get_body_as => $body
+        send_get_body_as => $body,
+        request_timeout  => $timeout
     );
     eval { $es->ping; } or do {
         diag $@;
@@ -0,0 +1,42 @@
+use Test::More;
+use POSIX ":sys_wait_h";
+
+my $es        = do "es_sync.pl";
+my $cxn_class = ref $es->transport->cxn_pool->cxns->[0];
+ok $es->info, "$cxn_class - Info before fork";
+
+my $Kids = 4;
+my %pids;
+
+for my $child ( 1 .. $Kids ) {
+    my $pid = fork();
+    if ($pid) {
+        $pids{$pid} = $child;
+        next;
+    }
+    if ( !defined $pid ) {
+        skip "fork() not supported";
+        done_testing;
+        last;
+    }
+
+    for ( 1 .. 100 ) {
+        $es->info;
+    }
+    exit;
+}
+
+my $ok = 0;
+for ( 1 .. 10 ) {
+    my $pid = waitpid( -1, WNOHANG );
+    if ( $pid > 0 ) {
+        delete $pids{$pid};
+        $ok++ unless $?;
+        redo;
+    }
+    last unless keys %pids;
+    sleep 1;
+}
+
+is $ok, $Kids, "$cxn_class - Fork";
+done_testing;
@@ -3,6 +3,8 @@ use warnings;
 use Search::Elasticsearch::Bulk;
 use lib 't/lib';
 
+local $ENV{ES_CXN};
+local $ENV{ES_CXN_POOL};
 my $es = do 'es_sync.pl';
 
 $es->indices->delete( index => 'test', ignore => 404 );
@@ -9,7 +9,7 @@ BEGIN {
 use strict;
 use warnings;
 
-# this test was generated with Dist::Zilla::Plugin::Test::NoTabs 0.07
+# this test was generated with Dist::Zilla::Plugin::Test::NoTabs 0.08
 
 use Test::More 0.88;
 use Test::NoTabs;
@@ -119,6 +119,10 @@ my @files = (
     't/60_Cxn/10_basic.t',
     't/60_Cxn/20_process_response.t',
     't/60_Cxn/30_http.t',
+    't/60_Cxn/40_fork_httptiny.t',
+    't/60_Cxn/41_fork_lwp.t',
+    't/60_Cxn/42_fork_hijk.t',
+    't/60_Cxn/43_fork_netcurl.t',
     't/70_Helper/10_bulk_add_action.t',
     't/70_Helper/20_bulk_helpers.t',
     't/70_Helper/30_bulk_flush.t',
@@ -130,6 +134,7 @@ my @files = (
     't/lib/MockCxn.pm',
     't/lib/default_cxn.pl',
     't/lib/es_sync.pl',
+    't/lib/es_sync_fork.pl',
     't/lib/index_test_data.pl',
     't/release-eol.t',
     't/release-no-tabs.t',