The HTTP request is not being executed in response - Flutter/Dart - http

I'm trying to perform a request to a Web API written in C# (.NET Core). The endpoint runs a async function and return a JSON with result of operation.
In Dart I can't get the response. then() or catchError() just don't executes.
The endpoint get products in payload. When I send only one product I can get the response but when ai send two or more I can't.
The payload is:
http .post('http://192.168.0.10:5000/api/v1/oficina/dart',
body: jsonEncode({
"usuario": "edigleyssonsilva",
"senha": "123456",
"codEmp": 1,
"codFil": 1,
"produtos": [
{
"ccuRes": "160",
"codEmp": 1,
"codFil": 1,
"codPro": "570.0001",
"codTns": "90250",
"datPrv": "2020-02-17",
"datEme": "2020-02-17",
"qtdEme": 2
}
]
}),
headers: {'Content-Type': 'application/json'})
.then((value) => print(value.body))
.catchError((err) {
print('Ocorreu um erro');
print(err);
});
I already tested the same endpoint with the same payload on Postman, Angular app and on a test file written in Dart and this works perfectly.
So, I have no idea why it doesn't work in Flutter

It's not very clear tell with the code you shared, either also share the code calling this function, but you can also try, with assigning your body to a Map object, and then encode it with json.encode, as jsonEncode was deprecated in new versions, though it works, but you should use the new way to encode it.
Also, you should use async-await while doing any asynchronous work.
Future<void> request() async {
Map<String, String> headers = {
'Content-type': 'application/json',
'Accept': 'application/json',
};
Map body = {"usuario": "edigleyssonsilva",
"senha": "123456",
"codEmp": 1,
"codFil": 1,
"produtos": [
{
"ccuRes": "160",
"codEmp": 1,
"codFil": 1,
"codPro": "570.0001",
"codTns": "90250",
"datPrv": "2020-02-17",
"datEme": "2020-02-17",
"qtdEme": 2
}
]};
final response = await http.post(url,
body: json.encode(body),
headers: headers,
).catchError((err) {
print('Ocorreu um erro');
print(err);
});
print('Response: ${response.body}');
}

If this only happens when calling a service on localhost:
Change your url from http://localhost:8080/bla to
http://10.0.2.2:8080/bla.
The problem is that your emulator doesn't understand localhost, like your machine's localhost, so to access it you need to switch to 10.0.2.2

Related

Firebase HTTP Function triggered twice when POST request sent with headers

I deployed a firebase HTTP cloud function and am experiencing this (unexpected) behavior:
when I call the function (using POST) from a browser environment with fetch(), the function gets triggered twice, one time without any data sent in the body, and another time as I would expect it. In the frontend (chrome network tab) I can only see 1 request, the successfull one.
this does only happen with POST requests
this does only happen when the request is sending headers
Is this normal behavior that I dont understand or a potential bug?
my minimal cloud function
exports.run = functions.https.onRequest(async (req, res) => {
// ALLOW CORS FOR POST REQUEST:
// => https://stackoverflow.com/a/38259193
res.set('Access-Control-Allow-Origin', '*');
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
return res.status(200).send({
status: "ok",
body: req.body,
query: req.query,
}).end();
});
calling from frontend
// example data (not a real one)
const url = "https://us-central1-myproject.cloudfunctions.net/test";
const postData = { x: 1, y: 2 };
// GET request => ✅ works as expected
fetch(url);
// POST request without headers => ✅ works as expected
fetch(url, {
method: 'POST',
body: JSON.stringify(postData),
});
// POST request with headers => ❌ 2 requests get triggered
fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(postData),
});
This behavior is happening because of the CORS preflight request:
A CORS preflight request is a CORS request that checks to see if the CORS protocol is understood and a server is aware using specific methods and headers.
...
A preflight request is automatically issued by a browser, and in normal cases, front-end developers don't need to craft such requests themselves. It appears when a request is qualified as "to be preflighted" and omitted for simple requests.
As pointed in this other question:
As long as you’re adding a Content-Type': 'application/json' header to the request, the browser is going to automatically on its own do a CORS preflight OPTIONS request before trying the request from your code.
Therefore, this is a normal behavior and is not a problem of Cloud Functions for Firebase.
In order to not have the two requests, you can change the header request as suggested by this answer:
// example data (not a real one)
const url = "https://us-central1-myproject.cloudfunctions.net/test";
const postData = { x: 1, y: 2 };
// POST request with different header => ✅ only one request is triggered
fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: JSON.stringify(postData),
}).then(data => console.log(data));

Deno - How to fetch data from distant API or URL?

I'm wondering how I can get data from other servers and API with deno ? Everything in the documentation teach me about making http servers and read files from local source. But I can't find anything useful about reading something on the network.
How can read JSON data from the Stripe API ? Or if I want to read a HTML file with text inside ?
Thank you for your time!
I am just giving you an example of the GET request for fetching repositories of Github.
You can change the URL and Request Configuration as per your need.
In the code given below, I am calling another API of Github. By using the fetch() method you can do that.
fetch() method first takes the URL as the first parameter and the next parameter is RequestInit which takes the request method type, headers, body, etc and at the end returning JSON response of that API call.
const githubResponse = async (): Promise<any> => {
const response = await fetch("https://api.github.com/search/repositories?q=android", {
method: "GET",
headers: {
"Content-Type": "application/json",
},
});
return response.json(); // For JSON Response
// return response.text(); // For HTML or Text Response
}
console.log(await githubResponse());
I have written the above code in a ts file named Testing.ts . So, you can run the above code by the command given below:
deno run --allow-net Testing.ts
Next, I am giving you a sample POST request code:
const githubResponse = async (): Promise<any> => {
const body: URLSearchParams = new URLSearchParams({
q: "AvijitKarmakar",
});
const response = await fetch("https://api.github.com/search/repositories", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: body
});
return response.json();
// return response.text(); // For HTML or Text Response
}
console.log(await githubResponse());
You can see that I have created a body object and passed it in the RequestInit through the body parameter and also changed the request method type to POST.
You'll need to do a HTTP Request, for that in Deno you use fetch, the same Web API the browsers use.
To read JSON response:
const res = await fetch('https://api.stripe.com');
const data = await res.json();
If you want HTML:
const res = await fetch('https://example.com');
const html = await res.text();
// Now you can use some HTML parsing lib
fetch requires the --allow-net flag.
Deno strives to be as close to the existent browser API as possible.
That means, you can use fetch. Example:
// fetch-kitten.ts
fetch("https://placekitten.com/200/300").then(async (d) =>
Deno.writeFile("kitten.jpg", new Uint8Array(await d.arrayBuffer()))
);
CLI:
deno run --allow-net --allow-write fetch-kitten.ts
Reference

Flutter First Http Request Not Firing

I'm developing a Flutter application, now working on authentication. When a user enters their credentials, I send a post request to my server (.NET Core). The problem is the first request (login in this case) doesn't fire and doesn't timeout, basically it stays in an infinite loop. If I change something in the app that triggers a hot reload, then the request fires and the next ones work just fine. Seems like a odd behaviour.
I've tried to await for the response and also tried using .then() clause, both have the same behaviour:
Future<Response> post(String path, String body) async {
final response = await http.post(url + path, headers: {
HttpHeaders.contentTypeHeader: 'application/json'
}, body: body);
// .then((res) => print(res));
...
}
Been stuck on this for 2 days and can't find a logical explanation for this behaviour. Anyone has/had the same problem?
I hope this should help you
post(String path, String body) async {
final response =
await http.post(url + path,
headers: { HttpHeaders.contentTypeHeader: 'application/json' },
body: body);
print (response.body());
}

Network request failed on Android when using fetch to post to cloud functions

I am using the guide explained here
to upload images to firebase cloud storage using cloud function as a middle ware or at least that what I understood from the guide.
My issue is with the fetch request at the client side:
const body = new FormData();
body.append("picture", {
uri: imageUri,
name,
type: type
});
await fetch(`${cloudFunctionUrl}`, {
method: "POST",
body,
headers: {
Accept: "application/json",
"Content-Type": "multipart/form-data"
}
}).then(async() => {
// do things
}).catch(error => {
console.log(error);
reject(error);
});
On iOS it works like a charm but on Android I get a network request failed error.
The publisher of the guide above declared that the method works for both iOS and Android.
Some topics suggested that the problem is with the headers of the request when it comes to Android, but didn't specify exactly what is wrong.
The issue was passing type = "jpg" while it should be type= "image/jpg". Thanks to Kadi

"415 Error" when querying Spotify for tokens

I've been trying to recreate the spotify oauth connection in MeteorJS. I've gotten as far as requesting the access and refresh tokens, but I keep getting a 415 error now. Here is the relevant code:
var results = HTTP.post(
'https://accounts.spotify.com/api/token',
{
data: {
code: code,
redirect_uri: redirectURI,
grant_type: 'authorization_code',
client_id: clientID,
client_secret: clientSecret
},
headers: {
'Content-Type':'application/json'
}
}
);
I can't seem to find any other good documentation of the problem and the code in this demo:
https://github.com/spotify/web-api-auth-examples/tree/master/authorization_code
works perfectly.
I had a similar problem (but in Java). The analogous solution was
headers: {
'Content-Type':'application/x-www-form-urlencoded'
}
You need to use params instead of data when sending the JSON object. Related question: Unsupported grant type error when requesting access_token on Spotify API with Meteor HTTP
I have successfully tried getting the access token from Spotify, using the below function. As you can see, you don't need to specify Content-Type, but just need to use params instead of data (as far as axios is concerned). Also make sure that you first combine the client id and the client secret key with a ":" in between them and then convert the combined string into base 64.
let getAccessToken = () => {
let options = {
url: 'https://accounts.spotify.com/api/token',
method: 'POST',
headers: {
// 'Content-Type':'application/x-www-form-urlencoded',
'Authorization': `Basic <base64 encoded client_id:client_secret>`
},
params: {
grant_type: 'client_credentials'
}
}
axios(options)
.then((resp) => {
console.log('resp', resp.data)
})
.catch((err) => {
console.log('ERR GETTING SPOTIFY ACCESS TOKEN', err);
})
}
If youre doing this clientside its not working because you're not allowed to post to another domain from the client side because of the same origin policy.
If this is server-side I'd recommend using a pre-existing spotify api npm module instead of writing your own requests. There are plenty of spotify api implementations on npmjs.org.
Use arunoda's npm package for integrating npm packages in your meteor application

Resources