API auth question

Hi all, I am working on a plugin that will use the Push API and I have a few questions pertaining to auth.

The app need to get push printer job status information. I have that working by using the http API to login with a user/pass and then using the session ID to auth the websockets. Fine. But I also need to read access the gcode file. For that I apparently need to use an Application Key? Is there anyway to have either auth do both jobs? Or to get the application key once logged in?

Also, on the push notifications, It is a firehose of data, and all I really care about is job status. Is there anyway to unsubscribe to the data that I don't want?

Thanks!

When logging in using a username and password, you have to save the session cookie. Browsers do this automatically, but not on cross-origin requests by default. If you aren't using a browser based client, then you will be able to create a session that can save cookies. So you either need to use an API key, or the login using username/password & store the cookie.

Downloading the gcode file is doable with either of these methods, from /downloads/files/local/<filename>.gcode.

No you can't turn off messages, you just have to filter it client side.

How can you use either Session or user/pass to download the file? The only way I have been able to get it to work is to append the api key

/downloads/files/local/<filename>.gcode?apikey=xxxx

What environment are you in? Browser? Something else? Need a bit more context of where you are using the API.

My "app" runs in a browser, and uses websocket to connect to push message. I use a I am using GET to fetch the gcode from /downloads

                    $.post( "http://octopi.local/api/login", { user: "user", pass: "pass" },function( data ) {
                        var ws = new WebSocket("ws://octopi.local/sockjs/websocket");
                        ws.onopen = function()
                        {
                            ws.send('{ "auth":"user:'+data.session+'" }')
                        };

                        ws.onmessage = function (e) 
                        { 
        var file_url = url;//'/downloads/files/local/xxx.gcode?apikey=xxxx';

        var myRequest = new Request(file_url,
            {
                method: 'GET',
                headers: {
                    'Content-Type': 'text/plain'
                },
                mode: 'cors',
                cache: 'no-cache' 
            }
        );
        fetch(myRequest)
            .then(function (response) {
                var contentLength = response.headers.get('Content-Length');

This is where you have the issue. The fetch API defaults to credentials: 'same-origin', which means none of the cookies are going to be saved (and therefore you need the API key).

Add credentials: 'include' to all your HTTP requests, not just this one but the login one as well and try again, eg:

        var myRequest = new Request(file_url,
            {
                method: 'GET',
                headers: {
                    'Content-Type': 'text/plain'
                },
                mode: 'cors',
                cache: 'no-cache',
+               credentials: 'include',
            }
        );
        fetch(myRequest)
            .then(function (response) {
                var contentLength = response.headers.get('Content-Length');

I was going to reply with the above answer, but thought I had better test it... There's a missing header OctoPrint's side. When enabling CORS on the API, it doesn't send the ' Access-Control-Allow-Credentials' header, which would be required for this. I'll open an issue to see if this can be added.

So this leaves us with the only option:

If you don't want to send the API key as a query parameter, then use the X-Api-Key header.

1 Like

That works. I would prefer to just use the apikey anyway. Thanks!

Now I just have to sort out the bandwidth issue. The push API is generating over 300k/min in data, and I hope to run this app on a cell phone where I might not have great coverage. I might have to use pull instead.

1 Like