From 9c9acae236ed6b5d9b27d15237e6fa9f0f619302 Mon Sep 17 00:00:00 2001
From: William Hearn <sylus1984@gmail.com>
Date: Sun, 10 Mar 2019 20:19:09 -0400
Subject: [PATCH] feat(s3fs): Compatibility with Minio

---
 config/install/s3fs.settings.yml |  1 +
 config/schema/s3fs.schema.yml    |  3 +++
 src/Asset/S3fsCssOptimizer.php   |  3 ++-
 src/Form/SettingsForm.php        | 10 ++++++++++
 src/S3fsService.php              |  6 +++++-
 src/StreamWrapper/S3fsStream.php |  2 +-
 src/Tests/S3fsConfigFormTest.php |  1 +
 7 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/config/install/s3fs.settings.yml b/config/install/s3fs.settings.yml
index 89315fc..2ed1bd1 100644
--- a/config/install/s3fs.settings.yml
+++ b/config/install/s3fs.settings.yml
@@ -8,6 +8,7 @@ use_cname: false
 use_customhost: false
 hostname: ''
 domain: ''
+use_path_style_endpoint: false
 cache_control_header: ''
 encryption: ''
 use_https: false
diff --git a/config/schema/s3fs.schema.yml b/config/schema/s3fs.schema.yml
index ae93d61..f44c8d1 100644
--- a/config/schema/s3fs.schema.yml
+++ b/config/schema/s3fs.schema.yml
@@ -31,6 +31,9 @@ s3fs.settings:
     domain:
       type: string
       label: 'CDN Domain Name'
+    use_path_style_endpoint:
+      type: boolean
+      label: 'Use path-style endpoint'
     cache_control_header:
       type: string
       label: 'S3 Object Cache-Control Header'
diff --git a/src/Asset/S3fsCssOptimizer.php b/src/Asset/S3fsCssOptimizer.php
index bf323d4..03e1e62 100644
--- a/src/Asset/S3fsCssOptimizer.php
+++ b/src/Asset/S3fsCssOptimizer.php
@@ -30,7 +30,8 @@ class S3fsCssOptimizer extends CssOptimizer {
       $last = $path;
       $path = preg_replace('`(^|/)(?!\.\./)([^/]+)/\.\./`', '$1', $path);
     }
-    return 'url(' . file_create_url($path) . ')';
+    $url = file_create_url($path);
+    return 'url(' . preg_replace('#^https?:#', '', $url) . ')';
   }
 
 }
diff --git a/src/Form/SettingsForm.php b/src/Form/SettingsForm.php
index d88a9ee..ff8143b 100644
--- a/src/Form/SettingsForm.php
+++ b/src/Form/SettingsForm.php
@@ -201,6 +201,15 @@ class SettingsForm extends ConfigFormBase {
       '#default_value' => $config->get('domain'),
       '#description' => $this->t('If serving files from CloudFront, the bucket name can differ from the domain name.'),
     ];
+    $advanced['use_path_style_endpoint'] = [
+      '#type' => 'checkbox',
+      '#title' => $this->t('Use path-style endpoint'),
+      '#default_value' => $config->get('use_path_style_endpoint'),
+      '#description' => $this->t('Send requests to a path-style endpoint, instead of a virtual-hosted-style endpoint. For example, %path_style, insead of %virtual_hosted_style.', [
+        '%path_style' => 'http://s3.amazonaws.com/bucket',
+        '%virtual_hosted_style' => 'http://bucket.s3.amazonaws.com',
+      ]),
+    ];
     $advanced['cache_control_header'] = [
       '#type' => 'textfield',
       '#title' => $this->t('S3 Object Cache-Control Header'),
@@ -427,6 +436,7 @@ class SettingsForm extends ConfigFormBase {
       ->set('use_customhost', $values['use_customhost'])
       ->set('hostname', $values['hostname'])
       ->set('domain', $values['domain'])
+      ->set('use_path_style_endpoint', $values['use_path_style_endpoint'])
       ->set('cache_control_header', $values['cache_control_header'])
       ->set('encryption', $values['encryption'])
       ->set('use_https', $values['use_https'])
diff --git a/src/S3fsService.php b/src/S3fsService.php
index e17f82d..a0b19b3 100644
--- a/src/S3fsService.php
+++ b/src/S3fsService.php
@@ -168,6 +168,10 @@ class S3fsService implements S3fsServiceInterface {
       if (!empty($config['use_customhost']) && !empty($config['hostname'])) {
         $client_config['endpoint'] = ($config['use_https'] ? 'https://' : 'http://') . $config['hostname'];
       }
+      // Use path-style endpoint, if selected.
+      if (!empty($config['use_path_style_endpoint'])) {
+        $client_config['use_path_style_endpoint'] = $config['use_path_style_endpoint'];
+      }
       $client_config['version'] = S3fsStream::API_VERSION;
       // Create the Aws\S3\S3Client object.
       $s3 = new S3Client($client_config);
@@ -205,7 +209,7 @@ class S3fsService implements S3fsServiceInterface {
     }
     // Create an iterator that will emit all of the objects matching the
     // key prefix.
-    $iterator = $s3->getIterator('ListObjectVersions', $iterator_args);
+    $iterator = $s3->getIterator('ListObjects', $iterator_args);
 
     // The $folders array is an associative array keyed by folder paths, which
     // is constructed as each filename is written to the DB. After all the files
diff --git a/src/StreamWrapper/S3fsStream.php b/src/StreamWrapper/S3fsStream.php
index 64d4264..ca67a74 100644
--- a/src/StreamWrapper/S3fsStream.php
+++ b/src/StreamWrapper/S3fsStream.php
@@ -194,7 +194,7 @@ class S3fsStream extends StreamWrapper implements StreamWrapperInterface {
         if (strpos($domain, '/') === 0) {
           $domain = $_SERVER['HTTP_HOST'] . $domain;
         }
-        $this->domain = "$scheme://$domain";
+        $this->domain = "https://$domain";
       }
       else {
         // Due to the config form's validation, this shouldn't ever happen.
diff --git a/src/Tests/S3fsConfigFormTest.php b/src/Tests/S3fsConfigFormTest.php
index fa19e28..4b9b8a2 100644
--- a/src/Tests/S3fsConfigFormTest.php
+++ b/src/Tests/S3fsConfigFormTest.php
@@ -43,6 +43,7 @@ class S3fsConfigFormTest extends WebTestBase {
     $edit['region'] = 'us-east-1';
     $edit['use_cname'] = 1;
     $edit['domain'] = 'domaincheck.com';
+    $edit['use_path_style_endpoint'] = 1;
     $edit['encryption'] = 'AES256';
     $edit['use_https'] = 1;
     $edit['root_folder'] = 'rootfoldercheck';
-- 
2.17.2 (Apple Git-113)

