Post request a raw json with Ktor client - kotlin

I want to make post request with Ktor but I get Error 400.
the curl looks like this :
curl --location --request POST 'https://api.jdoodle.com/execute' \
--header 'Content-Type: application/json' \
--data-raw '{
"script" : "console.log('\''hello'\'')",
"language": "nodejs",
"versionIndex": "1",
"clientId": "....",
"clientSecret": "...."
}'
Here is my code :
val client = HttpClient {
install(JsonFeature) {
val json = Json {
isLenient = true
ignoreUnknownKeys = true
}
serializer = KotlinxSerializer(json)
}
}
fun fetchData(requestBody: Request): Response {
return client.post(BASE_URL){
contentType(ContentType.Application.Json)
body = requestBody
}
}
#Serializable
data class Request(....)
What am I doing wrong ?

Related

API does not return right data in Google Apps Script

I'm trying to fetch Wise API to save the exchange rate to Google Sheets, but for some reason the data returned is not correct.
It works in Postman but when I make same request in Google Sheets via Google Apps Script data just don't match.
curl example from documentation
https://api.transferwise.com/v3/quotes/ \
-H "Authorization: Bearer <your client credentials token>"
-H 'Content-type: application/json' \
-d '{
"sourceCurrency": "GBP",
"targetCurrency": "USD",
"sourceAmount": null,
"targetAmount": 110 }'
Response in Postman:
Request in Google Apps Script:
const url = "https://api.transferwise.com/v3/quotes/";
const response = UrlFetchApp.fetch(url, {
"method": "POST",
"headers": {
"Authorization": "Bearer + mytoken",
"Content-Type": "application/json"
},
"muteHttpExceptions": true,
"followRedirects": true,
"validateHttpsCertificates": true,
"contentType": "application/json",
"payload": JSON.stringify({"\\\"sourceCurrency\\\"":"\\\"EUR\\\"","\\\"targetCurrency\\\"":"\\\"USD\\\"","\\\"sourceAmount\\\"":"null","\\\"targetAmount\\\"":"1000"})
});
const data = JSON.parse(response.getContentText())
Logger.log("Response code is %s", response.getResponseCode());
Logger.log(data.rate);
}
Response on console:
API is returning "1.0176" instead of "0.98015" and I can't discovery what I'm doing wrong.
Change your payload to:
"payload": `{
"sourceCurrency": "EUR",
"targetCurrency": "USD",
"souceAmount": 1000,
"targetAmount": null
}`

ASP.NET Core OData Batch works for get but not update (PATCH)

Using .NET Core 3.1 and Microsoft.AspNetCore.OData 8.0.4.
I've set up Batch on my API and it works if all the requests in the batch are GET.
But if I put any updates, it fails with an error I can't figure out.
Successful direct update:
curl --location --request PATCH 'https://localhost:44390/api/odata/TradeTypeSpread(8432C89B-6D71-48B2-9F40-0000190AD326)' \
--header 'ApiAccessKey: xxxx' \
--header 'Content-Type: application/json' \
--data-raw '{
"Id":"8432C89B-6D71-48B2-9F40-0000190AD326",
"Spread": 3.0
}'
200 OK
{
"error": null,
"isSucceeded": true,
"id": null
}
Failed batch update:
curl --location --request POST 'https://localhost:44390/api/Odata/$batch' \
--header 'ApiAccessKey: xxx' \
--header 'Content-Type: application/json' \
--data-raw '{
"requests": [
{
"id": "1",
"method": "PATCH",
"url": "/api/odata/TradeTypeSpread(8432C89B-6D71-48B2-9F40-0000190AD326)",
"body": {
"Id": "8432C89B-6D71-48B2-9F40-0000190AD326",
"Spread": 3.0
}
}
]
}'
{
"responses": [
{
"id": "1",
"status": 400,
"headers": {
"content-type": "application/json; odata.metadata=minimal; odata.streaming=true",
"odata-version": "4.0"
},
"body": {
"error": {
"code": "",
"message": "The input was not valid.",
"details": [
{
"code": "",
"message": "The input was not valid."
}
]
}
}
}
]
}
Can anyone see what I'm doing wrong in the second sample?
Startup Code:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
var defaultODataBatchHandler = new DefaultODataBatchHandler();
defaultODataBatchHandler.MessageQuotas.MaxNestingDepth = 2;
defaultODataBatchHandler.MessageQuotas.MaxOperationsPerChangeset = 100;
services
.AddControllersWithViews(options =>
{
options.Filters.Add(typeof(HttpGlobalExceptionFilter));
options.Filters.Add(typeof(ValidateModelStateAttribute));
})
.AddNewtonsoftJson(options => options.SerializerSettings.UseDefaultSettings(nullValueHandling: Newtonsoft.Json.NullValueHandling.Include))
.AddOData(opt => opt.AddRouteComponents(
"api/odata",
new ModuleOdataEntityDataModel().GetEntityDataModel(),
defaultODataBatchHandler)
.Select().Filter().Count().OrderBy().Expand().SetMaxTop(Convert.ToInt32(Configuration["OdataMaxPageSize"])))
.ConfigureApiBehaviorOptions(options =>
{
options.SuppressModelStateInvalidFilter = true;
});
Controller Code
public class TradeTypeSpreadController : ODataController
{
[EnableQuery]
public async Task<IQueryable<TradeTypeSpreadDto>> Get()
{
...
}
public async Task<IActionResult> Patch(Guid key, Delta<TradeTypeSpreadDto> detalTradeSpreadDto)
{
...
}
}
Thanks
Sam
Working batch update for OData in ASP Net Core might look like this:
[AcceptVerbs("PATCH", "MERGE")]
public async Task<IActionResult> Patch(
[FromODataUri] string key,
Delta<MyModel> patch)
{
var model = patch.GetInstance();
await _repository.Update(model);
// IQueryable
var res = _repository.GetAll().SingleOrDefault(x => x.Id == key);
return Updated(res);
}
And it expects "get single" to be available as well:
[EnableQuery]
public IActionResult Get(
[FromODataUri] string key)
{
var dataset = _salesAreaBandsRepository.GetAll();
return Ok(dataset.SingleOrDefault(x => x.Id == key));
}
And of course the GetEdmModel() has to be adjusted if you use compound key or other field as a key:
private static IEdmModel GetEdmModel()
{
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
var entitySet1 = builder.EntitySet<MyModel>("MyModel");
entitySet1.EntityType.HasKey(entity => entity.OtherKey);
return builder.GetEdmModel();
}
And you have:
app.UseODataBatching();
Sometimes you also need to change AddRouteComponents:
AddRouteComponents("odata", GetEdmModel(),
new DefaultODataBatchHandler())

UPDATE INTENT DIALOG FLOW VIA API V1

My problem is that when I want to update an intent via API DIALOGFLOW V1 it returns Unknown Error, BUT I can list and create the intent via API V1, here is my code for the update:
url : https://api.dialogflow.com/v1/intents/f5eedaaa-f7d1-4e4e-b1fa-6aa66c94ca6f?v=20150910
method : PUT
DATA : {"id":"f5eedaaa-f7d1-4e4e-b1fa-6aa66c94ca6f","name":"FORDEBUG","auto":false,"contexts":[],"responses":[{"resetContexts":false,"affectedContexts":[],"parameters":[],"messages":[{"type":0,"condition":null,"speech":["KOKOKOOOKK","KOJKFKF"]}],"defaultResponsePlatforms":[],"speech":[]}],"priority":500000,"webhookUsed":false,"webhookForSlotFilling":false,"fallbackIntent":false,"events":[],"userSays":[{"id":"d891eb29-7233-4f47-901c-751cbde5fff4","data":[{"text":"KOKOK","userDefined":false}],"isTemplate":false,"count":0,"updated":0,"isAuto":false},{"id":null,"data":[{"text":"FJFLFOPF"}]}],"followUpIntents":[],"liveAgentHandoff":false,"endInteraction":false,"conditionalResponses":[],"condition":null,"conditionalFollowupEvents":[],"templates":[]}
and here is the return that I have :
{
"id": "e5bf8ebf-f5e6-4568-8237-f69dcef6f5db",
"timestamp": "2021-06-07T16:53:36.748Z",
"lang": "en",
"status": {
"code": 400,
"errorType": "bad_request",
"errorDetails": "Unknown error errorid=0a4ffdc6-907a-4049-965d-509490bb428e"
}
}
Unfortunately Dialogflow V1 is already deprecated last May 31, 2020 and no further operations can be performed. It is suggested to migrate to Dialogflow V2 so you can continue using the service.
We are extending the V1 API shutdown deadline to May
31st, 2020. Migrate to the V2 API as described here.
If you use Dialogflow exclusively for Actions on Google, you don't
need to migrate your agent to the V2 API. However, note the following
changes:
The Dialogflow simulator will show responses in the V2 format and the
"Copy curl" button will generate requests in the V2 format. This
should have no impact on the functionality of the Actions on Google
simulator.
You will no longer be able to call API methods for the V1
intents and entities resources. You will still be able to modify your
agent using the Dialogflow Console.
Once you have migrated to V2, you can update an intent by batch or per intent.
EDIT 20210609
Here are the request body and call using curl. I'm not knowledgeable in php, but I suppose you can convert this to curl php.
But I assume that the content of the json will go to data:, the endpoint used in the curl command will be url: and method: will be either PATCH (for single intent) or POST (for batch intent update).
Updating a single intent using request_patch.json
{
"name":"projects/your-project-id/agent/intents/your-intent-id",
"displayName":"Image please",
"trainingPhrases":[
{
"type":"EXAMPLE",
"parts":[
{
"text":"Show an image"
}
]
},
{
"type":"EXAMPLE",
"parts":[
{
"text":"Show me an image"
}
]
},
{
"type":"EXAMPLE",
"parts":[
{
"text":"Show me an image please"
}
]
}
]
}
Curl command:
curl -X PATCH -H "Content-Type: application/json" \
-H "Authorization: Bearer "$(gcloud auth application-default print-access-token) \
https://dialogflow.googleapis.com/v2/projects/your-project-id/agent/intents/your-intent-id \
-d #request_patch.json
Successful response:
{
"name": "projects/your-project-id/agent/intents/your-intent-id", "displayName": "Image please",
"priority": 500000
}
Updating batch intents using request_batch.json
{
"intentBatchInline":{
"intents":[
{
"name":"projects/your-project-id/agent/intents/your-intent-id",
"displayName":"Image please",
"trainingPhrases":[
{
"type":"EXAMPLE",
"parts":[
{
"text":"Show an image"
}
]
},
{
"type":"EXAMPLE",
"parts":[
{
"text":"Show me an image"
}
]
},
{
"type":"EXAMPLE",
"parts":[
{
"text":"Show me an image please"
}
]
}
]
}
]
}
}
Curl command:
curl -X POST -H "Content-Type: application/json" \
-H "Authorization: Bearer "$(gcloud auth application-default print-access-token) \
POST https://dialogflow.googleapis.com/v2/projects/your-project-id/agent/intents:batchUpdate \
-d #request_batch.json
Successful response:
{
"name": "projects/your-project-id/operations/operation-id-here",
"done": true,
"response": {
"#type": "type.googleapis.com/google.cloud.dialogflow.v2.BatchUpdateIntentsResponse",
"intents": [
{
"name": "projects/your-project-id/agent/intents/your-intent-id",
"displayName": "Image please",
"priority": 500000
}
]
}
}

Flutter send notificiation from client app with curl

I'm trying to send a notification from flutter application directly, but I can not figure it out how to do it.
Everywhere they say have to send a curl request with basic network library but there is no example.
DATA='{"notification": {"body": "this is a body","title": "this is a title"}, "priority": "high", "data": {"click_action": "FLUTTER_NOTIFICATION_CLICK", "id": "1", "status": "done"}, "to": "<FCM TOKEN>"}'
curl https://fcm.googleapis.com/fcm/send -H "Content-Type:application/json" -X POST -d "$DATA" -H "Authorization: key=<FCM SERVER KEY>"
Please help me with an example in DART.
You could try this:
import 'dart:async';
import 'dart:convert' show Encoding, json;
import 'package:http/http.dart' as http;
class PostCall {
final postUrl = 'https://fcm.googleapis.com/fcm/send';
final data = {
"notification": {"body": "this is a body", "title": "this is a title"},
"priority": "high",
"data": {
"click_action": "FLUTTER_NOTIFICATION_CLICK",
"id": "1",
"status": "done"
},
"to": "<FCM TOKEN>"
};
Future<bool> makeCall() async {
final headers = {
'content-type': 'application/json',
'Authorization': 'key=<FCM SERVER KEY>'
};
final response = await http.post(postUrl,
body: json.encode(data),
encoding: Encoding.getByName('utf-8'),
headers: headers);
if (response.statusCode == 200) {
// on success do sth
return true;
} else {
// on failure do sth
return false;
}
}
}

Bigquery data transfer service for adwords

putenv('GOOGLE_APPLICATION_CREDENTIALS=../platform-engineering.json');
$client = new Google_Client();
$client->useApplicationDefaultCredentials();
$client->setScopes(array("https://www.googleapis.com/auth/bigquery",
"https://www.googleapis.com/auth/cloud-platform",
"https://www.googleapis.com/auth/cloudplatform.read-only"
));
$http = $client->authorize();
$body = '{"dataSourceId": "adwords","destinationDatasetId": "adwords","displayName": "testing","params": {"customer_id": "42342423432"}, "dataRefreshWindowDays": 3,"disabled": false, "datasetRegion":"US"}';
$resp = $http->request("POST", "https://content-bigquerydatatransfer.googleapis.com/v1/projects/platform-engineering/transferConfigs", [
'body' => $body,
'headers' => array('content-type' => 'application/json')
]);
print_r($resp->getBody()->getContents());
Response as below :
{ "error": {
"code": 400,
"message": "Request contains an invalid argument.",
"status": "INVALID_ARGUMENT" } }
CURL command-line not working either:
curl -H "Content‐Type: application/json" -H "Authorization: Bearer MY_TOKEN" -d '{"dataSourceId": "adwords","destinationDatasetId": "adwords","displayName": "mauliktestng","params": {"customer_id": "4729344234"}}' https://bigquerydatatransfer.googleapis.com/v1/projects/platform-engineering/transferConfigs
Try replacing body to this:
$body = '{"dataSourceId": "adwords","destinationDatasetId":
"adwords","displayName": "testing","params": {"fields": {"key":
"customer_id", "value": {"string_value": "42342423432"}}},
"dataRefreshWindowDays": 3,"disabled": false, "datasetRegion":"US"}';