Some users may experience random login-problems to our Community. We are investigating the root cause of this. If you get an error message from CloudFlare, please send the RayID in the message to support@superoffice.com. You may also clear your browser cookies and cashe to solve it. Thanks for your understanding. 

CRMScript HTTP call to Azure Function returns empty response (works in Postman and C#)

lock
push_pin
done
Answered
12

Hi everyone,

I'm currently trying to make a GET request from CRMScript to an Azure Function endpoint (*.azurewebsites.net).
The call works perfectly when I test it using Postman and with a simple C# console app.
However, when I try it using CRMScript, the response is empty.

What I'm doing

  • The function expects a requestid to be sent in the body.

  • Headers include Accept: application/json and a x-functions-key.

  • I've tried both GET and POST methods in CRMScript.

    JSONBuilder payload;
    payload.pushObject("");
    payload.addString("requestid", "example-request-id-1234"); //I get the requestid from the first function which also is a request to azurewebsites.
    payload.popLevel();
    
    printLine(payload.getString());
    
    HTTP httpClient;
    httpClient.addHeader("Accept", "application/json");
    httpClient.addHeader("Content-Type", "application/json; charset=utf-8");
    httpClient.addHeader("x-functions-key", "example-functions-key");
    httpClient.setOption("parameters", "?" + payload.getString());
    
    String response = String(httpClient.post("https://example-function.azurewebsites.net/api/MyFunctionEndpoint"));
    
    printLine("Response: " + response);
    

But response is always empty.

🔹 How it works correctly in C# (for comparison)

Here’s a minimal C# example that works correctly:

static async Task Main(string[] args) {
    var client = new HttpClient();
    var request = new HttpRequestMessage(HttpMethod.Get, "https://example-function.azurewebsites.net/api/MyFunctionEndpoint");
    request.Headers.Add("Accept", "application/json");
    request.Headers.Add("x-functions-key", "example-functions-key");
    
    var content = new StringContent("{ \"requestid\": \"example-request-id-1234\" }", null, "application/json");
    request.Content = content;
    
    var response = await client.SendAsync(request);
    response.EnsureSuccessStatusCode();
    Console.WriteLine(await response.Content.ReadAsStringAsync());
}

 

What am I doing wrong here ?

Just to add little preface. I'm trying first to trigger an azure job with crmscript, this works fine and then i use the request id from the response in trigging the azure job to check the status which for some odd reason does not work.

29 Apr 2025 | 02:22 PM

All Replies (12)

Hi,

Try enable http debug mode and printing the results from that:

HTTP httpClient;
httpClient.setDebugMode(true);

httpClient.addHeader("Accept", "application/json");
httpClient.addHeader("Content-Type", "application/json; charset=utf-8");
httpClient.addHeader("x-functions-key", "example-functions-key");
httpClient.setOption("parameters", "?" + payload.getString());

String response = String(httpClient.post("https://example-function.azurewebsites.net/api/MyFunctionEndpoint"));

printLine("Response: " + response);

printLine(http.getDebug());
printLine(http.getErrorMessage());

Map headers = http.getResponseHeaders();

for (headers.first(); !headers.eof(); headers.next())
{
  	printLine (headers.getKey() + " => " + headers.getVal());
}
29 Apr 2025 | 03:21 PM

Hi Ummair!

try adding the status code to the  output and see if it is 200. 

String statusCode = httpClient.getValue("statusCode");

printLine(statusCode + "-" + response);
 
Alternatively, use https://webhook.site to inspect what is being sent. Example:
 
#setLanguageLevel 4;

/*
{
  "status": "success",
  "data": {
    "authToken": "b0akv5svtdyTGiuWYAtAf1tt-D5ck4VJUrJWALVUR3L",
    "userId": "ksyrss7Ktue72o2XX"
  }
}
*/

String postUrl = "https://webhook.site/3595942d-0425-4638-9eb4-1573dbb2b5b6";
JSONBuilder jb;
jb.pushObject("");
jb.addString("status", "success" );
jb.pushObject("data");
jb.addString("authToken", "b0akv5svtdyTGiuWYAtAf1tt-D5ck4VJUrJWALVUR3L");
jb.addString("userId", "ksyrss7Ktue72o2XX");
jb.popLevel();
jb.popLevel();

String jsonString = jb.getString();
//print(jsonString);

HTTP httpPost;
httpPost.addHeader("Content-Type", "Application/json");
httpPost.addHeader("x-functions-key", "example-functions-key");

httpPost.setOption("parameters","?"+ jsonString);

String resPost = String(httpPost.post(postUrl));
String statusCode = httpPost.getValue("statusCode");

printLine(statusCode+""+resPost);


Best regards
29 Apr 2025 | 03:22 PM

Hey Tony and David. 

Adding status didnt make any difference.

Debug gives this (removed sensitive keywords)

== Info
  Trying 10.xx.xx.xx:3128...

== Info
CONNECT tunnel: HTTP/1.1 negotiated

== Info
allocate connect buffer

== Info
Establish HTTP proxy tunnel to function-host.example.net:443

=> Send header
CONNECT function-host.example.net:443 HTTP/1.1
Host: function-host.example.net:443
Proxy-Connection: Keep-Alive

<= Recv header
HTTP/1.1 200 Connection established

<= Recv header

== Info
CONNECT phase completed

== Info
CONNECT tunnel established, response 200

== Info
ALPN: curl offers http/1.1

== Info
TLSv1.3 (OUT), TLS handshake, Client hello (1):

== Info
 CAfile: ..\..\..\CS\curl-ca-bundle.crt

== Info
 CApath: none

== Info
TLSv1.3 (IN), TLS handshake, Server hello (2):

== Info
TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):

== Info
TLSv1.3 (OUT), TLS handshake, Client hello (1):

== Info
TLSv1.3 (IN), TLS change cipher, Change cipher spec (1):

== Info
TLSv1.3 (IN), TLS handshake, Server hello (2):

== Info
TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):

== Info
TLSv1.3 (IN), TLS handshake, Certificate (11):

== Info
TLSv1.3 (IN), TLS handshake, CERT verify (15):

== Info
TLSv1.3 (IN), TLS handshake, Finished (20):

== Info
TLSv1.3 (OUT), TLS handshake, Finished (20):

== Info
SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 / secp521r1 / RSASSA-PSS

== Info
ALPN: server accepted http/1.1

== Info
Server certificate:

== Info
 subject: C=US; ST=WA; L=Redmond; O=Microsoft Corporation; CN=*.azurewebsites.net

== Info
 start date: Apr 14 21:33:25 2025 GMT

== Info
 expire date: Oct 11 21:33:25 2025 GMT

== Info
 subjectAltName: host "function-host.example.net" matched cert's "*.azurewebsites.net"

== Info
 issuer: C=US; O=Microsoft Corporation; CN=Microsoft Azure RSA TLS Issuing CA 07

== Info
 SSL certificate verify ok.

== Info
  Certificate level 0: Public key type RSA (2048/112 Bits/secBits), signed using sha384WithRSAEncryption

== Info
  Certificate level 1: Public key type RSA (4096/152 Bits/secBits), signed using sha384WithRSAEncryption

== Info
  Certificate level 2: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption

== Info
Connected to 10.xx.xx.xx (10.xx.xx.xx) port 3128

== Info
using HTTP/1.x

=> Send header
POST /api/MyFunctionEndpoint HTTP/1.1
Host: function-host.example.net
Accept: application/json
Content-Type: application/json; charset=utf-8
x-functions-key: [REDACTED-KEY]
traceparent: [REDACTED-TRACEPARENT]
Content-Length: 83

=> Send data
{"status": "success","data": {"requestid": "example-request-id-uuid"}}

== Info
upload completely sent off: 83 bytes

== Info
TLSv1.3 (IN), TLS handshake, NewSession Ticket (4):

<= Recv header
HTTP/1.1 404 Not Found

<= Recv header
Content-Length: 0

<= Recv header
Date: Tue, 29 Apr 2025 15:54:06 GMT

<= Recv header
Request-Context: appId=cid-v1:[REDACTED-APP-ID]

<= Recv header

== Info
Connection #0 to host 10.xx.xx.xx left intact


And printing headers gives statuscode 404. 

content-length => 0
date => Tue, 29 Apr 2025 15:54:06 GMT
http/1.1 200 connection established => 
http/1.1 404 not found => 
request-context => appId=cid-v1:dd845549-256c-45ba-a07b-ab21d0d5b2df

How come it works in postman and with C# httpClient and not in CRMScript ?

29 Apr 2025 | 04:00 PM

Your csharp example show's that you are doing a GET operation, while in the crmscript example you are doing a POST operation. Maybe that is the issue?

29 Apr 2025 | 04:08 PM
I've tried with GET in CRMScript. It doesent work either.
In the headers it gives me:

HTTPConnection::endRequest(): URL using bad/illegal format or missing URL
29 Apr 2025 | 04:11 PM
Not sure if the CRMScript implementation supports sending a body with a GET operation..
29 Apr 2025 | 04:13 PM
The first method that retrieves the requestid is also a GET method in Postman and C#, but it works only when I use post in CRMScript. Was expecting the same for this method aswell.
29 Apr 2025 | 04:19 PM

I have checked the code, and from what I can see, we do not support a body for GET, DELETE or HEAD. I would argue that sending a body on a GET (which obviously impacts the response) is not recomended. Some more details here: https://stackoverflow.com/questions/978061/http-get-with-request-body

I don't expect us to change this implementation, so I suggest rewriting the endpoint to accepting all relevant parameters in the URI.

Sverre

30 Apr 2025 | 07:48 AM

Ummair, are there any codepaths in the Azure Function that returns a 404 result? 

In your second example your JSON has a different structure, you send in a status as well. Can that cause the azure function to return 404?

Is your Azure Function hosted on any other ports than 80 or 443?

I've got a feeling there is something in the redacted info that is relevant to why it's failing.

 

David, for the fun of it, you can send a body in a GET by messing around with the headers. Not recommended though 😀

String body = String('{"Food": "Blåbærsyltetøy"}').utf8Encode();

HTTP http;
http.addHeader("Content-Length", body.getLength().toString() + "\n\n" + body);
http.get(URL);
30 Apr 2025 | 08:21 AM
You're a legend, @Frode? 💎
The workaround actually did the trick! 🙌
I've also asked the dev to include requestId in the URL instead of the body so we can make it "work the proper way".
30 Apr 2025 | 09:47 AM

Hi all,

@Frode is a legend :-) But just to give you a warning as well. We have header-sanitation as a backlog item. You should not be allowed to add headers with newlines. So, Frode's sollution will most likely stop working in the near future. Sorry about that, but support for sending a payload as a GET should rather be solved with explicit support. 

Sverre

13 May 2025 | 11:33 AM
The backend developer have already changed things on their end to make it to accept a POST :)
13 May 2025 | 01:16 PM

Add reply