Calling REST APIs

Started by Thomas Rohde, February 20, 2023, 09:34:41 AM

Previous topic - Next topic

Thomas Rohde

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?

Jean-Baptiste Sarrodie

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.

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

If you value and use Archi, please consider making a donation!
Ask your ArchiMate related questions to the ArchiMate Community's Discussion Board.

merty

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)

jsimoncello

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"))     
     

jsimoncello

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);