Chaining graphql query to generate or remove Persistent URL

Hi all,

I am trying to enable persistent url using the shell script and is able to do so by doing subsequent queries.

First, I get the http service id by passing both the account id and device name using this query :

{
    "query": "{ 
        login {
            account(id: \"${accountId}\") {
                devices(name: \"${deviceName}\"){
                    items{ id name services(name: \"http\") { id name } enabled state }
                }
            }
        } 
    }"
}

Then subsequently I pass that id in the second query, either to set the persistent public url or removing it.

Set the public url :

{
	"query": "mutation SetPublicURL(\$serviceId: String!, \$isEnabled: Boolean!) { setConnectLink(serviceId: \$serviceId, enabled: \$isEnabled) { url password enabled } }",
	"variables": {
		"serviceId": "${serviceId}",
		"isEnabled": ${isEnabled}
	}
}

Remove the public url :

{
	"query": "mutation RemovePublicURL(\$serviceId: String!) { removeConnectLink(serviceId: \$serviceId) }",
	"variables": {
		"serviceId": "${serviceId}"
	}
}

As for the question, is there a way to combine the queries so if I want to set or remove, I can simply send one query to do so?

Regards,
Guruh.

Mutations need to be sent as separate requests. This is a graphQL usage design and not an API specific setting.

Mutations need to be sent as separate requests. This is a graphQL usage design and not an API specific setting.

In other words, if I want to generate and enable persistent url, I need to use the first query to get the http service Id, then pass it to the mutation on the second query subsequently?

First Query

{
    "query": "{ 
        login {
            account(id: \"${accountId}\") {
                devices(name: \"${deviceName}\"){
                    items{ id name services(name: \"http\") { id name } enabled state }
                }
            }
        } 
    }"
}

Second query (the mutation) :

{
	"query": "mutation SetPublicURL(\$serviceId: String!, \$isEnabled: Boolean!) { setConnectLink(serviceId: \$serviceId, enabled: \$isEnabled) { url password enabled } }",
	"variables": {
		"serviceId": "${serviceId}",
		"isEnabled": ${isEnabled}
	}
}

Or is there are more efficient query to do it?

You can do one query to fetch all of your devices without filtering to get a specific device name and iterate over the results instead of a request for each device. In your iteration, you can then make the mutation call to make a change if one is needed.

Hi,
Forgive me but this qs isn’t directly realted to the OP’s post…
Am new to and facing some issues with making GraphQL queries…

In your sample query above, can you tell me what exactly to set the ${accountID} variable to? (device name is i think straightforward).

When I tried this with my account email ID, even with setting up the ~/.remoteit/credentials file, I always get this output:
{"message":"Forbidden"}

TIA!
Kaiwan.

Perhaps the authorization’s missing?
How do I perform it from the device, via graphQL or curl?

TIA,
Kaiwan.

What language are you trying to use?

Did you see this documentation:

It is recommended to use access key and secret.

1 Like

Thanks @mycal , that heped!

  1. Via curl, I thunk it is authorizing correctly now (I get a json-formatted list of devices & services returned!).

  2. Now, the query issued, as seen above, isn’t working (yet); the output i get:

$ ./qry1 
GRAPHQL_URL=https://api.remote.it/graphql/v1
DATA_QRY1={
    query: "{ 
        login {
            account(id: "<email-id-i-registered>") {
                devices(name: "kenix-raspberrypi4-<...>"){
                    items{ id name services(name: "http") { id name } enabled state }
                }
            }
        } 
    }"
}
{"message":"Forbidden"}

(The value of the variables in the script i use are shown). Is something wrong with the query syntax? Is the ‘id’ field right?

  1. Given a service on a device (say, http_80), how can I programatically - via curl, ideally - start it / ‘connect’ it, and once connected, fetch it’s endpoint (proxy url:port#)?

Any help’s appreciated, TIA!
– kaiwan.

@bstrech, can you pl help me here? Thanks…

If your authentication is working, the next step is to ensure you have the correct query. I usually use Insomnia to test and perfect all my queries before porting them to code.

You don’t need to specify the account explicitly since it’s inferred from your credentials. The query you want is:

query {
	login { 
		account {
			devices( name:"home") {
				items{ id name }
			}
		}
	}
}

This is a valid query. Using Insomnia with the remote.it plugin is highly recommended as it generates all your queries without errors by leveraging the schema and validating what’s allowed. Alternatively, you can use the network debug feature in Firefox or Chrome to inspect the queries made in the web portal.

Also if you post exactly what your trying to do I may be able to help

OK I see you want to generate a connection, this is a mutation, all these are in the public insomnia repo

https://github.com/remoteit/code_samples/tree/main/insomnia_collections

The mutation you want is:

#Proxy connections can be generated to individual services and the unique
#address will be provided in the host and port fields.
#
#hostIP values could contain
#
#0.0.0.0 for fully public connections available to user
#
#255.255.255.255 to allow only the first accessing IP to "Latch" the connection.
#Blocking all others
#
#A unique public IP address to only allow that IP to access the connection

mutation GetConnection($serviceId: String!, $hostIP: String!) {
	connect(serviceId: $serviceId, hostIP: $hostIP) {
		id
		created
		host
		port
		reverseProxy
		timeout
	}
}

with the query variables

{
	"serviceId": "80:12:12:12:34:56:78:90",
	"hostIP": "255.255.255.255"
}

Put your service ID in for the service you wish to generate a connection to. The host IP is explained above.

This will return your connection information, something like this for a port proxy

{
	"data": {
		"connect": {
			"id": "574a34f3a680731583fc4c426f306b38494111111bf1",
			"created": "2023-04-27T17:28:40.050Z",
			"host": "proxy16.rt3.io",
			"port": 31117,
			"reverseProxy": false,
			"timeout": 480
		}
	}
}

or for a reverse proxy

{
	"data": {
		"connect": {
			"id": "0daaaaaaa128b4bdccb7552211111117c4a111b221",
			"created": "2021-03-17T11:35:46.442Z",
			"host": "d771213235f51123.p16.rt3.io",
			"port": null,
			"timeout": 480,
			"reverseProxy": true
		}
	}
}

Okay. I ran the auth script and then tried this:

curl ${GRAPHQL_URL} \                                                                     
  -X POST \                                                                               
  -H 'content-type: application/json' \                                                   
  --data "query: { \                                                                      
     login { \                                                                            
         account { \                                                                      
               devices( name:\"${devname}\") { \                         
                    items { id name } \                                  
                } \                                                      
            } \                                                          
        } \                                                              
    }"

where devname is my device name. It returns:
{"message":"Forbidden"}

So, am unsure what’s wrong…

The ‘auth’ part seems to go through all right; it returns info like this (i used jq to format it):

...
{
  "data": {
    "login": {
      "email": "<my-email>",
      "devices": {
        "items": [
          {
            "id": "90:00:00:00:00:...",
            "name": "k...",
            "services": [
              {
                "id": "90:00:00:00:00:...",
                "name": "...2_ctrl_2068"
              },
              {
                "id": "90:00:00:00:00:...",
                "name": "...2_http_80"
              },
...

TIA…
(Will work on your next replies as well, just want to get these basics in place first).

You ran this without the auth? That will never work. Each request has to be signed

Your curl call should look like this and the authentication should be valid:

curl --write-out -v -X ${VERB} -H “Authorization:${SIGNATURE_HEADER}” -H “Date:${DATE}” -H “Content-Type:${CONTENT_TYPE}” ${URL} -d “${DATA}” --insecure

The auth script is the base for everything, make that a method or function, then pass the query to it.

If you look at the example bash script, that I think your using as a test, your query is here, just replace this with what you want:

DATA=‘{ “query”: “{ login { email devices (size: 1000, from: 0) { items { id name services { id name} } } } }” }’

Substitute your desired query here!