TRON not using request.header - httprequest

I am using Xcode 8.3.3 (8E3004b)
I am using TRON (which includes Alamofire) to make HTTP Request to my REST API.
I have been successful getting a simple API working with this setup. I am trying to connect to a different API, which requires me to set the headers. It is this API that is throwing a Status 415 server error.
I have the following code to make the request via TRON. According to the TRON Github page, I should be ae to set the header like this:
request.headers = ["Content-Type":"application/json"]
I have also tried:
request.headerBuilder.headers(forAuthorizationRequirement: AuthorizationRequirement.allowed, including: ["Content-Type":"application/json"])
I tried adding a few different ways of writing that, but nothing seems to work.
Here's a bigger section of the code so you can see the context
let urlSubfix = "\(Constant.REST_MOBILE)\(Constant.REGISTER)"
let request: APIRequest<RegisterApiResult, JSONError> = tron.request(urlSubfix)
request.method = .put
// request.headers = ["Content-Type":"application/json"]
let header = request.headerBuilder.headers(forAuthorizationRequirement: AuthorizationRequirement.allowed, including: ["Content-Type":"application/json"])
request.headers = header
request.perform(withSuccess: { (registerApiResult) in
print("Successfully fetched our json object")
completion(registerApiResult)
}) { (err) in
print("Failed to fetch json...", err)
}
Here is the actual error from my log:
Failed to fetch json... APIError<JSONError>(request: Optional(http://www.slsdist.com/eslsd5/rest/mobileservice/register), response: Optional(<NSHTTPURLResponse: 0x618000028c20> { URL: http://www.slsdist.com/eslsd5/rest/mobileservice/register } { status code: 415, headers {
"Content-Length" = 0;
Date = "Sat, 22 Jul 2017 22:23:14 GMT";
Server = "Microsoft-IIS/7.5";
"X-Powered-By" = "Undertow/1, ASP.NET";
} }), data: Optional(0 bytes), error: Optional(Alamofire.AFError.responseValidationFailed(Alamofire.AFError.ResponseValidationFailureReason.unacceptableStatusCode(415))), errorModel: Optional(Go_Cart.Service.JSONError))
As you can see I have tried to set the headers a couple different ways, but neither of them seems to take affect. Any help or advice from anyone would be helpful.
Thanks in advance.

Related

Webhook call failed. Error: Failed to parse webhook JSON response: Expect message object but got: [Chinese letters]

I'm building my own WebhookClient for dialog flow. My code is the following (using Azure Functions, similar to Firebase Functions):
module.exports = async function(context, req) {
const agent = new WebhookClient({ request: context.req, response: context.res });
function welcome(agent) {
agent.add(`Welcome to my agent!!`);
}
let intentMap = new Map();
intentMap.set("Look up person", welcome);
agent.handleRequest(intentMap);
}
I tested the query and the response payload looks like this:
{
"fulfillmentText": "Welcome to my agent!!",
"outputContexts": []
}
And the headers in the response look like this:
Transfer-Encoding: chunked
Content-Type: application/json; charset=utf-8
Server: Microsoft-IIS/10.0
X-Powered-By: ASP.NET
Date: Tue, 11 Dec 2018 18:16:06 GMT
But when I test my bot in dialog flow, it returns the following:
Webhook call failed. Error: Failed to parse webhook JSON response:
Expect message object but got:
"笀ഀ਀  ∀昀甀氀昀椀氀氀洀攀渀琀吀攀砀琀∀㨀 ∀圀攀氀挀漀洀攀 琀漀 洀礀 愀最攀渀琀℀℀∀Ⰰഀ਀  ∀漀甀琀瀀甀琀䌀漀渀琀攀砀琀猀∀㨀 嬀崀ഀ਀紀".
There's Chinese symbols!? Here's a video of me testing it out in DialogFlow: https://imgur.com/yzcj0Kw
I know this should be a comment (as it isn't really an answer), but it's fairly verbose and I didn't want it to get lost in the noise.
I have the same problem using WebAPI on a local machine (using ngrok to tunnel back to Kestrel). A friend of mine has working code (he's hosting in AWS rather than Azure), so I started examining the differences between our responses. I've notice the following:
This occurs with Azure Functions and WebAPI (so it's not that)
The JSON payloads are identical (so it's not that)
Working payload isn't chunked
Working payload doesn't have a content type
As an experiment, I added this code to Startup.cs, in the Configure method:
app.Use(async (context, next) =>
{
var original = context.Response.Body;
var memory = new MemoryStream();
context.Response.Body = memory;
await next();
memory.Seek(0, SeekOrigin.Begin);
if (!context.Response.Headers.ContentLength.HasValue)
{
context.Response.Headers.ContentLength = memory.Length;
context.Response.ContentType = null;
}
await memory.CopyToAsync(original);
});
This code disables response chunking, which is now causing a new and slightly more interesting error for me in the google console:
*Webhook call failed. Error: Failed to parse webhook JSON response: com.google.gson.stream.MalformedJsonException: Unterminated object at line 1 column 94 path $.\u0000\\"\u0000f\u0000u\u0000l\u0000f\u0000i\u0000l\u0000l\u0000m\u0000e\u0000n\u0000t\u0000M\u0000e\u0000s\u0000s\u0000a\u0000g\u0000e\u0000s\u0000\\"\u0000.\
I thought this could be encoding at first, so I stashed my JSON as a string and used the various Encoding classes to convert between them, to no avail.
I fired up Postman and called my endpoint (using the same payload as Google) and I can see the whole response payload correctly - it's almost as if Google's end is terminating the stream part-way through reading...
Hopefully, this additional information will help us figure out what's going on!
Update
After some more digging and various server/lambda configs, I spotted this post here: https://github.com/googleapis/google-cloud-dotnet/issues/2258
It turns out that json.net IS the culprit! I guess it's something to do with the formatters on the way out of the pipeline. In order to prove this, I added this hard-coded response to my POST controller and it worked! :)
return new ContentResult()
{
Content = "{\"fulfillmentText\": null,\"fulfillmentMessages\": [],\"source\": null,\"payload\": {\"google\": {\"expectUserResponse\": false,\"userStorage\": null,\"richResponse\": {\"items\": [{\"simpleResponse\": {\"textToSpeech\": \"Why hello there\",\"ssml\": null,\"displayText\": \"Why hello there\"}}],\"suggestions\": null,\"linkOutSuggestion\": null}}}}",
ContentType = "application/json",
StatusCode = 200
};
Despite the HTTP header saying the charset is utf-8, that is definitely using the utf-16le character set, and then the receiving side is treating them as utf-16be. Given you're running on Azure, it sounds like there is some configuration you need to make in Azure Functions to represent the output as UTF-8 instead of using UTF-16 strings.

Requesting parameters are not sent over API in ionic 2

I am trying to send the the parameters using a post request but the parameters are not reaching to provide back the desired result and printing null as a result in console. here is my code
var headers = new Headers();
headers.append('Content-Type', 'application/x-www-form-urlencoded' );
let options = new RequestOptions({ headers: headers });
let postParams = {
acesscode: 'XXXXXXXXXXX',
productCode:'XXXXXXXXXX'
};
this.http.post("http://www.ebiebook.com/drmapi/v1/details", JSON.stringify(postParams), options)
.subscribe(data => {
console.log(data['_body']);
}, error => {
console.log(error);// Error getting the data
});
}
and the output screen is attached, It shows API is hitting well but the parameters data is unable to reach to provide the corresponding result. Please suggest.
This print you have attached does not show what is being sent by the request, instead it shows only the response your browser received from the server.
You better take a look at this thread here to see in this thread more about. You have to check the 'Headers' tab from Chrome's console -> Network.

How to get MvcOptions.ReturnHttpNotAcceptable to work together with ApiVersioning

I'd like to return HTTP 406 if the version requested is not supported. So I have:
services.AddApiVersioning(options =>
{
options.ReportApiVersions = true;
options.AssumeDefaultVersionWhenUnspecified = false;
options.ApiVersionReader = new MediaTypeApiVersionReader();
});
services.AddMvc(options =>
{
options.RespectBrowserAcceptHeader = true;
options.ReturnHttpNotAcceptable = true; // Return HTTP 406
});
But this always returns HTTP 406 even if the version is correct (e.g. application/json;v=1.0 or application\vnd.acme+json;v=1).
If I set ReturnHttpNotAcceptable to false, I get HTTP 400 (Bad Request) when version is unsupported, and HTTP 200 if version is supported.
Also, if I set my ApiVersionReader to be HeaderApiVersionReader, and set ReturnHttpNotAcceptable to true, it returns an HTTP 400 instead of 406 when the version is unsupported.
If I disable versioning altogether, I get HTTP 406 correctly with ReturnHttpNotAcceptable set to true and if, say, the request has appliction/xml and the API does not support XML.
I've asked this question on ASP.NET API Versioning on Github, but I'm wondering if this is just something I have not figured out, and could get an answer from this forum.
As indicated in the discussion here, I ended up with this approach:
I created an output formatter that accepts media type with version parameter (e.g. application/json;version=1.0 or application/vnd.acme+json;version=1.0)
I created a subsclass of ApiVersioning's DefaultErrorResponseProvider so it returns a HTTP 406 when the version specified in the Accept header is not accepted.

GET API code request failure

I just started learning how to use API and I found some really usefull websites and apps like Postman and import.io yet I'm having problems finishing it without help.
I started my little project by getting a working api from import.io (It reads a website and can give you a working API that finds the info in the website)
My REST API looks like this:
https://extraction.import.io/query/runtime/7629f27e-ceee-4ce2-9a1c-cede623d2fc0?_apikey=[apiKey]&url=http%3A%2F%2Fimdb.com
To test and make sure it's working I used postman app and then found a neat feature - code generation.
The app generated this code:
import http.client
conn = http.client.HTTPSConnection("extraction.import.io")
headers = {
'cache-control': "no-cache",
'postman-token': "2087cc79-77b5-0cb9-aa06-adc642978287"
}
conn.request("GET", "/query/runtime/1ac40e3e-f3eb-4290-88c0-e2651b8194a5?_apikey=[apiKey]&url=http%253A%252F%252Fwww.leagueofgraph.com", headers=headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
however the result is:
{
"message" : "Your extraction request has failed.",
"code" : 1003
}
What am I doing wrong?
The code that has been generated has double escaped the "http://"
it should be http%3A%2F%2F not http%253A%252F%252F
Try this corrected code:
import http.client
conn = http.client.HTTPSConnection("extraction.import.io")
headers = {
'cache-control': "no-cache",
'postman-token': "2087cc79-77b5-0cb9-aa06-adc642978287"
}
conn.request("GET", "/query/runtime/1ac40e3e-f3eb-4290-88c0-e2651b8194a5?_apikey=[apiKey]&url=http%3A%2F%2Fwww.leagueofgraph.com", headers=headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

Google Apps Script: Salesforce API Call

Just finished breakfast and already hit a snag. I'm trying to call the salesforce REST api from my google sheets. I've written a working script locally in python, but converting it into JS, something went wrong:
function authenticateSF(){
var url = 'https://login.salesforce.com/services/oauth2/token';
var options = {
grant_type:'password',
client_id:'XXXXXXXXXXX',
client_secret:'111111111111',
username:'ITSME#smee.com',
password:'smee'
};
var results = UrlFetchApp.fetch(url, options);
}
Here is the error response:
Request failed for https://login.salesforce.com/services/oauth2/token
returned code 400. Truncated server response:
{"error_description":"grant type not
supported","error":"unsupported_grant_type"} (use muteHttpExceptions
option to examine full response) (line 12, file "Code")
Mind you, these exact parameters work fine in my local python script (putting the key values inside quotations).
Here are the relevant docs:
Google Script: Connecting to external API's
Salesforce: REST API guide
Thank you all!
Google's UrlFetchApp object automatically defaults to a GET request. To authenticate, you have to explicitly set in the options the method "post":
function authenticateSF(){
var url = 'https://login.salesforce.com/services/oauth2/token';
var payload = {
'grant_type':'password',
'client_id':'XXXXXXXXXXX',
'client_secret':'111111111111',
'username':'ITSME#smee.com',
'password':'smee'
};
var options = {
'method':'post',
'payload':payload
};
var results = UrlFetchApp.fetch(url, options);
}