I struggle with creating a REST API client call just using pure Javascript without escaping to Java GraalVM interop.
Is it at all possible, or should I use Java http connections?
Hi,
I don't think it's possible to do it in pure javascript, so it most certainly have to rely on some java code through GraalVM or Nashorn interop.
I think (but haven't tested it) that if we where able to create a good java implementation of XMLHttpRequest made available to jArchi (either using jav code from js, or by adding it natively into the API), then it would become possible to use other libraries such as axios (https://axios-http.com/docs/intro).
Here is a potential candidate (nashorn polyfill): https://github.com/shendepu/nashorn-polyfill/blob/master/lib/xml-http-request-polyfill.js
Another one (need to hack source code of GWT): https://www.gwtproject.org/javadoc/latest/com/google/gwt/xhr/client/XMLHttpRequest.html
Or maybe this one: https://github.com/sabren/java-XmlHttpRequest
Regards,
JB
I had the same question in the past. Browsing through other examples, I found this snipped and altered it to call a JSON rest API. Maybe you can use it too (works with GraalVM)
function CallApi(url) {
var imports = new JavaImporter(java.net, java.util, java.lang, java.io)
var result=""
with (imports) {
var urlObj = new URL(url)
var hcon = urlObj.openConnection()
hcon.setRequestProperty ("Accept", "application/json")
hcon.setRequestProperty ("Accept-Charset", "UTF-8")
hcon.setRequestProperty ("Accept-Language", "NL")
hcon.connect()
try {
var reader = new BufferedReader(new InputStreamReader(hcon.getInputStream()))
var line = reader.readLine()
while (line != null) {
result += line + "\n"
line = reader.readLine()
}
reader.close()
result = JSON.parse(result)
if (("RESULT"===result.kind)&&("OK"===result.status)) {
//console.log("API call to"+url+" wend well")
} else {
console.setTextColor(255,0,0)
console.log("error in API call response")
}
} catch(e) {
console.setTextColor(255,0,0)
console.log("HTTPS error:")
console.log(e)
console.log(hcon.getHeaderFields())
exit()
}
}
console.setDefaultTextColor()
return result
}
if API needs standard HTTPS username/password insert this when creating headers (of course, replace/set "Username" and "Password":
userCredentials = Username +":" +Password
basicAuth = "Basic " + new String(Base64.getEncoder().encode(userCredentials.getBytes()))
hcon.setRequestProperty ("Authorization", basicAuth)
if REST API needs cookie, add this to the code
Retrieving cookie from call:
cookie=(hcon.getHeaderFields().get("Set-Cookie"))[0]
Using cookie
hcon.setRequestProperty ("Cookie", cookie)
Thanks for this example, really useful !
If API use a bearer token, the syntax is (with a whitespace after Bearer) :
hcon.setRequestProperty("Authorization", "Bearer " + token)
and to get correct encoding in my case, I have added UTF-8 where reading the response stream
var reader = new BufferedReader(new InputStreamReader(hcon.getInputStream(), "UTF-8"))
In case you're like me behind a corporate proxy with authentication, you should user Proxy and Authenticator classes from java.net. Syntax is a bit strange, VsCode will complain that your script has problems but it works :
var imports = new JavaImporter(java.net, java.util, java.lang, java.io, java.nio.charset)
var result = ""
with (imports) {
var urlObj = new URL(url)
var proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(PROXY_IP, PROXY_PORT));
//create a subclass of Authenticator
var ProxyAuth = Java.extend(Java.type("java.net.Authenticator"));
var auth = new ProxyAuth() { getPasswordAuthentication: function() {
return new java.net.PasswordAuthentication(PROXY_USER, PROXY_PASS.toCharArray());
}}
Authenticator.setDefault(auth);
var hcon = urlObj.openConnection(proxy);