I have a web app hosted on IIS 7 that is doing Http calls using the Google Fit API, I'm able to successfully send a POST and retrieve an access token, after which I do a GET for the following uri:
"https://www.googleapis.com/fitness/v1/users/me/dataSources/raw:com.google.weight:com.google.android.apps.fitness:user_input/datasets/00-1427209862000000000"
Here's how I build a request and look at the response:
request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = "GET";
request.ContentLength = 0;
request.Accept = "application/json";
request.Headers.Add("Authorization", "Bearer " + dict["access_token"]);
response = (HttpWebResponse)request.GetResponse();
respStream = response.GetResponseStream();
sResponse = new StreamReader(respStream).ReadToEnd();
respStream.Close();
Response.Write(sResponse);
When I run this app on a browser on the host server, I successfully get a json object (it isn't the json I expect, but that's another issue). However, when I try to access the site on a remote client, I get a 403 error pointing to when I try to retrieve the response. Any ideas?
It probably depends how you got the access_token value.
How long after retrieving the access token are you making this request? It's only valid for an hour, so you may need to fetch a new one using the refresh token.
There's some more resources on access/refresh tokens this question:
Google OAuth2 Refresh_token expires when Access_token does
Update: This turned out to be a permissions issue. I was trying to access a data source that I didn't have scopes for, the fact that it didn't return a 403 when accessing on the host threw me off the trail. Still strange that it didn't return a 403 (it just returned an empty json object) when requested on the host server though...if you see this and have an idea why, feel free to comment. I'm curious.
Related
My Flutter web app needs to call an API when the user submits a contact form. The API is that of a discord bot that proceeds to post the message in a specific channel on my Discord server. This setup works fine for two other apps that are using the same dependencies and the same production environment (Firebase hosting), but on this specific app it throws the following error:
Access to XMLHttpRequest at
'https://discordapp.com/api/channels/689799838509957177/messages' from
origin 'https://autonet.tk' has been blocked by CORS policy: Response
to preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource.
If I add the header 'Access-Control-Allow-Origin': '*' to the request, I just get a XMLHttpRequest error
My code:
import 'package:http/http.dart' as http;
var resp = await http.post(
"https://discordapp.com/api/channels/689799838509957177/messages",
headers: {
'Authorization': "Bot " + botToken,
},
body: {
"content": "NEW MESSAGE: " + body
});
Making it harder to triangulate the root cause is the fact that this runs fine on my local machine. It's only once I deploy the app to Firebase hosting that I get that CORS error.
Another thing worth noting is that on the Discord side, there is no configuration that I had to make in order to accept the incoming request for the other two web apps that work fine using the same code. (There is no list of allowed hosts).
'Access-Control-Allow-Origin' it's a header that must be in the response, not in the request. For more information, I suggest you this read:
https://stackoverflow.com/a/20035319/14106548
EDIT:
After a small research I think you are calling the wrong endpoint. This is why the response doesn't have the proper header attached.
The endpoint is:
https://discord.com/api
For more info look at: https://discord.com/developers/docs/reference
I'm hitting an API using http dart library while doing this I'm getting 302 status code. I know that 302 status code is for redirects, can you please say how can i enable redirects in http post method. I have used the following code:
Future<LoginModel> login(String username, String password) async {
var client = new http.Client();
final response =
await client.post(LOGIN_URL +"username=Student&password=2018" ,
headers: {'Content-type': 'application/json',
'Accept': 'application/json'});
if (response.statusCode == 200) {
return LoginModel.fromJson(json.decode(response.body));
} else {
throw Exception('Failed to load post');
}
}
302 is a status code returned by the server to indicate that the client should retry the request using a different URL. It's a way to redirect the client to a different endpoint.
The problem is that only GET (or HEAD) requests can be retried automatically. You are using a POST.
If the 302 status code is received in response to a request other than
GET or HEAD, the user agent MUST NOT automatically redirect the
request unless it can be confirmed by the user, since this might
change the conditions under which the request was issued.
A well-behaved API should probably not issue 30X in response to a POST, but it is. The way to get around this is to make a new http request with the redirected URL. (You might want to put it in a while loop to keep following the redirects until you get to 200, or some error, or reach a timeout/limit.)
add header with
"Accept":"application/json" . henceforth it will only return json data otherwise it will prompt to redirect with html url, default dio configuration does not have response type so you have to mention it in header.
This is because of some issue with the URL that you use. status code 302, says that the URL you are using has been moved or redirected.
May be the loginurl that you are using has certificates now and using https:// instead of http://
When I execute HttpWebRequest.GetResponse on URL, GetResponse returns "The remote server returned an error: (400) Bad Request." instead of response.
The strange thing is that when I run this url at the browser I get the right response.
doesn't webrequest need to return the same values as the browser?
the following code return bad request
// Create a request for the URL.
WebRequest request = WebRequest.Create(
"http://someUrl/api/v5/basicAuth");
// Get the response.
WebResponse response = request.GetResponse();
// Display the status.
Console.WriteLine(((HttpWebResponse)response).StatusDescription);
// Get the stream containing content returned by the server.
Stream dataStream = response.GetResponseStream();
// Open the stream using a StreamReader for easy access.
StreamReader reader = new StreamReader(dataStream);
// Read the content.
string responseFromServer = reader.ReadToEnd();
// Display the content.
Console.WriteLine(responseFromServer);
// Clean up the streams and the response.
reader.Close();
response.Close();
also tried using WebClient with same results.
any idea how to get the proper response same as the browser?
The title says you're getting a 400 bad request, but in your question you say 404 Not Found. Those are very different. For a 404, I'd be troubleshooting the URL itself and how the request is being routed, DNS, etc. if it's a 400, then I would use something like Fiddler to capture how my request looks when using a browser, then see what the request looks like when coming from the program and see what's different/missing. It could be that some HTTP headers are needed, such as the content-type, or handling of cookies, etc etc. But something like Fiddler could at least get you started.
I am trying to login to a site, and then view user details.
The API documentation from the site is:
LogOn : All Calls with JSON and return JSON type
post - https://www.bit2c.co.il/Account/LogOn {UserName:'',Password:'',SecondFactor:[optional]}
return true if OK , error list of strings if not
Balance - GET https://www.bit2c.co.il/Account/Balance
return UserBalance as JSON
I've tried connecting to the site using
import requests
session=requests.session()
session.auth = ("username", "pass")
session.post("https//www.bit2c.co.il/Account/Balance")
but i am getting response 200 and the response content is "you must login".
What am I doing wrong ?
What kind of session? What is on server-side? Can you post the raw request/response pair(s)?
If PHP or ASP runs on server-side, you must capture the Set-Cookie header of the response to the login request, find the session cookie and in consequent requests you must set the Cookie header with the session cookie name and value captured previously.
I want to post data to another server (JSP or ColdFusion).
Note: Post which means the data is required at the another server also the browser should be redirected automatically.
Is it better to use
form tag...input type hidden fields, values
...
and from javascript
form.submit();
or
HttpWebRequest myRequest =
(HttpWebRequest)WebRequest.Create("http://...");
myRequest.CookieContainer = new System.Net.CookieContainer(10000);
myRequest.Method = "POST";
myRequest.ContentType = "application/x-www-form-urlencoded";
myRequest.ContentLength = data.Length;
Stream newStream = myRequest.GetRequestStream();
newStream.Write(data, 0, data.Length);
newStream.Close();
return myRequest;
or
I should use WebClient class?
Please provide the points from Security view also.
If you want the browser to be correctly sent to the other server, then you should really do this client side - your second option will send the response from the remote server back down to the client, but any links in the HTML that are relative will appear broken, as the user will be attempting to request them from your server.
Also, making the request from the code-behind, you'll be sending the request from your server, without any of the client's cookies, headers, etc for that site (which you won't have access to).
The other issues to consider:
Client may have JavaScript disabled.
If the remote server supports SSL, then you should probably be posting to that.
Doing this client side, you'll be sending all form data to the client initially, and then sending it on to the 3rd party server.