What is difference between node-fetch(nodejs) and requests(python) - python-requests

python codes get response but javascript code can't get response.
what is diff between the two??
import fetch from 'node-fetch';
const url = "http://host3.dreamhack.games:15592/img_viewer"
const imageUrl = "/static/dream.png"
const data = {
"url": imageUrl
}
const res = await fetch(url, {
method: "POST",
body: JSON.stringify(data)
})
const text = await res.text()
console.log(text)
//<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
//<title>500 Internal Server Error</title>
//<h1>Internal Server Error</h1>
//<p>The server encountered an internal error and was unable to complete your request. Either the //server is overloaded or there is an error in the application.</p>
import requests
url = "http://host3.dreamhack.games:15592/img_viewer"
imageUrl = "/static/dream.png"
data = {
"url": imageUrl
}
response = requests.post(url, data=data)
print(response.text)
I think the two codes are same, why get different response?
(after time above url is not available)
** server
#app.route("/img_viewer", methods=["GET", "POST"])
def img_viewer():
if request.method == "GET":
return render_template("img_viewer.html")
elif request.method == "POST":
url = request.form.get("url", "")
urlp = urlparse(url)
if url[0] == "/":
url = "http://localhost:8000" + url
elif ("localhost" in urlp.netloc) or ("127.0.0.1" in urlp.netloc):
data = open("error.png", "rb").read()
img = base64.b64encode(data).decode("utf8")
return render_template("img_viewer.html", img=img)
try:
data = requests.get(url, timeout=3).content
img = base64.b64encode(data).decode("utf8")
except:
data = open("error.png", "rb").read()
img = base64.b64encode(data).decode("utf8")
return render_template("img_viewer.html", img=img)

I see 2 reasons:
The headers in node-js might be drifferent by default. You could specify them to make the requests identical tho.
It seems like javascript has a different fingerprint than python-requests, even when using the same headers. Some websites like cloudfare can detect that, and then usually throw a 403 [Forbidden] http error.
But I didn't find out, what exactly is defferent that case.

Related

Cannot await combined future of multiple async requests, proc hangs when doing so

I wanted to do some performance testing of my site. For that purpose I wanted to fire n requests asynchronously, combine the Futures that result of that into one future that completes when they all complete and then wait for that futures completion.
However, my code gets stuck awaiting the combined future and never completes.
My code looked like this:
import benchy
import std/[sugar, strformat, sequtils, httpclient, asyncfutures, asyncdispatch]
proc callSite(client: AsyncHttpClient, url: static string, callCount: int): Future[string] {.async.} =
var futures : seq[Future[AsyncResponse]] = #[]
for x in 1..callCount:
futures.add client.get(url)
echo "pre combo"
let comboFuture = all(futures)
let responses = await comboFuture
echo "post awaited combo"
result = await responses[0].body
echo "post response"
var myClient = newAsyncHttpClient()
myClient.headers = newHttpHeaders({
"Authorization": "Bearer " & token,
"Accept": "application/json"
})
const url = <Some URL>
timeIt "campaign overview":
let x = waitFor myClient.callSite(url, 3)
keep(x)
When I run this I never get past "pre combo", the request gets stuck, even though the server receives 3 requests and sends 3 responses (I checked that in server-side logs).
What is going wrong here?
The reason for the issue is that clients from std/httpclient do not support a client dealing with more than one request at a time!
import benchy
import std/[sugar, strformat, sequtils, httpclient, asyncfutures, asyncdispatch]
proc callSite(clients: seq[AsyncHttpClient], url: static string): Future[string] {.async.} =
var futures : seq[Future[AsyncResponse]] = #[]
for client in clients:
futures.add client.get(url)
let comboFuture = all(futures)
let responses = await comboFuture
result = await responses[0].body
proc createMyClient(): AsyncHttpClient =
result = newAsyncHttpClient()
result.headers = newHttpHeaders({
"Authorization": "Bearer " & token,
"Accept": "application/json"
})
let fiftyClients: seq[AsyncHttpClient] = (1..50).toSeq().mapIt(createMyClient())
const url = <Some Url>
timeIt "50 client":
let x = waitFor fiftyClients.callSite(url)
keep(x)

How to pass form-urlencoded data in GET request with SWIFT 5

I'm using Swift 5 and attempting to get an access token from an API I'm developing using asp.net MVC. With Postman I set my request to GET, pass in some information in the body, and I get back an access token.
In XCode when I try this it gives me the error: "GET method must not have a body."
My Code:
func GetToken(email: String, password: String) {
let dataToSend = [
"grant_type": "password",
"username": email,
"password": password
]
let newData = try! JSONSerialization.data(withJSONObject: dataToSend, options: [])
var request = URLRequest(url: getNewTokenURL)
request.httpMethod = "Get"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = newData
URLSession.shared.dataTask(with: request) { (data, response, error) in
guard let data = data else {return}
do {
let myData = try JSONDecoder().decode(TokenResponse.self, from: data)
self.userToken = myData.accessToken
}
catch {
}
}.resume()
}
How do I perform the GET request with the data I need to send to it?
GET requests don't have a body. Parameters in a GET request are passed along with it's url as query parameters.
let url = URL(string: "https://www.example.com/getExample?sampleParam=sampleValue&anotherParam=anotherValue")
Edit: Also you need to give method in all caps. Since GET is the default you didn't have an issue.
Also if you are sure that the data is being passed as JSON then the method should be a POST method for that you just need to set the method of the request to POST as follows:
request.method = "POST"
Note: It's case sensitive.

How do I set headers on Flutter/Dart http Request object?

I need a way to set the headers of the dart http Request object to application/JSON.
I want to build a Request object to send to my backend API. I set the body to my JSON object, but when it gets sent, it defaults the headers to text/html instead of application/json.
I have tried using the built-in method
http.post(url,dynamic body);
but unfortunately this method places the body in the parameters of the URL and I need it in the actual body of the request.
So instead I built an http Request object, and manually set the URL and body but like I said, it sets the headers to text/html.
I have read the docs for https://pub.dev/documentation/http/latest/http/Request-class.html, but unfortunately, I haven't found a way to set the headers.
postRequest(uri) async {
Uri url = Uri.tryParse("https://ptsv2.com/t/umt4a-1569012506/post");
http.Request request = new http.Request("post", url);
request.body = '{mediaItemID: 04b568fa, uri: https://www.google.com}';
var letsGo = await request.send();
print(letsGo.statusCode);
}
Much thanks for any possible solutions!
Ps. this is my first ask on Stack Overflow so I apologize if I made any errors in posting.
Solved!
postRequest(uri) async {
Uri url = Uri.tryParse("https://ptsv2.com/t/umt4a-1569012506/post");
http.Request request = new http.Request("post", url);
request.headers.clear();
request.headers.addAll({"content-type":"application/json; charset=utf-8"});
request.body = '{mediaItemID: 04b568fa, uri: https://www.google.com}';
var letsGo = await request.send();
print(letsGo.statusCode);
}
I was having some issues with the Request object default setting the encoding.
By manually specifying utf-8, the server I am contacting accepts it.
for the post or get any request you can Add Header like this -
var permAddUrl = 'your requested url';
var bodyParameters = {
'Email': email,
'MobileNo': mobileNumber,
};
await http.post(
requesturl,
headers: { 'Content-Type': 'application/x-www-form-urlencoded',
"Authorization":"$token",
},
body: bodyParameters,).then((response) {
var data = json.encode(response.body);
print(data);
setState(() {
if(response.statusCode == 200){
//var statesList = data['data'];
UtilAction.showSnackBar(context, " Details Submitted Successfully");
}
});
});

flutter: HTTP get request - disable encoding parameters

I'm trying to make a demo app with flutter and trying to fetch products from a demo magento site.
This is my code:
Future<List<Product>> fetchProducts() async {
final params = <String, String>{
'searchCriteria[filter_groups][0][filters][0][condition_type]': 'in',
'searchCriteria[filter_groups][0][filters][0][field]': 'type_id',
'searchCriteria[pageSize]': '20',
'searchCriteria[filter_groups][0][filters][0][value]': 'simple,configurable,bundle',
'searchCriteria[currentPage]': '1',
'searchCriteria[sortOrders][0][field]': 'created_at',
'searchCriteria[sortOrders][0][direction]': 'DESC'
};
var uri = Uri.parse('https://demo.com/rest/v1/default/products');
uri = uri.replace(queryParameters: params);
print(uri);
final response =
await http.get(uri, headers: {HttpHeaders.authorizationHeader: "Bearer qb7157owxy8a29ewgogroa6puwoafxxx"});
if (response.statusCode == 200) {
// If the call to the server was successful, parse the JSON.
final data = json.decode(response.body);
final products = data["items"] as List;
return products.map<Product>((json) => Product.fromJson(json)).toList();
} else {
// If that call was not successful, throw an error.
throw Exception('Failed to load post');
}
}
When I debugged, the response was 400 - Bad request. I guess that because the uri was encoded to include percentage characters as I printed as below:
So how can I disable encoding the uri?
Thank you, guys.
I believe you should replace:
var uri = Uri.parse('https://demo.com/rest/v1/default/products');
uri = uri.replace(queryParameters: params);
print(uri);
with:
var uri = Uri.https('demo.com', '/rest/v1/default/products', params);
more on this: Uri.https
more on: replace
example result:
regardless of this, if I try with your params, the library behaves normal and encodes the special characters. (see more here)
if we put the actual request in the browser to check the response:
https://demo.mage-mobile.com/rest/v1/default/products?searchCriteria[filter_groups][0][filters][0][condition_type]=in&searchCriteria[filter_groups][0][filters][0][field]=type_id&searchCriteria[pageSize]=20&searchCriteria[filter_groups][0][filters][0][value]=simple%2Cconfigurable%2Cbundle&searchCriteria[currentPage]=1&searchCriteria[sortOrders][0][field]=created_at&searchCriteria[sortOrders][0][direction]=DESC
we get the following response:
And this brings me to my initial suspicion: the API does not support this call.
Maybe you should also check this type of param from your code: 'searchCriteria[filter_groups][0][filters][0][condition_type]', it seems you are trying to acces some information from a collection but you actually writing a string...
try removing the quotes (' bla bla ') from these params id... also try to put the request direcly in the browser(or postman) to see it work.
About the encoding (changing [ to %5B) -- this is normal and it should happen.

Dart: HTTP GET with Header

I'm working on creating a Flutter application that works with LIFX. I'm trying to follow their instructions here, but I'm having issues adding a header to my HTTP GET request.
TestHttpGet() async {
var httpClient = new HttpClient();
var header = "Bearer $token"; //token hidden
var url = 'https://api.lifx.com/v1/lights/all/state';
String result;
try {
var request = await httpClient.getUrl(Uri.parse(url));
request.headers.set("Authorization", header);
var response = await request.close();
if (response.statusCode == HttpStatus.OK) {
var json = await response.transform(UTF8.decoder).join();
print(json);
var data = JSON.decode(json);
result = data['brightness'].toString();
} else {
result =
'Error getting response:\nHttp status ${response.statusCode}';
}
} catch (exception) {
result = 'Failed parsing response';
}
This returns with Error getting response: Http status 404. I've tried various ways of request.headers .set .add [HttpHeaders.Authorization] = "header" all return with a 404. Any advice would be appreciated.
You can pass a Map<String, String> to the http.get call as the headers parameter like this:
await httpClient.get(url, headers: {
'Authorization': 'Bearer $token',
});
In order to set headers you can't set the entire variable since it is set as final. What you need to do is set the value of the individual array items which are also known as the individual "headers" in this case.
For example :
http.Request request = http.Request('GET', uri);
request.headers['Authorization'] = 'Bearer $token';
I believe dart makes all the fields of a HttpHeader to lowercase.
https://github.com/flutter/flutter/issues/16665
The argument for that is because "Field names are case-insensitive". (otherwise it is not HTTP compliant)
https://www.rfc-editor.org/rfc/rfc2616#section-4.2
Let me know if you found a workaround for this.

Resources