First REST API call is slow - json

We have built a Xamarin.Forms application that uses REST API calls.
The initial load of the application is fast however the first API call is slow (extra 3-4 secs comparing to the second request against the same URL).
The behavior is similar on both iOS and Andorid platforms.
Is there any option to eliminate this waiting time?
Here is a sample code we use to do the API call (by using unirest package):
HttpResponse authRes = Unirest.post(App.TenantConfig.response.idmUrl + "/api/v1/authn")
.header("Accept", "application/json")
.header("Content-Type", "application/json")
.header("Cache-Control", "no-cache")
.header("Postman-Token", "672008d5-52f7-8997-3e04-57ac24b6dab6")
.body("{\n \"username\": \"" + Username + "\",\n \"password\": \"" + Password + "\",\n \"options\": {\n \"multiOptionalFactorEnroll\": true,\n \"warnBeforePasswordExpired\": true\n } \n}")
.asString();

Related

Send bearer + token in request header C++ builder?

I'm working with a C++ application in embarcadero RAD Studio.
I'm trying to access my swagger api https://camur3.treffo.se/api/swagger/index.html to fetch information using the RESTClient, RESTRequest and RESTResponse components.
Now the API is authorized with bearer + token. Right now i can get out the token:
So i've trying to do a new call to the api from another button
void __fastcall TForm7::B_NewRequestClick(TObject *Sender)
{
RESTClient1->BaseURL = "https://camur3.treffo.se/api/users/authenticate/access";
//Request header + token??
RESTRequest1->Execute();
}
But don't know how to send the token in next request..
Anyone who knows how to do this?
You need to put the token in an Authorization request header, eg:
RESTRequest1->Params->AddHeader(_D("Authorization"), _D("Bearer ") + token);
Or
RESTRequest1->AddParameter(_D("Authorization"), _D("Bearer ") + token, TRESTRequestParameterKind::pkHTTPHEADER);
Or
RESTRequest1->AddAuthParameter(_D("Authorization"), _D("Bearer ") + token, TRESTRequestParameterKind::pkHTTPHEADER);

InDesign Socket HTTP response is missing sections

I am automating Adobe InDesign to create documents using JSON data gathered from a web API with a SQL Server backend. I am using the Sockets object to make an HTTP 1.0 call to our server. Sometimes the response received is missing about 1700 characters from various points within the JSON string, yet when I call the same API endpoint using curl or Postman I get a complete and valid response.
The response should be about 150k characters long, and I'm using conn.read(99999999) to read it. In addition, the appearance of the end of the string looks correct, so I don't believe it's any kind of truncation problem.
The problem only seems to occur when I request a UTF-8 encoding. If I request ASCII I get a complete and valid response, but missing various Unicode characters. If I request BINARY I get a complete and valid response but the JavaScript/ExtendScript seems to be handling any multi-byte Unicode characters received as individual bytes, rather than as the Unicode characters we want to display.
Here is an illustration of the behavior I'm seeing, using bogus data...
"Expected" response...
[{"Id":1, "name":"Random Name", "Text":"A bunch of text", "AnotherId": 1}]
"Actual" response...
[{"Id":1, "name":"Random Name", "Text":"A bunc": 1}]
The problem first manifested itself as a JSON2 parsing error, for obvious reasons, but the root of it seems to be the fact that parts of the data are going missing in-transit.
So far we've only seen this problem when making the call using the InDesign Sockets object, and not every response exhibits this behavior.
Any help or insights you could offer would be appreciated.
Here is the function I'm using to call for data...
function httpRequest(url, encoding) {
try {
var response = "";
var hostName = getHostFromUrl(url);
var pathAndQuery = getPathAndQueryFromUrl(url);
var httpGet = "GET ";
httpGet += pathAndQuery;
httpGet += " HTTP/1.0\r\nHost: ";
httpGet += hostName;
httpGet += "\r\n";
var conn = new Socket;
conn.timeout = 30;
//conn.encoding = encoding || "UTF-8";
//conn.charset = "UTF-16";
if (conn.open(hostName + ":80", encoding || "UTF-8")) {
// send a HTTP GET request
conn.writeln(httpGet);
// and read the server's response
response = conn.read(99999999);
conn.close();
}
return parseHttpResponse(response);
}
catch (e) {
$.writeln(e);
$.global.alert("There was a problem making an HTTP Request: " + e);
return null;
}
}
It turns out my handling of the HTTP response was too simplistic and needed extra logic to handle Unicode characters properly.
The solution, in my case, was to use the GetURL method made available by Kris Coppieter here.

How do I make a secure API request from an Arduino ESP32, programmed in the Arduino IDE using ArduinoJson?

I have been hacking away at this for a few days with no luck.
I am trying to make a secure (SSL/HTTPS) API request in an Arduino environment. The controller I am using is an ESP32, which connects through wifi fine, and can retrieve/post data. However I am having no luck connecting to a secure API.
I'm trying to connect to this API https://strike.acinq.co/documentation/api-reference
EXAMPLE CURL REQUEST IN API'S DOCUMENTATION:
$ curl https://api.dev.strike.acinq.co/api/v1/charges \
-u sk_pJDwxFxCVw5fQJhRRMpf29jReUjjN: \
-X POST \
-d amount=42000 \
-d currency="btc" \
-d description="1%20Blockaccino"
Here is my Arduino code, I am using the ArduinoJson.h and WiFi.h libraries:
// Connect to HTTP server
WiFiClient client;
client.setTimeout(10000);
if (!client.connect("api.strike.acinq.co", 80)) {
Serial.println(F("Connection failed"));
return;
}
Serial.println(F("Connected!"));
// Send HTTP request
client.println(F("GET /api/v1/charges?id=MYKEY&amount=4200&currency=btc HTTP/1.0"));
client.println(F("Host: api.strike.acinq.co"));
client.println(F("Content-Type: application/x-www-form-urlencoded"));
client.println(F("Connection: close"));
if (client.println() == 0) {
Serial.println(F("Failed to send request"));
return;
}
// Check HTTP status
char status[32] = {0};
client.readBytesUntil('\r', status, sizeof(status));
if (strcmp(status, "HTTP/1.1 200 OK") != 0) {
Serial.print(F("Unexpected response: "));
Serial.println(status);
return;
}
A 401 "Invalid API Key" Is the closest I have got. I know the API-key works, and that I am just using it wrong. I've tried moving the key to:
client.println(F("id: MYKEY"));
but that didn't work either.
I have tried other libraries and ArduinoJson seems to be the best. I think the issue is the fact its a secure server and the layout of my request. I found many resources for connecting to open API's on Arduino, but nothing on connecting to secure ones. I think I am almost there with the code...
UPDATE
So I have updated my code. I am still trying to use ArduinoJson. I can connect to the API but it keeps spitting out "HTTP/1.1 400 BAD_REQUEST". I don't know weather this is because its over HTTPS or the formatting of my request.
In the API docs -u and -X don't have a field name like "amount=4200", so I am assuming -u would just be added client.print("?="+apiKey);
//open weather map api key
String apiKey= "myapikey";
int status = WL_IDLE_STATUS;
char server[] = "api.strike.acinq.co";
Serial.println("\nStarting connection to server...");
// if you get a connection, report back via serial:
if (client.connect(server, 80)) {
Serial.println("connected to server");
// Make a HTTP request:
client.print("POST /api/v1/charges");
client.print("?="+apiKey);
client.print("&amount=4200");
client.print("&currency='btc'");
client.println("&description='sweets'");
client.println("Host: api.strike.acinq.co");
client.println("Connection: close");
client.println();
}
else {
Serial.println("unable to connect");
}
UPDATE
I figured out the println and print actually mean something and have subsequently organised my request much better. It still comes back with 400 Unauthorized?
String PostData = "&description=\"car\"&amount=1000&currency=\"sweetsandthat\"";
client.println("POST /api/v1/charges HTTP/1.1");
client.println("Host: api.strike.acinq.co");
client.println("Authorization: Basic "+apiKey);
client.print("Content-Length: ");
client.println(PostData.length());
client.println(); // blank line required
client.println(PostData);
Serial.println("POSTED DATA: " + PostData);
// client.stop();
client.println();
} else {
Serial.println("unable to connect");
}
delay(1000);
String line = "";
while (client.connected()) {
line = client.readStringUntil('999');
Serial.println(line);
Serial.println("parsingValues");
//create a json buffer where to store the json data
StaticJsonBuffer<5000> jsonBuffer;
JsonObject& root = jsonBuffer.parseObject(line);
if (!root.success()) {
Serial.println("parseObject() failed");
return;
}
//get the data from the json tree
String nextWeatherTime0 = root["id"][0];
// Print values.
Serial.println(nextWeatherTime0);
}
client.println("Connection: close");
client.stop();
}
Check the response for a BAD request, We usually get it when we deal with a bad URL or URL not found. check whether you are connecting to the same url mentioned in docs.
First connect to the api and after that make queries like providing your api key and feilds
remove this.
client.println("Host: api.strike.acinq.co");
and use GET request to get the response of the data you have in these fields
String PostData = "&description=\"car\"&amount=1000&currency=\"sweetsandthat\""
I have also been struggling to get an https post to work on the esp32. A few things, the wifi.h module, I believe, does not support https. The WiFiClientSecure.h does, and you need to set the port to 443. I have also failed to get a POST to work, but I succeed in a basic GET test connection to howsmysssl.com. Andreas Spiess covers this well in a youtube video. He goes beyond SSL to establishing trust. I just want basic SSL to work, so if you get this figured out, please let me know. Hopefully I got you one step closer. :)

Azure Automation Webhook - Twilio StatusCallback not arriving in JSON

I'm trying to implement a solution which automatically calls someone when a certain event occurs, based on Twilio, Azure Automation and SCOM. Furthermore, it shall be possible for someone to call a number, and the same process is triggered.
The Twilio Account/Phonenumber is set up and works fine. When I do a call to the Twilio Number I successfully receive HTTP POST on my Azure Automation Webhook and the Runbook is fired.
The only problem I'm facing right now, is that I cannot make use of the cmdlet ConvertFrom-Json to extract the WebhookBody.
This is the error I get when using the cmdlet:
ConvertFrom-JSON : Invalid JSON primitive: Called. At line:13 char:11
+ $Inputs = ConvertFrom-JSON $webhookdata.RequestBody
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [ConvertFrom-Json], ArgumentException
+ FullyQualifiedErrorId : System.ArgumentException,Microsoft.PowerShell.Commands.ConvertFromJsonCommand
And this is the Input arriving on the Azure Automation Webhook from Twilio:
{"WebhookName":"Twilio
Endpoint","RequestBody":"Called=%2B41815880262&ToState=Chur&CallerCountry=CH&Direction=inbound&Timestamp=Fri%2C%2010%20Feb%202017%2009%3A07%3A35%20%2B0000&CallbackSource=call-progress-events&CallerState=&ToZip=&SequenceNumber=0&CallSid=CA7c152287d945595fe600614fe7778f8a&To=%2B41815880262&CallerZip=&ToCountry=CH&ApiVersion=2010-04-01&CalledZip=&CalledCity=&CallStatus=completed&Duration=1&From=%2BMYTELNUZMBER&CallDuration=8&AccountSid=MYSID&CalledCountry=CH&CallerCity=&Caller=%2Bmybnumber&FromCountry=CH&ToCity=&FromCity=&CalledState=Chur&FromZip=&FromState=","RequestHeader":{"Cache-Control":"max-age=259200","Connection":"close","Accept":"/","Host":"s2events.azure-automation.net","User-Agent":"TwilioProxy/1.1","X-Twilio-Signature":"pq2jYVGN3H5LmanwId0xCvp69tM=","x-ms-request-id":"bc1cf55a-33b2-4046-a343-199d1a7fac4a"}}
When I simply output the WebHook Data with this cmd, I can see that the Twilio Repsonse looks somewhat strange (Heade looks good though):
$WebhookName = $WebhookData.WebhookName
$WebhookHeaders = $WebhookData.RequestHeader
$WebhookBody = $WebhookData.RequestBody
Write-Output $WebhookHeaders
Write-Output $WebhookBody
Output:
Cache-Control : max-age=259200 Connection : close Accept
: / Host : s2events.azure-automation.net User-Agent
: TwilioProxy/1.1 X-Twilio-Signature : xmEbt23prT+W8zJrRZE5pdKullE=
x-ms-request-id : bdca412c-584e-42ba-acbb-969cdf9c1ec0
Called=%2B41815880262&ToState=Chur&CallerCountry=CH&Direction=inbound&Timestamp=Wed%2C%2008%20Feb%202017%2013%3A18%3A27%20%2B0000&CallbackSource=call-progress-events&CallerState=&ToZip=&SequenceNumber=0&CallSid=CALLSID&To=%2B41815880262&CallerZip=&ToCountry=CH&ApiVersion=2010-04-01&CalledZip=&CalledCity=&CallStatus=completed&Duration=1&From=%2BMYNUMBER&CallDuration=7&AccountSid=MYSID&CalledCountry=CH&CallerCity=&Caller=%2BMYBNUMBER&FromCountry=CH&ToCity=&FromCity=&CalledState=Chur&FromZip=&FromState=
Does anybody have an idea what I could do instead of writing my own "Converter" to get the values from the TWILIO HTTP POST? Or may I be doing something horribly wrong?
So, I think I understood your problem. You are doing it slightly wrong: $webhook data is already an object, which has everything you need:
$WebhookData.WebhookName
$WebhookData.RequestHeader
$WebhookData.RequestBody
You just need to parse RequestBody into something meaningful:
$data = #{ };
foreach ($item in $WebhookData.RequestBody.Split('&')) {
try {
$item = $item.Split('=');
$data.Add($item[0], [System.Net.WebUtility]::UrlDecode($item[1]))
}
catch {
Write-Warning -Message ('Possible null parameter value for {0}' -f $item[0]);
}
}
Twilio developer evangelist here.
When Twilio sends a webhook request to your URL it is not encoded as JSON. This is why your JSON conversion is failing.
Twilio sends the data as either URL encoded parameters in the body of a POST request or URL query parameters for GET requests. This is the same as if the request were made by the submission of a form in a browser.
I'm not familiar with Azure cmdlets but if there is one for parsing URL encoded data, then you'll want to use that instead. Alternatively, #4c74356b41 has provided a decent implementation.

c# httpcontent "400 - Bad Request" if string contains newline character

I am running into some kind of trouble communicating with a restful service from my .Net WPF application (.Net 4.5), in particular when sending a "PUT" request with some json data.
FYI: The restful service is running under Python Flask.
The method I use the following method to send request to the restful service:
HttpClient http = new HttpClient();
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", encodedCredentials);
http.Timeout = TimeSpan.FromSeconds(1);
// Add an Accept header for JSON format.
http.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpContent content = new StringContent(jDataString, Encoding.UTF8, "application/json");
When I submit usual string, all works just fine. But I am having trouble as soon as the string contains line breaks.
Using:
mytring.Replace("\r", "").Replace("\n", "")
works, my string is then accepted by the restful service.
Unfortunately, this is not acceptable, because I want to be able to retrieve line breaks.
I hence tried approaches like:
mytring.Replace("\n", "\\n").Replace("\r", "\\r")
or even with a inside-character to make sure I recognize the pattern:
mytring.Replace("\n", "\\+n").Replace("\r", "\\+r")
In both cases, my parsed string looks fine, but isn't accepted by the restful service.
Below two examples - the first version is accepted, not the second and third...
"XML_FIELD": "<IDs><Id Type=\"System.Int32\" Value=\"7\" /></IDs>"
"XML_FIELD": "<IDs>\r\n<Id Type=\"System.Int32\" Value=\"20\" />\r\n</IDs>"
"XML_FIELD": "<IDs>\+r\+n<Id Type=\"System.Int32\" Value=\"20\" />\+r\+n</IDs>"
Thanks in advance for the help!!
Regards!
Ok, got it...
The issue was coming from "\r\n" character which were coming directly from my DB...
Anyway, change to perform is for SERIALIZATION is
mySerializedString.Replace("\r\n", "\n")
.Replace("\n", "\\n")
.Replace("\r", "\\r")
.Replace("\'", "\\'")
.Replace("\"", "\\\"")
.Replace("\t", "\\t")
.Replace("\b", "\\b")
.Replace("\f", "\\f");
And to de-serialize do the inverse:
myDeSerializedString.Replace("\\n", "\n")
.Replace("\\r", "\r")
.Replace("\\'", "\'")
.Replace("\\\"", "\"")
.Replace("\\t", "\t")
.Replace("\\b", "\b")
.Replace("\\f", "\f");
NOTE: in the process, we loose "\r\n" characters (which are replaced by "\n").