diff --git a/public/js/app.js b/public/js/app.js index 540aab0e..244cdde9 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -1748,8 +1748,31 @@ angular.module('cerebro').controller('RestController', ['$scope', '$http', if (path.substring(0, 1) !== '/') { path = '/' + path; } - var body = JSON.stringify($scope.editor.getValue(), undefined, 1); - var curl = 'curl -X' + method + ' \'' + $scope.host + path + '\''; + + var matchesAPI = function(path, api) { + return path.indexOf(api) === (path.length - api.length); + }; + + var contentType = 'application/json'; + var body = ''; + + try { + if (matchesAPI(path, '_bulk') || matchesAPI(path, '_msearch')) { + contentType = 'application/x-ndjson'; + body = $scope.editor.getStringValue().split('\n').map(function(line) { + return line === '' ? '\n' : JSON.stringify(JSON.parse(line)); + }).join('\n'); + } else { + body = JSON.stringify($scope.editor.getValue(), undefined, 1); + } + } catch (e) { + AlertService.error('Unexpected content format for [' + path + ']'); + return; + } + + var curl = 'curl'; + curl += ' -H \'Content-type: ' + contentType + '\''; + curl += ' -X' + method + ' \'' + $scope.host + path + '\''; if (['POST', 'PUT'].indexOf(method) >= 0) { curl += ' -d \'' + body + '\''; } diff --git a/src/app/components/rest/controller.js b/src/app/components/rest/controller.js index 4de374fb..ef44871e 100644 --- a/src/app/components/rest/controller.js +++ b/src/app/components/rest/controller.js @@ -81,8 +81,31 @@ angular.module('cerebro').controller('RestController', ['$scope', '$http', if (path.substring(0, 1) !== '/') { path = '/' + path; } - var body = JSON.stringify($scope.editor.getValue(), undefined, 1); - var curl = 'curl -X' + method + ' \'' + $scope.host + path + '\''; + + var matchesAPI = function(path, api) { + return path.indexOf(api) === (path.length - api.length); + }; + + var contentType = 'application/json'; + var body = ''; + + try { + if (matchesAPI(path, '_bulk') || matchesAPI(path, '_msearch')) { + contentType = 'application/x-ndjson'; + body = $scope.editor.getStringValue().split('\n').map(function(line) { + return line === '' ? '\n' : JSON.stringify(JSON.parse(line)); + }).join('\n'); + } else { + body = JSON.stringify($scope.editor.getValue(), undefined, 1); + } + } catch (e) { + AlertService.error('Unexpected content format for [' + path + ']'); + return; + } + + var curl = 'curl'; + curl += ' -H \'Content-type: ' + contentType + '\''; + curl += ' -X' + method + ' \'' + $scope.host + path + '\''; if (['POST', 'PUT'].indexOf(method) >= 0) { curl += ' -d \'' + body + '\''; } diff --git a/tests/components/rest/controller.tests.js b/tests/components/rest/controller.tests.js index 55e5a0d8..de470a45 100644 --- a/tests/components/rest/controller.tests.js +++ b/tests/components/rest/controller.tests.js @@ -10,9 +10,18 @@ describe('RestController', function() { this.AlertService = $injector.get('AlertService'); this.ModalService = $injector.get('ModalService'); this.AceEditorService = $injector.get('AceEditorService'); + this.ClipboardService = $injector.get('ClipboardService'); this.createController = function() { return $controller('RestController', - {$scope: this.scope}, this.$http, this.$window, this.RestDataService, this.AlertService, this.ModalService, this.AceEditorService); + {$scope: this.scope}, + this.$http, + this.$window, + this.RestDataService, + this.AlertService, + this.ModalService, + this.AceEditorService, + this.ClipboardService + ); }; this._controller = this.createController(); })); @@ -129,7 +138,7 @@ describe('RestController', function() { it('loads all possible autocompletion options', function() { this.scope.indices = []; this.scope.updateOptions(""); - expect(this.scope.options).toEqual(['_msearch', '_search', '_suggest']); + expect(this.scope.options).toEqual(['_msearch', '_search']); }); it('skip autocompletion if indices is absent', function() { this.scope.indices = undefined; @@ -183,4 +192,64 @@ describe('RestController', function() { }); }); + describe('copyAsCURLCommand', function() { + it('copy json call to clipboard', function() { + this.scope.path = 'wot/_search'; + this.scope.method = 'GET'; + this.scope.host = 'http://localhost:9200'; + this.scope.editor = { getValue: function(){} }; + spyOn(this.scope.editor, 'getValue').and.returnValue({'k': 'v'}); + spyOn(this.ClipboardService, 'copy'); + this.scope.copyAsCURLCommand(); + expect(this.scope.editor.getValue).toHaveBeenCalled(); + expect(this.ClipboardService.copy).toHaveBeenCalledWith( + 'curl -H \'Content-type: application/json\' -XGET \'http://localhost:9200/wot/_search\'', + jasmine.any(Function), + jasmine.any(Function) + ); + }); + + it('copy x-ndjson call to clipboard for _bulk', function() { + this.scope.path = 'wot/_bulk'; + this.scope.method = 'POST'; + this.scope.host = 'http://localhost:9200'; + this.scope.editor = { getStringValue: function(){} }; + var body = '{"header": ""}\n{"query": "query"}\n{"header": ""}\n{"query": "query"}\n'; + spyOn(this.scope.editor, 'getStringValue').and.returnValue(body); + spyOn(this.ClipboardService, 'copy'); + this.scope.copyAsCURLCommand(); + expect(this.scope.editor.getStringValue).toHaveBeenCalled(); + expect(this.ClipboardService.copy).toHaveBeenCalledWith( + 'curl -H \'Content-type: application/x-ndjson\' -XPOST \'http://localhost:9200/wot/_bulk\' -d \'{"header":""}\n' + + '{"query":"query"}\n' + + '{"header":""}\n' + + '{"query":"query"}\n' + + '\n\'', + jasmine.any(Function), + jasmine.any(Function) + ); + }); + + it('copy x-ndjson call to clipboard for _msearch', function() { + this.scope.path = 'wot/_msearch'; + this.scope.method = 'POST'; + this.scope.host = 'http://localhost:9200'; + this.scope.editor = { getStringValue: function(){} }; + var body = '{"header": ""}\n{"query": "query"}\n{"header": ""}\n{"query": "query"}\n'; + spyOn(this.scope.editor, 'getStringValue').and.returnValue(body); + spyOn(this.ClipboardService, 'copy'); + this.scope.copyAsCURLCommand(); + expect(this.scope.editor.getStringValue).toHaveBeenCalled(); + expect(this.ClipboardService.copy).toHaveBeenCalledWith( + 'curl -H \'Content-type: application/x-ndjson\' -XPOST \'http://localhost:9200/wot/_msearch\' -d \'{"header":""}\n' + + '{"query":"query"}\n' + + '{"header":""}\n' + + '{"query":"query"}\n' + + '\n\'', + jasmine.any(Function), + jasmine.any(Function) + ); + }); + }); + });