Grab list of commits with Http request

Hello fellow specklers,

I am trying to receive the list of commits from a given stream and display it in unreal engine 4.

Since unreal engine supports Http requests I am trying to send a “POST” request to the graphQL server (https://speckle.xyz/graphql) by translating the provided curl command. However I receive a bad request as a response.

Is this path, copying the curl command from the “https://speckle.xyz/graphql” and trying to translate it as a HTTP post request a rational solution or I need a different route ?

Curl command :

curl 'https://speckle.xyz/graphql' -H 'Accept-Encoding: gzip, deflate, br' -H 'Content-Type: application/json' -H 'Accept: application/json' -H 'Connection: keep-alive' -H 'DNT: 1' -H 'Origin: https://speckle.xyz' -H 'Authorization: Bearer xxxxx' --data-binary '{"query":"# Write your query or mutation here\nquery{\n stream (id: \"2455b33e6b\"){\n id\n name\n commits{\n totalCount\n cursor\n items{\n id\n referencedObject\n message\n }\n }\n }\n}"}' --compressed

UE4 http request :

Request->SetVerb(TEXT(“POST”));
Request->SetHeader(“Accept-Encoding”, TEXT(“gzip”));
Request->SetHeader(“Content-Type”, TEXT(“application/json”));
Request->SetHeader(“Accept”, TEXT(“application/json”));
Request->SetHeader(“Connection”, TEXT(“keep-alive”));
Request->SetHeader(“DNT”, TEXT(“1”));
Request->SetHeader(“Origin”, TEXT(“https://speckle.xyz”));
Request->SetHeader(“Authorization”, "Bearer " + AuthToken);

const FString prefixBoundary(TEXT("–data-binary"));
const FString fileHeader(TEXT(“query{\n stream (id: “2455b33e6b”){\n id\n name\n commits{\n totalCount\n cursor\n items{\n id\n referencedObject\n }\n }\n }\n}”));
const FString suffixBoundary(TEXT("–compressed"));

//Set the content of the request
Request->SetContentAsString(prefixBoundary + fileHeader + suffixBoundary);

2 Likes

Hey @PanMig ,

Sorry but I don’t know C++ :sweat_smile: Have you already had a look at how @cristi set up the API calls to retrieve objects?

Here’s also an example making raw HTTP calls in javascript that could give you extra pointers:

https://speckle.guide/dev/js-app-script.html#writing-your-queries

2 Likes

Hi @PanMig ,

Hmm, looking at the code, try the following:

  • remove the Connection: keep-alive header? (i don’t know how ue4 handles keep-alive connections, maybe it can cause issues)
  • the POST data should not contain --data-binary and -compressed. Those are not boundaries, are actual curl parameters that don’t need to be included in the POST data. so maybe just do:
Request->SetContentAsString(fileHeader);

(it also must be a valid json)

2 Likes

To be a valid POST-data json, the query text that you have should be wrapped inside {"query": "..." }.

And the quotes inside the query should be backslash-escaped ( \" )

1 Like

@PanMig
Hmm, things can get tricky because you have to escape quotes once for the json representation and once for c++ string variable representation.

So I think you can end up with something like:

FString streamId = "2455b33e6b";
FString postPayload = "{\"query\": \"query{\n stream (id: \\\"" + streamId + "\\\"){\n id\n name\n commits{\n totalCount\n cursor\n items{\n id\n referencedObject\n }\n }\n }\n}\"}";
Request->SetContentAsString(postPayload);

(haven’t tested it, let me know how it works)

EDIT: might also have to replace \n with \\n

3 Likes

Many thanks it works fine since I am able to print the full json response correctly in the console. Now time for parsing.

Just a quick question out of curiosity, can you please explain what you are escaping in this particular session ?

> stream (id: \\\"" + streamId + "\\\")

2 Likes

Sure. So this is the GraphQL query that you want to run:

query{
 stream (id: "2455b33e6b"){
 id
 name
 commits{
 totalCount
 cursor
 items{
 id
 referencedObject
 }
 }
 }
}

In order to execute the query, you must make a POST request to the https://speckle.xyz/graphql API, by sending a query post parameter with your query. To send it via http, you must encode the post payload with json. So you get this json string that must be sent to the server:

{"query": "query{\n stream (id: \"2455b33e6b\"){\n id\n name\n commits{\n totalCount\n cursor\n items{\n id\n referencedObject\n }\n }\n }\n}"}

And in order to write that in C++ code, as a string variable, you have to escape the \ and " characters in the json representation. And you get:

FString x = "{\"query\": \"query{\\n stream (id: \\\"2455b33e6b\\\"){\\n id\\n name\\n commits{\\n totalCount\\n cursor\\n items{\\n id\\n referencedObject\\n }\\n }\\n }\\n}\"}";

And there i just used string concatenation to insert a variable there :slight_smile:

2 Likes

Ohh I see, I thought the \" part in the json representation could be omitted, due to the hardcoded value, my bad. Thanks for the clarification.

1 Like

Oh, I just found out that newlines are optional in the graphql query, so you can simplify it by removing the newlines :slight_smile:

But the quote for the id is needed if you pass a string value in the graphql query. And so is escaping the quote when putting it inside a json field value

3 Likes