Archi Forum

Archi Plug-ins => jArchi => Topic started by: Thomas Rohde on February 20, 2023, 09:34:41 AM

Title: Calling REST APIs
Post by: Thomas Rohde on February 20, 2023, 09:34:41 AM
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?
Title: Re: Calling REST APIs
Post by: Jean-Baptiste Sarrodie on February 20, 2023, 20:51:55 PM
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

Title: Re: Calling REST APIs
Post by: merty on February 27, 2023, 20:12:43 PM
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)
Title: Re: Calling REST APIs
Post by: jsimoncello on June 15, 2023, 15:59:03 PM
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"))     
     
Title: Re: Calling REST APIs
Post by: jsimoncello on June 27, 2023, 15:24:50 PM
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);