Bläddra i källkod

HUE-2916 [fb] Change URL-routing

Filebrowser routing `r'^view(?P<path>/.*)$'` is unsuitable for absolute
URI.
* Changes filebrowser routing rules to `r'^view=(?P<path>.*)$'`
  this new pattern will allow path like:
  - /user/romain/public (default to hdfs)
  - s3://bucket/key
* Makes related changes on other applications
Ivan Orlov 10 år sedan
förälder
incheckning
cde6a6a
26 ändrade filer med 116 tillägg och 109 borttagningar
  1. 2 2
      apps/beeswax/src/beeswax/api.py
  2. 2 2
      apps/filebrowser/src/filebrowser/templates/fb_components.mako
  3. 2 2
      apps/filebrowser/src/filebrowser/templates/listdir_components.mako
  4. 8 8
      apps/filebrowser/src/filebrowser/urls.py
  5. 7 1
      apps/filebrowser/src/filebrowser/views.py
  6. 53 51
      apps/filebrowser/src/filebrowser/views_test.py
  7. 8 8
      apps/jobbrowser/src/jobbrowser/tests.py
  8. 0 1
      apps/metastore/src/metastore/templates/describe_partitions.mako
  9. 1 1
      apps/oozie/src/oozie/templates/editor/edit_workflow.mako
  10. 3 3
      apps/oozie/src/oozie/templates/editor2/common_workflow.mako
  11. 1 1
      apps/oozie/src/oozie/templates/editor2/coordinator_editor.mako
  12. 1 1
      apps/oozie/src/oozie/templates/editor2/workflow_editor.mako
  13. 5 5
      apps/oozie/src/oozie/templates/utils.inc.mako
  14. 2 2
      apps/pig/src/pig/models.py
  15. 3 3
      apps/pig/src/pig/templates/app.mako
  16. 3 3
      apps/search/src/search/static/search/js/search.utils.js
  17. 1 1
      apps/security/src/security/static/security/js/hdfs.ko.js
  18. 1 1
      apps/security/src/security/static/security/js/hive.ko.js
  19. 5 5
      apps/security/src/security/templates/hdfs.mako
  20. 1 1
      apps/security/src/security/templates/hive.mako
  21. 2 2
      apps/sqoop/src/sqoop/static/sqoop/js/sqoop.jobs.js
  22. 1 1
      desktop/core/src/desktop/models.py
  23. 1 1
      desktop/core/src/desktop/static/desktop/js/jquery.filechooser.js
  24. 1 1
      desktop/core/src/desktop/static/desktop/js/jquery.hdfsautocomplete.js
  25. 1 1
      desktop/core/src/desktop/static/desktop/js/jquery.hdfstree.js
  26. 1 1
      desktop/core/src/desktop/tests.py

+ 2 - 2
apps/beeswax/src/beeswax/api.py

@@ -448,7 +448,7 @@ def save_results_hdfs_directory(request, query_history_id):
         response['id'] = query_history.id
         response['query'] = query_history.query
         response['path'] = target_dir
-        response['success_url'] = '/filebrowser/view%s' % target_dir
+        response['success_url'] = '/filebrowser/view=%s' % target_dir
         query_history = db.insert_query_into_directory(query_history, target_dir)
         response['watch_url'] = reverse(get_app_name(request) + ':api_watch_query_refresh_json', kwargs={'id': query_history.id})
       except Exception, ex:
@@ -515,7 +515,7 @@ def save_results_hdfs_file(request, query_history_id):
         response['id'] = query_history.id
         response['query'] = query_history.query
         response['path'] = target_file
-        response['success_url'] = '/filebrowser/view%s' % target_file
+        response['success_url'] = '/filebrowser/view=%s' % target_file
         response['watch_url'] = reverse(get_app_name(request) + ':api_watch_query_refresh_json', kwargs={'id': query_history.id})
       except Exception, ex:
         error_msg, log = expand_exception(ex, db)

+ 2 - 2
apps/filebrowser/src/filebrowser/templates/fb_components.mako

@@ -50,10 +50,10 @@ from django.utils.translation import ugettext as _
                     % for breadcrumb_item in breadcrumbs:
                     <% label = breadcrumb_item['label'] %>
                     %if label == '/':
-                            <li><a href="/filebrowser/view${breadcrumb_item['url']}"><span
+                            <li><a href="/filebrowser/view=${breadcrumb_item['url']}"><span
                                     class="divider">${label}</span></a></li>
                     %else:
-                            <li><a href="/filebrowser/view${breadcrumb_item['url']}">${label}</a><span class="divider">/</span></li>
+                            <li><a href="/filebrowser/view=${breadcrumb_item['url']}">${label}</a><span class="divider">/</span></li>
                     %endif
                     % endfor
             </ul>

+ 2 - 2
apps/filebrowser/src/filebrowser/templates/listdir_components.mako

@@ -1292,7 +1292,7 @@ from django.utils.translation import ugettext as _
             if (response.status != 0) {
               $(document).trigger("error", "${ _('Error: ') }" + response['data']);
             } else if (num_of_pending_uploads == 0) {
-              location = "/filebrowser/view" + self.currentPath();
+              location = "/filebrowser/view=" + self.currentPath();
             }
           },
           onSubmit:function (id, fileName, responseJSON) {
@@ -1340,7 +1340,7 @@ from django.utils.translation import ugettext as _
           onComplete:function (id, fileName, responseJSON) {
             num_of_pending_uploads--;
             if (num_of_pending_uploads == 0) {
-              location = "/filebrowser/view" + self.currentPath();
+              location = "/filebrowser/view=" + self.currentPath();
             }
           },
           onSubmit:function (id, fileName, responseJSON) {

+ 8 - 8
apps/filebrowser/src/filebrowser/urls.py

@@ -23,16 +23,16 @@ urlpatterns = patterns('filebrowser.views',
   url(r'^$', 'index', name='index'),
 
   # Catch-all for viewing a file (display) or a directory (listdir)
-  url(r'^view(?P<path>/.*)$', 'view', name='view'),
+  url(r'^view=(?P<path>.*)$', 'view', name='view'),
 
-  url(r'^listdir(?P<path>/.*)$', 'listdir', name='listdir'),
-  url(r'^display(?P<path>/.*)$', 'display', name='display'),
-  url(r'^stat(?P<path>/.*)$', 'stat', name='stat'),
-  url(r'^download(?P<path>/.*)$', 'download', name='download'),
+  url(r'^listdir=(?P<path>.*)$', 'listdir', name='listdir'),
+  url(r'^display=(?P<path>.*)$', 'display', name='display'),
+  url(r'^stat=(?P<path>.*)$', 'stat', name='stat'),
+  url(r'^download=(?P<path>.*)$', 'download', name='download'),
   url(r'^status$', 'status', name='status'),
-  url(r'^home_relative_view(?P<path>/.*)$', 'home_relative_view', name='home_relative_view'),
-  url(r'^chooser(?P<path>/.*)$', 'chooser', name='choose'),
-  url(r'^edit(?P<path>/.*)$', 'edit', name='edit'),
+  url(r'^home_relative_view=(?P<path>.*)$', 'home_relative_view', name='home_relative_view'),
+  url(r'^chooser=(?P<path>.*)$', 'chooser', name='choose'),
+  url(r'^edit=(?P<path>.*)$', 'edit', name='edit'),
 
   # POST operations
   url(r'^save$', 'save_file'),

+ 7 - 1
apps/filebrowser/src/filebrowser/views.py

@@ -1304,6 +1304,7 @@ def status(request):
 def location_to_url(location, strict=True):
     """
     If possible, returns a file browser URL to the location.
+    Prunes HDFS URI to path.
     Location is a URI, if strict is True.
 
     Python doesn't seem to have a readily-available URI-comparison
@@ -1315,7 +1316,11 @@ def location_to_url(location, strict=True):
     if strict and not split_path[1] or not split_path[2]:
       # No netloc not full url or no URL
       return None
-    return reverse("filebrowser.views.view", kwargs=dict(path=split_path[2]))
+    path = location
+    if split_path[0] == 'hdfs':
+      path = split_path[2]
+    return reverse("filebrowser.views.view", kwargs=dict(path=path))
+
 
 def truncate(toTruncate, charsToKeep=50):
     """
@@ -1327,5 +1332,6 @@ def truncate(toTruncate, charsToKeep=50):
     else:
         return toTruncate
 
+
 def _is_hdfs_superuser(request):
   return request.user.username == request.fs.superuser or request.user.groups.filter(name__exact=request.fs.supergroup).exists()

+ 53 - 51
apps/filebrowser/src/filebrowser/views_test.py

@@ -204,7 +204,7 @@ class TestFileBrowserWithHadoop(object):
     self.c.post('/filebrowser/mkdir', dict(path=prefix, name=success_path))
 
     # Read the parent dir and make sure we created 'success_path' only.
-    response = self.c.get('/filebrowser/view' + prefix)
+    response = self.c.get('/filebrowser/view=' + prefix)
     dir_listing = response.context['files']
     assert_equal(3, len(dir_listing))
     assert_equal(dir_listing[2]['name'], success_path)
@@ -227,7 +227,7 @@ class TestFileBrowserWithHadoop(object):
     assert_equal(200, resp.status_code)
 
     # Read the parent dir and make sure we created 'success_path' only.
-    response = self.c.get('/filebrowser/view' + prefix)
+    response = self.c.get('/filebrowser/view=' + prefix)
     file_listing = response.context['files']
     assert_equal(3, len(file_listing))
     assert_equal(file_listing[2]['name'], success_path)
@@ -397,7 +397,7 @@ class TestFileBrowserWithHadoop(object):
       self.c.post('/filebrowser/mkdir', dict(path=prefix, name=path))
 
     # Read the parent dir
-    response = self.c.get('/filebrowser/view' + prefix)
+    response = self.c.get('/filebrowser/view=' + prefix)
 
     dir_listing = response.context['files']
     assert_equal(len(orig_paths) + 2, len(dir_listing))
@@ -418,21 +418,21 @@ class TestFileBrowserWithHadoop(object):
       assert_equal('..', resp.context['files'][0]['name'])
 
     # Test's home directory now exists. Should be returned.
-    response = self.c.get('/filebrowser/view' + prefix)
+    response = self.c.get('/filebrowser/view=' + prefix)
     assert_equal(response.context['home_directory'], home)
 
     # Test URL conflicts with filenames
     stat_dir = '%sstat/dir' % prefix
     self.cluster.fs.do_as_user('test', self.cluster.fs.mkdir, stat_dir)
-    response = self.c.get('/filebrowser/view%s' % stat_dir)
+    response = self.c.get('/filebrowser/view=%s' % stat_dir)
     assert_equal(stat_dir, response.context['path'])
 
-    response = self.c.get('/filebrowser/view/test-filebrowser/?default_to_home')
+    response = self.c.get('/filebrowser/view=/test-filebrowser/?default_to_home')
     assert_true(re.search('%s$' % home, response['Location']))
 
     # Test path relative to home directory
     self.cluster.fs.do_as_user('test', self.cluster.fs.mkdir, '%s/test_dir' % home)
-    response = self.c.get('/filebrowser/home_relative_view/test_dir')
+    response = self.c.get('/filebrowser/home_relative_view=/test_dir')
     assert_equal('%s/test_dir' % home, response.context['path'])
 
 
@@ -455,53 +455,53 @@ class TestFileBrowserWithHadoop(object):
     expect = [ '..', '.', FUNNY_NAME] + [ str(i) for i in range(1, 11) ]
 
     # Check pagination
-    listing = self.c.get('/filebrowser/view' + BASE + '?pagesize=20').context['files']
+    listing = self.c.get('/filebrowser/view=' + BASE + '?pagesize=20').context['files']
     assert_equal(len(expect), len(listing))
 
-    listing = self.c.get('/filebrowser/view' + BASE + '?pagesize=10').context['files']
+    listing = self.c.get('/filebrowser/view=' + BASE + '?pagesize=10').context['files']
     assert_equal(12, len(listing))
 
-    listing = self.c.get('/filebrowser/view' + BASE + '?pagesize=10&pagenum=1').context['files']
+    listing = self.c.get('/filebrowser/view=' + BASE + '?pagesize=10&pagenum=1').context['files']
     assert_equal(12, len(listing))
 
-    listing = self.c.get('/filebrowser/view' + BASE + '?pagesize=10&pagenum=2').context['files']
+    listing = self.c.get('/filebrowser/view=' + BASE + '?pagesize=10&pagenum=2').context['files']
     assert_equal(3, len(listing))
 
     # Check sorting (name)
-    listing = self.c.get('/filebrowser/view' + BASE + '?sortby=name').context['files']
+    listing = self.c.get('/filebrowser/view=' + BASE + '?sortby=name').context['files']
     assert_equal(sorted(expect[2:]), [ f['name'] for f in listing ][2:])
 
-    listing = self.c.get('/filebrowser/view' + BASE + '?sortby=name&descending=false').context['files']
+    listing = self.c.get('/filebrowser/view=' + BASE + '?sortby=name&descending=false').context['files']
     assert_equal(sorted(expect[2:]), [ f['name'] for f in listing ][2:])
 
-    listing = self.c.get('/filebrowser/view' + BASE + '?sortby=name&descending=true').context['files']
+    listing = self.c.get('/filebrowser/view=' + BASE + '?sortby=name&descending=true').context['files']
     assert_equal(".", listing[1]['name'])
     assert_equal("..", listing[0]['name'])
     assert_equal(FUNNY_NAME, listing[2]['name'])
 
     # Check sorting (size)
-    listing = self.c.get('/filebrowser/view' + BASE + '?sortby=size').context['files']
+    listing = self.c.get('/filebrowser/view=' + BASE + '?sortby=size').context['files']
     assert_equal(expect, [ f['name'] for f in listing ])
 
     # Check sorting (mtime)
-    listing = self.c.get('/filebrowser/view' + BASE + '?sortby=mtime').context['files']
+    listing = self.c.get('/filebrowser/view=' + BASE + '?sortby=mtime').context['files']
     assert_equal(".", listing[1]['name'])
     assert_equal("..", listing[0]['name'])
     assert_equal(FUNNY_NAME, listing[-1]['name'])
 
     # Check filter
-    listing = self.c.get('/filebrowser/view' + BASE + '?filter=1').context['files']
+    listing = self.c.get('/filebrowser/view=' + BASE + '?filter=1').context['files']
     assert_equal(['..', '.', '1', '10'], [ f['name'] for f in listing ])
 
-    listing = self.c.get('/filebrowser/view' + BASE + '?filter=' + FUNNY_NAME).context['files']
+    listing = self.c.get('/filebrowser/view=' + BASE + '?filter=' + FUNNY_NAME).context['files']
     assert_equal(['..', '.', FUNNY_NAME], [ f['name'] for f in listing ])
 
     # Check filter + sorting
-    listing = self.c.get('/filebrowser/view' + BASE + '?filter=1&sortby=name&descending=true').context['files']
+    listing = self.c.get('/filebrowser/view=' + BASE + '?filter=1&sortby=name&descending=true').context['files']
     assert_equal(['..', '.', '10', '1'], [ f['name'] for f in listing ])
 
     # Check filter + sorting + pagination
-    listing = self.c.get('/filebrowser/view' + BASE + '?filter=1&sortby=name&descending=true&pagesize=1&pagenum=2').context['files']
+    listing = self.c.get('/filebrowser/view=' + BASE + '?filter=1&sortby=name&descending=true&pagesize=1&pagenum=2').context['files']
     assert_equal(['..', '.', '1'], [ f['name'] for f in listing ])
 
 
@@ -510,7 +510,7 @@ class TestFileBrowserWithHadoop(object):
     self.cluster.fs.mkdir(prefix)
 
     # Note that the trailing slash is important. We ask for the root dir.
-    resp = self.c.get('/filebrowser/chooser/?format=json')
+    resp = self.c.get('/filebrowser/chooser=/?format=json')
     # We should get a json response
     dic = json.loads(resp.content)
     assert_equal('/', dic['current_dir_path'])
@@ -541,22 +541,22 @@ class TestFileBrowserWithHadoop(object):
       f.close()
 
       # Snappy compressed fail
-      response = c.get('/filebrowser/view%s/test-view.notsnappy?compression=snappy' % prefix)
+      response = c.get('/filebrowser/view=%s/test-view.notsnappy?compression=snappy' % prefix)
       assert_true('Failed to decompress' in response.context['message'], response)
 
       # Snappy compressed succeed
-      response = c.get('/filebrowser/view%s/test-view.snappy' % prefix)
+      response = c.get('/filebrowser/view=%s/test-view.snappy' % prefix)
       assert_equal('snappy', response.context['view']['compression'])
       assert_equal(response.context['view']['contents'], 'This is a test of the emergency broadcasting system.', response)
 
       # Snappy compressed succeed
-      response = c.get('/filebrowser/view%s/test-view.stillsnappy' % prefix)
+      response = c.get('/filebrowser/view=%s/test-view.stillsnappy' % prefix)
       assert_equal('snappy', response.context['view']['compression'])
       assert_equal(response.context['view']['contents'], 'The broadcasters of your area in voluntary cooperation with the FCC and other authorities.', response)
 
       # Largest snappy compressed file
       finish.append( MAX_SNAPPY_DECOMPRESSION_SIZE.set_for_testing(1) )
-      response = c.get('/filebrowser/view%s/test-view.stillsnappy?compression=snappy' % prefix)
+      response = c.get('/filebrowser/view=%s/test-view.stillsnappy?compression=snappy' % prefix)
       assert_true('File size is greater than allowed max snappy decompression size of 1' in response.context['message'], response)
 
     finally:
@@ -604,7 +604,7 @@ class TestFileBrowserWithHadoop(object):
       f.close()
 
       # Snappy compressed succeed
-      response = self.c.get('/filebrowser/view%s/test-view.compressed.avro' % prefix)
+      response = self.c.get('/filebrowser/view=%s/test-view.compressed.avro' % prefix)
       assert_equal('avro', response.context['view']['compression'])
       assert_equal(eval(response.context['view']['contents']), dummy_datum, response)
 
@@ -640,13 +640,13 @@ class TestFileBrowserWithHadoop(object):
     data_file_writer.close()
 
     # autodetect
-    response = self.c.get('/filebrowser/view%s/test-view.avro' % prefix)
+    response = self.c.get('/filebrowser/view=%s/test-view.avro' % prefix)
     # (Note: we use eval here cause of an incompatibility issue between
     # the representation string of JSON dicts in simplejson vs. json)
     assert_equal(eval(response.context['view']['contents']), dummy_datum)
 
     # offsetting should work as well
-    response = self.c.get('/filebrowser/view%s/test-view.avro?offset=1' % prefix)
+    response = self.c.get('/filebrowser/view=%s/test-view.avro?offset=1' % prefix)
     assert_equal('avro', response.context['view']['compression'])
 
     f = self.cluster.fs.open(prefix + '/test-view2.avro', "w")
@@ -654,11 +654,11 @@ class TestFileBrowserWithHadoop(object):
     f.close()
 
     # we shouldn't autodetect non avro files
-    response = self.c.get('/filebrowser/view%s/test-view2.avro' % prefix)
+    response = self.c.get('/filebrowser/view=%s/test-view2.avro' % prefix)
     assert_equal(response.context['view']['contents'], "hello")
 
     # we should fail to do a bad thing if they specify compression when it's not set.
-    response = self.c.get('/filebrowser/view%s/test-view2.avro?compression=gzip' % prefix)
+    response = self.c.get('/filebrowser/view=%s/test-view2.avro?compression=gzip' % prefix)
     assert_true('Failed to decompress' in response.context['message'])
 
 
@@ -673,7 +673,7 @@ class TestFileBrowserWithHadoop(object):
     f.write(test_data.decode('hex'))
 
     # autodetect
-    response = self.c.get('/filebrowser/view%s/test-parquet.parquet' % prefix)
+    response = self.c.get('/filebrowser/view=%s/test-parquet.parquet' % prefix)
 
     assert_true('FRANCE' in response.context['view']['contents'])
 
@@ -687,11 +687,11 @@ class TestFileBrowserWithHadoop(object):
     f.write(sdf_string)
     f.close()
 
-    response = self.c.get('/filebrowser/view%s/test-view.gz?compression=gzip' % prefix)
+    response = self.c.get('/filebrowser/view=%s/test-view.gz?compression=gzip' % prefix)
     assert_equal(response.context['view']['contents'], "sdf\n")
 
     # autodetect
-    response = self.c.get('/filebrowser/view%s/test-view.gz' % prefix)
+    response = self.c.get('/filebrowser/view=%s/test-view.gz' % prefix)
     assert_equal(response.context['view']['contents'], "sdf\n")
 
     # ensure compression note is rendered
@@ -699,7 +699,7 @@ class TestFileBrowserWithHadoop(object):
     assert_true('Output rendered from compressed' in response.content, response.content)
 
     # offset should do nothing
-    response = self.c.get('/filebrowser/view%s/test-view.gz?compression=gzip&offset=1' % prefix)
+    response = self.c.get('/filebrowser/view=%s/test-view.gz?compression=gzip&offset=1' % prefix)
     assert_true("Offsets are not supported" in response.context['message'], response.context['message'])
 
     f = self.cluster.fs.open(prefix + '/test-view2.gz', "w")
@@ -707,11 +707,11 @@ class TestFileBrowserWithHadoop(object):
     f.close()
 
     # we shouldn't autodetect non gzip files
-    response = self.c.get('/filebrowser/view%s/test-view2.gz' % prefix)
+    response = self.c.get('/filebrowser/view=%s/test-view2.gz' % prefix)
     assert_equal(response.context['view']['contents'], "hello")
 
     # we should fail to do a bad thing if they specify compression when it's not set.
-    response = self.c.get('/filebrowser/view%s/test-view2.gz?compression=gzip' % prefix)
+    response = self.c.get('/filebrowser/view=%s/test-view2.gz?compression=gzip' % prefix)
     assert_true("Failed to decompress" in response.context['message'])
 
 
@@ -731,10 +731,10 @@ class TestFileBrowserWithHadoop(object):
     view_i18n_helper(self.c, self.cluster, 'johab', content)
 
     # Test that the default view is home
-    response = self.c.get('/filebrowser/view/')
+    response = self.c.get('/filebrowser/view=/')
     assert_equal(response.context['path'], '/')
-    response = self.c.get('/filebrowser/view/?default_to_home=1')
-    assert_equal("http://testserver/filebrowser/view/user/test", response["location"])
+    response = self.c.get('/filebrowser/view=/?default_to_home=1')
+    assert_equal("http://testserver/filebrowser/view=/user/test", response["location"])
 
 
   def test_view_access(self):
@@ -744,10 +744,10 @@ class TestFileBrowserWithHadoop(object):
     self.cluster.fs.mkdir(NO_PERM_DIR, mode='700')
 
     c_no_perm = make_logged_in_client(username='no_home')
-    response = c_no_perm.get('/filebrowser/view%s' % NO_PERM_DIR)
+    response = c_no_perm.get('/filebrowser/view=%s' % NO_PERM_DIR)
     assert_true('Cannot access' in response.context['message'])
 
-    response = self.c.get('/filebrowser/view/test-does-not-exist')
+    response = self.c.get('/filebrowser/view=/test-does-not-exist')
     assert_true('Cannot access' in response.context['message'])
 
 
@@ -962,20 +962,20 @@ class TestFileBrowserWithHadoop(object):
     self.c.post('/filebrowser/rmtree?skip_trash=true', dict(path=[HOME_TRASH_DIR2]))
 
     # No trash folder
-    response = self.c.get('/filebrowser/view/user/test?default_to_trash', follow=True)
+    response = self.c.get('/filebrowser/view=/user/test?default_to_trash', follow=True)
 
     assert_equal([], response.redirect_chain)
 
     self.c.post('/filebrowser/rmtree', dict(path=[PATH_1]))
 
     # We have a trash folder so a redirect (Current not always there)
-    response = self.c.get('/filebrowser/view/user/test?default_to_trash', follow=True)
+    response = self.c.get('/filebrowser/view=/user/test?default_to_trash', follow=True)
     assert_true(any(['.Trash' in page for page, code in response.redirect_chain]), response.redirect_chain)
 
     self.c.post('/filebrowser/rmtree?skip_trash=true', dict(path=[HOME_TRASH_DIR]))
 
     # No home trash, just regular root trash
-    response = self.c.get('/filebrowser/view/user/test?default_to_trash', follow=True)
+    response = self.c.get('/filebrowser/view=/user/test?default_to_trash', follow=True)
     assert_true(any(['.Trash' in page for page, code in response.redirect_chain]), response.redirect_chain)
 
 def view_i18n_helper(c, cluster, encoding, content):
@@ -992,10 +992,10 @@ def view_i18n_helper(c, cluster, encoding, content):
     f.write(bytestring)
     f.close()
 
-    response = c.get('/filebrowser/view%s?encoding=%s' % (filename, encoding))
+    response = c.get('/filebrowser/view=%s?encoding=%s' % (filename, encoding))
     assert_equal(response.context['view']['contents'], content)
 
-    response = c.get('/filebrowser/view%s?encoding=%s&end=8&begin=1' % (filename, encoding))
+    response = c.get('/filebrowser/view=%s?encoding=%s&end=8&begin=1' % (filename, encoding))
     assert_equal(response.context['view']['contents'],
                  unicode(bytestring[0:8], encoding, errors='replace'))
   finally:
@@ -1010,7 +1010,7 @@ def edit_i18n_helper(c, cluster, encoding, contents_pass_1, contents_pass_2):
   filename = prefix + u'//test-filebrowser//./test-edit-carácter-internacional with space and () en-hello pt-Olá ch-你好 ko-안녕 ru-Здравствуйте'
 
   # File doesn't exist - should be empty
-  edit_url = '/filebrowser/edit' + filename
+  edit_url = '/filebrowser/edit=' + filename
   response = c.get(edit_url)
   assert_equal(response.context['form'].data['path'], filename)
   assert_equal(response.context['form'].data['contents'], "")
@@ -1052,8 +1052,10 @@ def edit_i18n_helper(c, cluster, encoding, contents_pass_1, contents_pass_2):
   finally:
     cleanup_file(cluster, filename)
 
+
 def test_location_to_url():
-  assert_equal('/filebrowser/view/var/lib/hadoop-hdfs', location_to_url('/var/lib/hadoop-hdfs', False))
-  assert_equal('/filebrowser/view/var/lib/hadoop-hdfs', location_to_url('hdfs://localhost:8020/var/lib/hadoop-hdfs'))
-  assert_equal('/filebrowser/view/', location_to_url('hdfs://localhost:8020'))
-  assert_equal(None, location_to_url('thrift://10.0.0.1:9083'))
+  prefix = '/filebrowser/view='
+  assert_equal(prefix + '/var/lib/hadoop-hdfs', location_to_url('/var/lib/hadoop-hdfs', False))
+  assert_equal(prefix + '/var/lib/hadoop-hdfs', location_to_url('hdfs://localhost:8020/var/lib/hadoop-hdfs'))
+  assert_equal(prefix + '/', location_to_url('hdfs://localhost:8020'))
+  assert_equal(prefix + 's3%3A//bucket/key', location_to_url('s3://bucket/key'))

+ 8 - 8
apps/jobbrowser/src/jobbrowser/tests.py

@@ -782,35 +782,35 @@ def test_make_log_links():
 
   # FileBrowser
   assert_equal(
-      """<a href="/filebrowser/view/user/romain/tmp" target="_blank">hdfs://localhost:8020/user/romain/tmp</a>  &lt;dir&gt;""",
+      """<a href="/filebrowser/view=/user/romain/tmp" target="_blank">hdfs://localhost:8020/user/romain/tmp</a>  &lt;dir&gt;""",
       LinkJobLogs._make_links('hdfs://localhost:8020/user/romain/tmp  <dir>')
   )
   assert_equal(
-      """<a href="/filebrowser/view/user/romain/tmp" target="_blank">hdfs://localhost:8020/user/romain/tmp</a>&lt;dir&gt;""",
+      """<a href="/filebrowser/view=/user/romain/tmp" target="_blank">hdfs://localhost:8020/user/romain/tmp</a>&lt;dir&gt;""",
       LinkJobLogs._make_links('hdfs://localhost:8020/user/romain/tmp<dir>')
   )
   assert_equal(
-      """output: <a href="/filebrowser/view/user/romain/tmp" target="_blank">/user/romain/tmp</a>  &lt;dir&gt;""",
+      """output: <a href="/filebrowser/view=/user/romain/tmp" target="_blank">/user/romain/tmp</a>  &lt;dir&gt;""",
       LinkJobLogs._make_links('output: /user/romain/tmp  <dir>')
   )
   assert_equal(
-      'Successfully read 3760 records (112648 bytes) from: &quot;<a href="/filebrowser/view/user/hue/pig/examples/data/midsummer.txt" target="_blank">/user/hue/pig/examples/data/midsummer.txt</a>&quot;',
+      'Successfully read 3760 records (112648 bytes) from: &quot;<a href="/filebrowser/view=/user/hue/pig/examples/data/midsummer.txt" target="_blank">/user/hue/pig/examples/data/midsummer.txt</a>&quot;',
       LinkJobLogs._make_links('Successfully read 3760 records (112648 bytes) from: "/user/hue/pig/examples/data/midsummer.txt"')
   )
   assert_equal(
-      'data,upper_case  MAP_ONLY  <a href="/filebrowser/view/user/romain/out/fffff" target="_blank">hdfs://localhost:8020/user/romain/out/fffff</a>,',
+      'data,upper_case  MAP_ONLY  <a href="/filebrowser/view=/user/romain/out/fffff" target="_blank">hdfs://localhost:8020/user/romain/out/fffff</a>,',
       LinkJobLogs._make_links('data,upper_case  MAP_ONLY  hdfs://localhost:8020/user/romain/out/fffff,')
   )
   assert_equal(
-      'MAP_ONLY  <a href="/filebrowser/view/user/romain/out/fffff" target="_blank">hdfs://localhost:8020/user/romain/out/fffff</a>\n2013',
+      'MAP_ONLY  <a href="/filebrowser/view=/user/romain/out/fffff" target="_blank">hdfs://localhost:8020/user/romain/out/fffff</a>\n2013',
       LinkJobLogs._make_links('MAP_ONLY  hdfs://localhost:8020/user/romain/out/fffff\n2013')
   )
   assert_equal(
-      ' <a href="/filebrowser/view/jobs.tsv" target="_blank">/jobs.tsv</a> ',
+      ' <a href="/filebrowser/view=/jobs.tsv" target="_blank">/jobs.tsv</a> ',
       LinkJobLogs._make_links(' /jobs.tsv ')
   )
   assert_equal(
-      '<a href="/filebrowser/view/user/romain/job_pos_2012.tsv" target="_blank">hdfs://localhost:8020/user/romain/job_pos_2012.tsv</a>',
+      '<a href="/filebrowser/view=/user/romain/job_pos_2012.tsv" target="_blank">hdfs://localhost:8020/user/romain/job_pos_2012.tsv</a>',
       LinkJobLogs._make_links('hdfs://localhost:8020/user/romain/job_pos_2012.tsv')
   )
 

+ 0 - 1
apps/metastore/src/metastore/templates/describe_partitions.mako

@@ -14,7 +14,6 @@
 ## See the License for the specific language governing permissions and
 ## limitations under the License.
 <%!
-  from filebrowser.views import location_to_url
   from desktop.views import commonheader, commonfooter
   from django.utils.translation import ugettext as _
 %>

+ 1 - 1
apps/oozie/src/oozie/templates/editor/edit_workflow.mako

@@ -45,7 +45,7 @@ ${ layout.menubar(section='workflows') }
         <li><a href="#properties"><i class="fa fa-cog"></i> ${ _('Properties') }</a></li>
         % if user_can_edit_job:
           <li>
-            <a data-bind="attr: {href: '/filebrowser/view' + fixLeadingSlash(deployment_dir()) }" target="_blank" title="${ _('Go upload additional files and libraries to the deployment directory on HDFS') }" rel="tooltip" data-placement="right"><i class="fa fa-folder-open"></i> ${ _('Workspace') }</a>
+            <a data-bind="attr: {href: '/filebrowser/view=' + fixLeadingSlash(deployment_dir()) }" target="_blank" title="${ _('Go upload additional files and libraries to the deployment directory on HDFS') }" rel="tooltip" data-placement="right"><i class="fa fa-folder-open"></i> ${ _('Workspace') }</a>
           </li>
         % endif
 

+ 3 - 3
apps/oozie/src/oozie/templates/editor2/common_workflow.mako

@@ -549,13 +549,13 @@
 <script type="text/html" id="common-fs-link">
 <!-- ko if: $data.path.length > 0 -->
   <!-- ko if: with_label -->
-    <a data-bind="attr: {href: '/filebrowser/view' + ($data.path[0] != '/' ? $root.workflow.properties.deployment_dir() + '/' : '') + $data.path , title: '${ _('Open') } '+ $data.path }" target="_blank">
+    <a data-bind="attr: {href: '/filebrowser/view=' + ($data.path[0] != '/' ? $root.workflow.properties.deployment_dir() + '/' : '') + $data.path , title: '${ _('Open') } '+ $data.path }" target="_blank">
       <span data-bind="text: $data.path.lastIndexOf('/') == $data.path.length - 1 ? $data.path : $data.path.split('/').pop()"></span>
     </a>
   <!-- /ko -->
 
    <!-- ko if: ! with_label -->
-     <a data-bind="attr: {href: '/filebrowser/view' + ($data.path[0] != '/' ? $root.workflow.properties.deployment_dir() + '/' : '') + $data.path }" target="_blank" title="${ _('Open') }">
+     <a data-bind="attr: {href: '/filebrowser/view=' + ($data.path[0] != '/' ? $root.workflow.properties.deployment_dir() + '/' : '') + $data.path }" target="_blank" title="${ _('Open') }">
        <i class="fa fa-external-link-square"></i>
      </a>
    <!-- /ko -->
@@ -565,7 +565,7 @@
 
 <script type="text/html" id="param-fs-link">
   <!-- ko if: path.split('=', 2)[1] && path.split('=', 2)[1].charAt(0) == '/' -->
-    <a data-bind="attr: {href: '/filebrowser/view' + $data.path.split('=', 2)[1] }" target="_blank" title="${ _('Open') }">
+    <a data-bind="attr: {href: '/filebrowser/view=' + $data.path.split('=', 2)[1] }" target="_blank" title="${ _('Open') }">
       <i class="fa fa-external-link-square"></i>
     </a>
   <!-- /ko -->

+ 1 - 1
apps/oozie/src/oozie/templates/editor2/coordinator_editor.mako

@@ -299,7 +299,7 @@ ${ layout.menubar(section='coordinators', is_editor=True, pullright=buttons) }
                   </span>
                   <span data-bind="visible: dataset_variable().length > 0 && instance_choice() != 'range'">
                     ${ _('Will convert to') }
-                    <a target="_blank" data-bind="text: convertDatasetVariables(dataset_variable(), same_start(), start(), same_frequency(), frequency_unit(), start_instance(), instance_choice()), attr: {'href': '/filebrowser/view' + convertDatasetVariables(dataset_variable(), same_start(), start(), same_frequency(), frequency_unit(), start_instance(), instance_choice())}"></a>
+                    <a target="_blank" data-bind="text: convertDatasetVariables(dataset_variable(), same_start(), start(), same_frequency(), frequency_unit(), start_instance(), instance_choice()), attr: {'href': '/filebrowser/view=' + convertDatasetVariables(dataset_variable(), same_start(), start(), same_frequency(), frequency_unit(), start_instance(), instance_choice())}"></a>
                   </span>
                   </a>
                 </span>

+ 1 - 1
apps/oozie/src/oozie/templates/editor2/workflow_editor.mako

@@ -55,7 +55,7 @@ ${ commonheader(_("Workflow Editor"), "Oozie", user, "40px") | n,unicode }
 
     <a title="${ _('Workspace') }" target="_blank" rel="tooltip" data-placement="right"
         data-original-title="${ _('Go upload additional files and libraries to the deployment directory on HDFS') }"
-        data-bind="css: {'btn': true}, attr: { href: '/filebrowser/view' + $root.workflow.properties.deployment_dir() }">
+        data-bind="css: {'btn': true}, attr: { href: '/filebrowser/view=' + $root.workflow.properties.deployment_dir() }">
       <i class="fa fa-fw fa-folder-open"></i>
     </a>
 

+ 5 - 5
apps/oozie/src/oozie/templates/utils.inc.mako

@@ -94,9 +94,9 @@
     <% path = Hdfs.urlsplit(url)[2] %>
     % if path:
       % if path.startswith(posixpath.sep):
-        <a href="/filebrowser/view${path}">${ url }</a>
+        <a href="/filebrowser/view=${path}">${ url }</a>
       % else:
-        <a href="/filebrowser/home_relative_view/${path}">${ url }</a>
+        <a href="/filebrowser/home_relative_view=/${path}">${ url }</a>
       % endif
     % else:
       ${ url }
@@ -111,9 +111,9 @@
     <% path = Hdfs.urlsplit(url)[2] %>
     % if path:
       % if path.startswith(posixpath.sep):
-        /filebrowser/view${path}
+        /filebrowser/view=${path}
       % else:
-        /filebrowser/home_relative_view/${path}
+        /filebrowser/home_relative_view=/${path}
       % endif
     % else:
       javascript:void(0)
@@ -360,7 +360,7 @@
         // check if it's a relative path
         var pathAddition = "";
         if ($.trim(inputElement.val()) != "") {
-          var checkPath = "/filebrowser/chooser${ workflow.deployment_dir }" + "/" + inputElement.val();
+          var checkPath = "/filebrowser/chooser=${ workflow.deployment_dir }" + "/" + inputElement.val();
           $.getJSON(checkPath, function (data) {
             pathAddition = "${ workflow.deployment_dir }/";
             callFileChooser();

+ 2 - 2
apps/pig/src/pig/models.py

@@ -160,9 +160,9 @@ def hdfs_link(url):
     path = Hdfs.urlsplit(url)[2]
     if path:
       if path.startswith(posixpath.sep):
-        return "/filebrowser/view" + path
+        return "/filebrowser/view=" + path
       else:
-        return "/filebrowser/home_relative_view/" + path
+        return "/filebrowser/home_relative_view=/" + path
     else:
       return url
   else:

+ 3 - 3
apps/pig/src/pig/templates/app.mako

@@ -927,7 +927,7 @@ ${ commonshare() | n,unicode }
         CodeMirror.isTable = false;
         if (_partial.toLowerCase().indexOf("load") > -1 || _partial.toLowerCase().indexOf("into") > -1) {
           var _path = _partial.substring(_partial.lastIndexOf("'") + 1);
-          var _autocompleteUrl = "/filebrowser/view";
+          var _autocompleteUrl = "/filebrowser/view=";
           if (_path.indexOf("/") == 0) {
             _autocompleteUrl += _path.substr(0, _path.lastIndexOf("/"));
           }
@@ -1000,11 +1000,11 @@ ${ commonshare() | n,unicode }
             var _path = _partial.substring(_partial.lastIndexOf("'") + 1);
             if (_path[0] == "/") {
               if (_path.lastIndexOf("/") != 0) {
-                showHdfsAutocomplete("/filebrowser/view" + _partial.substring(_partial.lastIndexOf("'") + 1) + "?format=json", false);
+                showHdfsAutocomplete("/filebrowser/view=" + _partial.substring(_partial.lastIndexOf("'") + 1) + "?format=json", false);
               }
             }
             else {
-              showHdfsAutocomplete("/filebrowser/view" + USER_HOME + _partial.substring(_partial.lastIndexOf("'") + 1) + "?format=json", false);
+              showHdfsAutocomplete("/filebrowser/view=" + USER_HOME + _partial.substring(_partial.lastIndexOf("'") + 1) + "?format=json", false);
             }
           }
         }

+ 3 - 3
apps/search/src/search/static/search/js/search.utils.js

@@ -49,17 +49,17 @@ function addTemplateFunctions(item) {
 
   item.hue_fn_preview = function () {
     return function (val) {
-      return '<a href="/filebrowser/view/' + $.trim(Mustache.render(val, item)) + '">' + $.trim(Mustache.render(val, item)) + '</a>';
+      return '<a href="/filebrowser/view=/' + $.trim(Mustache.render(val, item)) + '">' + $.trim(Mustache.render(val, item)) + '</a>';
     }
   };
   item.hue_fn_embeddeddownload = function () {
     return function (val) {
-      return '<a href="/filebrowser/download/' + $.trim(Mustache.render(val, item)) + '?disposition=inline">' + $.trim(Mustache.render(val, item)) + '</a>';
+      return '<a href="/filebrowser/download=/' + $.trim(Mustache.render(val, item)) + '?disposition=inline">' + $.trim(Mustache.render(val, item)) + '</a>';
     }
   };
   item.hue_fn_download = function () {
     return function (val) {
-      return '<a href="/filebrowser/download/' + $.trim(Mustache.render(val, item)) + '>' + $.trim(Mustache.render(val, item)) + '</a>';
+      return '<a href="/filebrowser/download=/' + $.trim(Mustache.render(val, item)) + '>' + $.trim(Mustache.render(val, item)) + '</a>';
     }
   };
   item.hue_fn_date = function () {

+ 1 - 1
apps/security/src/security/static/security/js/hdfs.ko.js

@@ -376,7 +376,7 @@ var Assist = function (vm, assist) {
   }
 
   self.openPath = function (obj) {
-    window.open("/filebrowser/view" + obj.path(), '_blank');
+    window.open("/filebrowser/view=" + obj.path(), '_blank');
   }
 
   self.loadParents = function (breadcrumbs) {

+ 1 - 1
apps/security/src/security/static/security/js/hive.ko.js

@@ -647,7 +647,7 @@ var Assist = function (vm, initial) {
     e.stopPropagation();
     e.stopImmediatePropagation();
     self.fetchHivePath(obj.path(), function(data){
-      location.href = "/security/hdfs#" + data.hdfs_link.substring("/filebrowser/view".length);
+      location.href = "/security/hdfs#" + data.hdfs_link.substring("/filebrowser/view=".length);
     });
   }
 

+ 5 - 5
apps/security/src/security/templates/hdfs.mako

@@ -97,7 +97,7 @@ ${ layout.menubar(section='hdfs') }
               <div class="path-container">
                 <div class="input-append span12">
                   <input id="path" class="path" type="text" data-bind="value: $root.assist.path" autocomplete="off" />
-                  <a data-bind="attr: { href: '/filebrowser/view' + $root.assist.path() }" target="_blank" title="${ _('Open in File Browser') }" class="btn btn-inverse">
+                  <a data-bind="attr: { href: '/filebrowser/view=' + $root.assist.path() }" target="_blank" title="${ _('Open in File Browser') }" class="btn btn-inverse">
                     <i class="fa fa-external-link"></i>
                   </a>
                 </div>
@@ -145,7 +145,7 @@ ${ layout.menubar(section='hdfs') }
 
                   <div class="acl-panel-content">
                     <span class="fake-pre" data-bind="visible: $root.assist.showAclsAsText">
-                      # file: <a class="force-word-break" data-bind="attr: { href: '/filebrowser/view' + $root.assist.path() }, text: $root.assist.path()" target="_blank"></a><br/>
+                      # file: <a class="force-word-break" data-bind="attr: { href: '/filebrowser/view=' + $root.assist.path() }, text: $root.assist.path()" target="_blank"></a><br/>
                       # owner: <span data-bind="text: $root.assist.owner"></span><br/>
                       # group: <span data-bind="text: $root.assist.group"></span><br/>
                       <div data-bind="foreach: $root.assist.regularAcls">
@@ -158,7 +158,7 @@ ${ layout.menubar(section='hdfs') }
 
                     <span data-bind="visible: ! $root.assist.showAclsAsText()">
                       <h4>${ _('Path') }</h4>
-                      <a class="force-word-break" data-bind="attr: { href: '/filebrowser/view' + $root.assist.path() }, text: $root.assist.path()" target="_blank" title="${ _('Open in File Browser') }" rel="tooltip"></a>
+                      <a class="force-word-break" data-bind="attr: { href: '/filebrowser/view=' + $root.assist.path() }, text: $root.assist.path()" target="_blank" title="${ _('Open in File Browser') }" rel="tooltip"></a>
 
                       <h4>${ _('User/Group') }</h4>
                       <i class="fa fa-user" style="color: #999999" title="${_('User')}"></i> <span title="${_('User')}" data-bind="text: $root.assist.owner"></span>&nbsp;
@@ -231,7 +231,7 @@ ${ layout.menubar(section='hdfs') }
       <div class="span4">
         <h4>${ _('to apply to the selection') }</h4>
         <ul class="unstyled modal-panel" data-bind="foreach: $root.assist.checkedItems">
-          <li><a class="force-word-break" data-bind="attr: { href: '/filebrowser/view' + path }, text: path" target="_blank" title="${ _('Open in File Browser') }" rel="tooltip"></a></li>
+          <li><a class="force-word-break" data-bind="attr: { href: '/filebrowser/view=' + path }, text: path" target="_blank" title="${ _('Open in File Browser') }" rel="tooltip"></a></li>
         </ul>
       </div>
     </div>
@@ -242,7 +242,7 @@ ${ layout.menubar(section='hdfs') }
         <h4>${ _('ACLs to apply') }</h4>
 
         <span class="fake-pre modal-panel">
-          # file: <a class="force-word-break" data-bind="attr: { href: '/filebrowser/view' + $root.assist.path() }, text: $root.assist.path()" target="_blank"></a><br/>
+          # file: <a class="force-word-break" data-bind="attr: { href: '/filebrowser/view=' + $root.assist.path() }, text: $root.assist.path()" target="_blank"></a><br/>
           # owner: <span data-bind="text: $root.assist.owner"></span><br/>
           # group: <span data-bind="text: $root.assist.group"></span><br/>
           <div data-bind="foreach: $root.assist.regularAcls">

+ 1 - 1
apps/security/src/security/templates/hive.mako

@@ -114,7 +114,7 @@ ${ layout.menubar(section='hive') }
     <!-- /ko -->
 
     <!-- ko if: privilegeType() == 'uri' -->
-      <i class="fa fa-long-arrow-right"></i> <i class="fa fa-file-o"></i> <i class="fa fa-long-arrow-right"></i> <a data-bind="attr: { href: '/filebrowser/view/' + URI().split('/')[3] }" target="_blank"><span data-bind="text: URI"></span></a>
+      <i class="fa fa-long-arrow-right"></i> <i class="fa fa-file-o"></i> <i class="fa fa-long-arrow-right"></i> <a data-bind="attr: { href: '/filebrowser/view=/' + URI().split('/')[3] }" target="_blank"><span data-bind="text: URI"></span></a>
     <!-- /ko -->
 
     <i class="fa fa-long-arrow-right"></i> action=<span data-bind="text: action"></span>

+ 2 - 2
apps/sqoop/src/sqoop/static/sqoop/js/sqoop.jobs.js

@@ -127,7 +127,7 @@ var jobs = (function($) {
             });
           }
         });
-        return (output_directory) ? '/filebrowser/view' + output_directory : null;
+        return (output_directory) ? '/filebrowser/view=' + output_directory : null;
       });
       self.inputDirectoryFilebrowserURL = ko.computed(function() {
         var input_directory = null;
@@ -140,7 +140,7 @@ var jobs = (function($) {
             });
           }
         });
-        return (input_directory) ? '/filebrowser/view' + input_directory : null;
+        return (input_directory) ? '/filebrowser/view=' + input_directory : null;
       });
       self.storageType = ko.computed(function() {
         var storage_type = null;

+ 1 - 1
desktop/core/src/desktop/models.py

@@ -820,7 +820,7 @@ def get_data_link(meta):
     elif 'fam' in meta:
       link += '[%(fam)s]' % meta
   elif meta['type'] == 'hdfs':
-    link = '/filebrowser/view%(path)s' % meta # Could add a byte #
+    link = '/filebrowser/view=%(path)s' % meta # Could add a byte #
   elif meta['type'] == 'link':
     link = meta['link']
   elif meta['type'] == 'hive':

+ 1 - 1
desktop/core/src/desktop/static/desktop/js/jquery.filechooser.js

@@ -106,7 +106,7 @@
         else {
           $(_parent.element).html("<i style=\"font-size: 24px; color: #DDD\" class=\"fa fa-spinner fa-spin\"></i>");
         }
-        $.getJSON("/filebrowser/chooser" + path, function (data) {
+        $.getJSON("/filebrowser/chooser=" + path, function (data) {
             $(_parent.element).empty();
             path = data.current_dir_path; // use real path.
             var _flist = $("<ul>").addClass("unstyled").css("margin-left", "2px");

+ 1 - 1
desktop/core/src/desktop/static/desktop/js/jquery.hdfsautocomplete.js

@@ -208,7 +208,7 @@
       }
     });
 
-    var BASE_PATH = "/filebrowser/view";
+    var BASE_PATH = "/filebrowser/view=";
     var _currentFiles = [];
 
     function showHdfsAutocomplete(callback) {

+ 1 - 1
desktop/core/src/desktop/static/desktop/js/jquery.hdfstree.js

@@ -125,7 +125,7 @@
     var _root = $("<ul>").addClass("content unstyled").attr("data-path", "__JHUEHDFSTREE__ROOT__").attr("data-loaded", "true");
     _root.appendTo(_tree.find("li"));
 
-    var BASE_PATH = "/filebrowser/view";
+    var BASE_PATH = "/filebrowser/view=";
     var _currentFiles = [];
     
     function escapeSingleQuote(path) {

+ 1 - 1
desktop/core/src/desktop/tests.py

@@ -944,5 +944,5 @@ def test_get_data_link():
   assert_equal('/hbase/#Cluster/document_demo/query/20150527[f1]', get_data_link({'type': 'hbase', 'table': 'document_demo', 'row_key': '20150527', 'fam': 'f1'}))
   assert_equal('/hbase/#Cluster/document_demo/query/20150527[f1:c1]', get_data_link({'type': 'hbase', 'table': 'document_demo', 'row_key': '20150527', 'fam': 'f1', 'col': 'c1'}))
 
-  assert_equal('/filebrowser/view/data/hue/1', get_data_link({'type': 'hdfs', 'path': '/data/hue/1'}))
+  assert_equal('/filebrowser/view=/data/hue/1', get_data_link({'type': 'hdfs', 'path': '/data/hue/1'}))
   assert_equal('/metastore/table/default/sample_07', get_data_link({'type': 'hive', 'database': 'default', 'table': 'sample_07'}))