How to rewrite this Curl call (to the Apache Hue REST API) as (JQuery) AJAX?

I need to call the Apache Hue REST API via AJAX calls (using JQuery for example) and so I need to convert the following curl call to AJAX (taken from https://docs.gethue.com/developer/api/#execute-a-query )

curl -X POST https://demo.gethue.com/notebook/api/execute/hive --data 'executable={"statement":"SHOW TABLES","database":"default"}&notebook={"type":"query","snippets":[{"id":1,"statement_raw":"SHOW TABLES","type":"hive","variables":[]}],"name":"","isSaved":false,"sessions":[]}&snippet={"id":1,"type":"hive","result":{},"statement":"SHOW TABLES","properties":{}}'

(obviously I’m using the URL of my Hue installation and my query would be something like “SELECT * FROM my_table LIMIT 10;”)

This was one of my attempts, but I always get back an error in the console {status: -1, message: "'type'"}

$.ajax({
    url: "/notebook/api/execute/hive/",
    type: 'POST',
    processData: false,
    data: {"executable": JSON.stringify({"statement":"SELECT * FROM my_table LIMIT 10","database":"default"}), "notebook": JSON.stringify({"type":"query","snippets":[{"id":1,"statement_raw":"SELECT * FROM my_table LIMIT 10","type":"hive","variables":[]}],"name":"","isSaved":false,"sessions":[]}), "snippet": JSON.stringify({"id":1,"type":"hive","result":{},"statement":"SELECT * FROM my_table LIMIT 10","properties":{}})},
    success: function(data) { console.log(data); },
    error: function(err) { console.log(err); }
});

If I remove the processData: false line I get the error: {status: -1, message: "'handle'"}

However I tried the following in Chrome devtools console (I am logged into Hue via the web interface on the same page as the console) and it works fine, so I know the above should work if I can get the syntax right:

$.ajax({
    url: "/notebook/api/autocomplete/",
    type: 'POST',
    data: {"snippet": JSON.stringify({"type": "hive"})},
    success: function(data) {console.log(data); }
});

For reference, the curl equivalent of that is here (although it seems I don’t need to specify CRSF or sessionID because I’m already logged in via the interface in the same browser window as the console):

curl -X POST https://demo.gethue.com/notebook/api/autocomplete/ --data 'snippet={"type":"hive"}' --cookie "csrftoken=XUFgN1WPZNlaJtBeBDtBvwzrOFqRXIaMlNJv4mdvsS2bIE2Lb8LRmCh5cPUBnBdk;sessionid=9cdltfee1q1zmt8b7slsjcomtxzgvgfz" -H "X-CSRFToken: XUFgN1WPZNlaJtBeBDtBvwzrOFqRXIaMlNJv4mdvsS2bIE2Lb8LRmCh5cPUBnBdk

Any suggestions very welcome!
Thanks

If you are trying on demo.gethue.com it won’t work as it, as there the Connectors are enabled. cf. Beta section in https://docs.gethue.com/administrator/configuration/connectors/#databases

But you are doing a ko.mapping.toJSON() should work.

Then you will hit an issue like
{“status”:-1,“message”:“Snippet type hive is not configured.”}

And you should add the connectors params too
connector":{"na…

It is easier to look at the Chrome console Network tab when doing a SELECT 1 and looking at the execute call.

Good news is that in Hue 5 this API will be simple and clean…

Thanks @Romain. We have Hive all setup and installed and it works fine via the web interface. The network tab in Chrome shows a lot more fields are being sent than are specified in the API doc, I’m not sure if this is significant and if they are all needed? I tried an AJAX request with just the “snippet” fields:

$.ajax({
	url: "notebook/api/execute/hive/",
	type: 'POST',
	beforeSend: function(request) {
    request.setRequestHeader("Content-Type", 'application/x-www-form-urlencoded; charset=UTF-8');
	},
    data: {"snippet": {"id":"b2643bcfe-9e9b-6354-8dbc-8a2563f7254cb","type":"hive","status":"running","statementType":"text","statement":"SELECT 1;","aceCursorPosition":{"column":9,"row":0},"statementPath":"","associatedDocumentUuid":null,"properties":{"files":[],"functions":[],"arguments":[],"settings":[]},"result":{"id":"b2643bcfe-9e9b-6354-8dbc-8a2563f7254cb","type":"table","handle":{"has_more_statements":false,"statement_id":0,"statements_count":1,"previous_statement_hash":"ef10d24b9fdfe97deed746bb839573afef8647de5"}},"database":"default","wasBatchExecuted":false}},
	success: function(data) { console.log(data); },
	error: function(err) { console.log(err); }
});

which gives me a 500 internal server error and this is the relevant part of the response:

Exception Type: TypeError at /hue/notebook/api/execute/hive/
Exception Value: <desktop.appmanager.DesktopModuleInfo object at 0x2f37250> is not JSON serializable
Request information:
GET: No GET data

POST:
snippet[statementType] = u'text'
snippet[id] = u'b2643bcfe-9e9b-6354-8dbc-8a2563f7254cb'
snippet[aceCursorPosition][row] = u'0'
snippet[status] = u'running'
snippet[result][handle][statements_count] = u'1'
snippet[associatedDocumentUuid] = u''
snippet[type] = u'hive'
snippet[database] = u'default'
snippet[statementPath] = u''
snippet[result][handle][has_more_statements] = u'false'
snippet[result][handle][previous_statement_hash] = u'ef10d24b9fdfe97deed746bb839573afef8647de5'
snippet[result][id] = u'b2643bcfe-9e9b-6354-8dbc-8a2563f7254cb'
snippet[result][type] = u'table'
snippet[aceCursorPosition][column] = u'9'
snippet[result][handle][statement_id] = u'0'
snippet[statement] = u'SELECT 1;'
snippet[wasBatchExecuted] = u'false'

I also get the same Exception error message if I try with the “notebook” fields as well (this is all the form data that the web interface is sending when it successfully works), so my request is:

$.ajax({
	url: "notebook/api/execute/hive/",
	type: 'POST',
	beforeSend: function(request) {
    request.setRequestHeader("Content-Type", 'application/x-www-form-urlencoded; charset=UTF-8');
	},
    data: {"notebook": {"id":24989,"uuid":"b2643bcfe-9e9b-6354-8dbc-8a2563f7254cb","name":"Hive test","description":"test hive editor","type":"query-hive","initialType":"hive","coordinatorUuid":null,"isHistory":true,"isManaged":false,"parentSavedQueryUuid":"b2643bcfe-9e9b-6354-8dbc-8a2563f7254cb","isSaved":true,"onSuccessUrl":null,"pubSubUrl":null,"isPresentationModeDefault":false,"isPresentationMode":false,"presentationSnippets":{},"isHidingCode":false,"snippets":[{"id":"b2643bcfe-9e9b-6354-8dbc-8a2563f7254cb","name":"","type":"hive","isBatchable":true,"aceCursorPosition":{"column":9,"row":0},"errors":[],"aceErrorsHolder":[],"aceWarningsHolder":[],"aceErrors":[],"aceWarnings":[],"editorMode":true,"dbSelectionVisible":false,"isSqlDialect":true,"database":"default","currentQueryTab":"queryHistory","pinnedContextTabs":[],"loadingQueries":false,"queriesHasErrors":false,"queriesCurrentPage":1,"queriesTotalPages":1,"queriesFilter":"","queriesFilterVisible":false,"statementType":"text","statementTypes":["text","file"],"statementPath":"","externalStatementLoaded":false,"associatedDocumentLoading":true,"associatedDocumentUuid":null,"statement_raw":"SELECT 1;","statementsList":["SELECT 1;"],"aceSize":100,"status":"running","statusForButtons":"executing","properties":{"files":[],"functions":[],"arguments":[],"settings":[]},"viewSettings":{"placeHolder":"Example: SELECT * FROM tablename, or press CTRL + space","sqlDialect":true},"variables":[],"hasCurlyBracketParameters":true,"variableNames":[],"variableValues":{},"statement":"SELECT 1;","result":{"id":"b2643bcfe-9e9b-6354-8dbc-8a2563f7254cb","type":"table","hasResultset":true,"handle":{"has_more_statements":false,"statement_id":0,"statements_count":1,"previous_statement_hash":"ef10d24b9fdfe97deed746bb839573afef8647de5"},"meta":[],"rows":null,"hasMore":false,"statement_id":0,"statement_range":{"start":{"row":0,"column":0},"end":{"row":0,"column":0}},"statements_count":1,"metaFilter":{"query":"","facets":{},"text":[]},"isMetaFilterVisible":false,"filteredMetaChecked":true,"filteredMeta":[],"fetchedOnce":false,"startTime":"2021-02-18T14:42:25.058Z","endTime":"2021-02-18T14:42:25.058Z","executionTime":0,"data":[],"explanation":"","logs":"","logLines":0,"hasSomeResults":true},"showGrid":true,"showChart":false,"showLogs":true,"progress":0,"jobs":[],"isLoading":false,"resultsKlass":"results hive","errorsKlass":"results hive alert alert-error","is_redacted":false,"chartType":"bars","chartSorting":"none","chartScatterGroup":null,"chartScatterSize":null,"chartScope":"world","chartTimelineType":"bar","chartLimits":[5,10,25,50,100],"chartLimit":null,"chartX":null,"chartXPivot":null,"chartYSingle":null,"chartYMulti":["_c0"],"chartData":[],"chartMapType":"marker","chartMapLabel":null,"chartMapHeat":null,"hasDataForChart":false,"previousChartOptions":{"chartLimit":null,"chartX":null,"chartXPivot":null,"chartYSingle":null,"chartMapType":"marker","chartMapLabel":null,"chartMapHeat":null,"chartYMulti":["_c0"],"chartScope":"world","chartTimelineType":"bar","chartSorting":"none","chartScatterGroup":null,"chartScatterSize":null},"isResultSettingsVisible":false,"settingsVisible":false,"checkStatusTimeout":null,"topRisk":null,"suggestion":"","hasSuggestion":null,"compatibilityCheckRunning":false,"compatibilitySourcePlatform":"hive","compatibilitySourcePlatforms":[{"name":"Teradata","value":"teradata"},{"name":"Oracle","value":"oracle"},{"name":"Netezza","value":"netezza"},{"name":"Impala","value":"impala"},{"name":"Hive","value":"hive"},{"name":"DB2","value":"db2"},{"name":"Greenplum","value":"greenplum"},{"name":"MySQL","value":"mysql"},{"name":"PostgreSQL","value":"postgresql"},{"name":"Informix","value":"informix"},{"name":"SQL Server","value":"sqlserver"},{"name":"Sybase","value":"sybase"},{"name":"Access","value":"access"},{"name":"Firebird","value":"firebird"},{"name":"ANSISQL","value":"ansisql"},{"name":"Generic","value":"generic"}],"compatibilityTargetPlatform":"hive","compatibilityTargetPlatforms":[{"name":"Impala","value":"impala"},{"name":"Hive","value":"hive"}],"showOptimizer":false,"wasBatchExecuted":false,"isReady":true,"lastExecuted":1613659345047,"lastAceSelectionRowOffset":0,"executingBlockingOperation":null,"showLongOperationWarning":false,"formatEnabled":true,"isFetchingData":false,"isCanceling":false}],"selectedSnippet":"hive","creatingSessionLocks":[],"sessions":[{"type":"hive","properties":[{"multiple":true,"defaultValue":[],"value":[],"nice_name":"Files","key":"files","help_text":"Add one or more files, jars, or archives to the list of resources.","type":"hdfs-files"},{"multiple":true,"defaultValue":[],"value":[],"nice_name":"Functions","key":"functions","help_text":"Add one or more registered UDFs (requires function name and fully-qualified class name).","type":"functions"},{"nice_name":"Settings","multiple":true,"key":"settings","help_text":"Hive and Hadoop configuration properties.","defaultValue":[],"type":"settings","options":["hive.map.aggr","hive.exec.compress.output","hive.exec.parallel","hive.execution.engine","mapreduce.job.queuename"],"value":[]}],"reuse_session":true,"id":5349,"session_id":"b2643bcfe-9e9b-6354-8dbc-8a2563f7254cb"}],"directoryUuid":"","dependentsCoordinator":[],"historyFilter":"","historyFilterVisible":false,"loadingHistory":false,"historyInitialHeight":4238.011364,"forceHistoryInitialHeight":true,"historyCurrentPage":1,"historyTotalPages":5,"schedulerViewModel":null,"schedulerViewModelIsLoaded":false,"isBatchable":true,"isExecutingAll":false,"executingAllIndex":0,"retryModalConfirm":null,"retryModalCancel":null,"unloaded":false,"updateHistoryFailed":false,"viewSchedulerId":"","loadingScheduler":false}, "snippet": {"id":"b2643bcfe-9e9b-6354-8dbc-8a2563f7254cb","type":"hive","status":"running","statementType":"text","statement":"SELECT 1;","aceCursorPosition":{"column":9,"row":0},"statementPath":"","associatedDocumentUuid":null,"properties":{"files":[],"functions":[],"arguments":[],"settings":[]},"result":{"id":"b2643bcfe-9e9b-6354-8dbc-8a2563f7254cb","type":"table","handle":{"has_more_statements":false,"statement_id":0,"statements_count":1,"previous_statement_hash":"ef10d24b9fdfe97deed746bb839573afef8647de5"}},"database":"default","wasBatchExecuted":false}},
	success: function(data) { console.log(data); },
	error: function(err) { console.log(err); }
});

I believe this is very close to working but I just need the syntax right! We are using Hue 4 by the way but I am not sure which minor version.
Thanks

You can check the Hue logs? It will tell you in the trace which field in missing in the json. You can then also start printing the json data there to see why it is mix/matching, then it will be easy!

Sorry the current API is so complicated, but this will change in Q2/Q3 2021

@Romain thanks, do you know which log it might be in? I tried stderr.log and only see this, which is part of what I’m getting in the request response in the browser:

[18/Feb/2021 18:17:45 +0000] middleware   INFO     Processing exception: <desktop.appmanager.DesktopModuleInfo object at 0x2f37250> is not JSON serializable: Traceback (most recent call last):
  File "/data/cloudera/parcels/CDH-5.16.2-1.cdh5.16.2.p4463.3989/lib/hue/build/env/lib/python2.6/site-packages/Django-1.6.10-py2.6.egg/django/core/handlers/base.py", line 112, in get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/data/cloudera/parcels/CDH-5.16.2-1.cdh5.16.2.p4463.3989/lib/hue/build/env/lib/python2.6/site-packages/Django-1.6.10-py2.6.egg/django/db/transaction.py", line 371, in inner
    return func(*args, **kwargs)
  File "/data/cloudera/parcels/CDH-5.16.2-1.cdh5.16.2.p4463.3989/lib/hue/desktop/core/src/desktop/views.py", line 92, in hue
    'default_cluster_interface': default_cluster_interface
  File "/data/cloudera/parcels/CDH-5.16.2-1.cdh5.16.2.p4463.3989/lib/hue/desktop/core/src/desktop/lib/django_util.py", line 223, in render
    return render_json(data, request.GET.get("callback"), status=status)
  File "/data/cloudera/parcels/CDH-5.16.2-1.cdh5.16.2.p4463.3989/lib/hue/desktop/core/src/desktop/lib/django_util.py", line 298, in render_json
    json = encode_json(data, indent)
  File "/data/cloudera/parcels/CDH-5.16.2-1.cdh5.16.2.p4463.3989/lib/hue/desktop/core/src/desktop/lib/django_util.py", line 270, in encode_json
    return json.dumps(data, indent=indent, cls=Encoder)
  File "/usr/lib64/python2.6/json/__init__.py", line 237, in dumps
    **kw).encode(obj)
  File "/usr/lib64/python2.6/json/encoder.py", line 367, in encode
    chunks = list(self.iterencode(o))
  File "/usr/lib64/python2.6/json/encoder.py", line 309, in _iterencode
    for chunk in self._iterencode_dict(o, markers):
  File "/usr/lib64/python2.6/json/encoder.py", line 275, in _iterencode_dict
    for chunk in self._iterencode(value, markers):
  File "/usr/lib64/python2.6/json/encoder.py", line 309, in _iterencode
    for chunk in self._iterencode_dict(o, markers):
  File "/usr/lib64/python2.6/json/encoder.py", line 275, in _iterencode_dict
    for chunk in self._iterencode(value, markers):
  File "/usr/lib64/python2.6/json/encoder.py", line 317, in _iterencode
    for chunk in self._iterencode_default(o, markers):
  File "/usr/lib64/python2.6/json/encoder.py", line 323, in _iterencode_default
    newobj = self.default(o)
  File "/data/cloudera/parcels/CDH-5.16.2-1.cdh5.16.2.p4463.3989/lib/hue/desktop/core/src/desktop/lib/django_util.py", line 76, in default
    return json.JSONEncoder.default(self, o)
  File "/usr/lib64/python2.6/json/encoder.py", line 344, in default
    raise TypeError(repr(o) + " is not JSON serializable")
TypeError: <desktop.appmanager.DesktopModuleInfo object at 0x2f37250> is not JSON serializable

Also sorry I didn’t quite understand what you mean by “You can then also start printing the json data there to see why it is mix/matching, then it will be easy!” ?
Many thanks