I'm new to HttpClient class and I'm having issue with monitoring requests using Charles Proxy. Basically what I need is to monitor the requests which are made either from simulator or actual iOS device. Here you can find a great tutorial of how to configure Charles for iOS development.
I was making simple HttpClient requests for instance, just a simple authorisation
async Task<string> authorizeUser()
{
HttpClient _client = new HttpClient ();
_client.BaseAddress = new Uri("https://...../api/");
_client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue ("bearer", token);
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("grant_type", "password"),
new KeyValuePair<string, string>("username", "theUserName"),
new KeyValuePair<string, string>("password", "thePassword")
});
var result = await _client.PostAsync("auth", content);
string resultContent = result.Content.ReadAsStringAsync().Result;
return resultContent;
}
The code works, the user is being authorised, and the bearer token is being returned. But what was the issue, that my requests on the simulator were not appearing in the Charles http traffic monitoring list.
I thought perhaps, it is because I'm using simulator, but that was not the case. I tried opening the safari and browsed some web page and the traffic immediately appeared. So the issue was not from the simulator.
I also tried installing on the device, and again the same story, when using HttpClient the traffic monitoring screen remains silent, but as soon as I open the browser, the traffic screen starts jiggling and usurping all the requests.
I thought may be it is because I use HTTPS, although in any case at least the request header should be captured, even though the body is encoded. But that was not the case, I tried opening some HTTPS site on my device safari and again the traffic appeared on my Charles screen.
The next thing that I did I downloaded monotouch HttpClient sample. And the good news is that there are several methods of sending requests, actually four of them -
1. http WebRequest,
2. https WebRequest,
3. http NSUrlConnection ,
4. HttpClient.
And I tried them all, as you may guess first three perfectly appeared in charles, but the last HttpClient again I don't know why didn't show up in traffic log screen.
So I'm 100% sure that the issue is the HttpClient class, which I don't know why despite the fact that it is working normally, that is sending/receiving requests, the requests made by this class can not be captured by Charles.
And to exclude the last possible reason for this issue, that is may be the problem is in Charles, I also tried using Fiddler on Windows, which was running as a virtual machine on my Mac (here you can find how to do that), the same story was repeated - all the requests made by HttpClient were not captured, the rest (WebRequests, NSUrlConnection-s, safari web page openings) worked perfectly fine.
Please, can anybody suggest me, whether it is some kind of bug, may be there is workaround or other solution to this problem.
Thanks all for your Replies
Kind Regards Gagik
There's many ways to initialize HttpClient. Some ways won't talk with the OS (fully managed) and won't be aware of the iOS proxy settings.
The best (for iOS) is generally to use the handler that uses CFNetwork, see this blog for more details. Basically it means:
var client = new HttpClient (CFNetworkHandler ());
Otherwise you'll need to set the HttpClientHandler.Proxy to CFNetwork.GetDefaultProxy. E.g.
var handler = new HttpClientHandler {
Proxy = CFNetwork.GetDefaultProxy (),
UseProxy = true,
};
var client = new HttpClient(handler);
Related
I'm trying to do an API request using Axios, it works in every windows' and Android browsers but does not work on MacOs Safari (but in Chrome it works fine) or any iOs browser.
In the same code I make another calls to the same API (different endpoints) and it works with no problems at all in safari and iOs.
When I console.log the throwed exception turns out that's a Network error.
I don't think that's a CORS issue, couse it works on another browsers.
My request:
try {
const response = await api.get(
"/precos/get",
{
headers: {
'Content-Type': 'application/json'
'token': getToken()
}
}
);
this.filtraProdutoPorTabela(response.data.data);
} catch (err){
// do something with the error
}
Console error:
Network Error
{"url":"http://url/precos/get","method":"get","headers":{"Accept":"application/json, text/plain, /","this.state-Type":"application/json","token”:”e…c”},”baseURL”:”the base url ”,”transformRequest":[null],"transformResponse":[null],"timeout":0,"xsrfCookieName":"XSRF-TOKEN","xsrfHeaderName":"X-XSRF-TOKEN","maxContentLength":-1,"httpsAgent":{}}}
The only problem that would cause this that I can think of is that you for sure have the links on your computer set to for example: http://localhost:5000/api/posts
And that works fine since your doing it in the same machine but when you try it on your mobile devices or any other device when the browser tries to hit that route it sees the localhost portion of the url and it points to it self not your actual machine.
To solve this problem you have to put the ip address and the port of your machine not the literal text "localhost".
From:
http://localhost:5000/api/posts
To:
http://192.168.1.23:500/api/posts
http://{ YOUR IP ADDRESS }:5000/api/posts
When investigating this issue on my own I came across this post:
link not working in Safari.
For some reason on Safari link event is not being triggered. I had my onClick action, that was triggering axios call, bind to html <a /> tag. Safari was not letting axios execute request properly.
Adding:
event.preventDefault()
to function called by tag when clicked solved the issue.
Why are directory methods in path_provider awaited like so? They are not over the internet calls to the network.
Directory tempDir = await getTemporaryDirectory();
String tempPath = tempDir.path;
Directory appDocDir = await getApplicationDocumentsDirectory();
String appDocPath = appDocDir.path;
Edit:
I don't think I was specific enough. I understand from the method signature that it returns a future. I was more asking as to why it is a future, why the methods are asynchronous.
Is it because they are kind of like unix file system writes/reads, ie blocking?
Because the underlying code is asynchronous, and returns a Future. To get the value returned from a Future you must either use await or .then().
path_provider uses MethodChannel to call native code, and the MethodChannel.invokeMethod() function is asynchronous. Specifically, the interface to native code (platform channels) works by sending a message and waiting for a response. It does this asynchronously so it does not lock up your app while waiting for your request to complete on the native side.
Flutter’s platform-specific API support does not rely on code generation, but rather on a flexible message passing style:
The Flutter portion of the app sends messages to its host, the iOS or Android portion of the app, over a platform channel.
The host listens on the platform channel, and receives the message. It then calls into any number of platform-specific APIs—using the native programming language—and sends a response back to the client, the Flutter portion of the app.
Futures and asynchronous code are not just for network/internet related work.
path_provider's API is asynchronous because it communicates with platform-native Android or iOS code, and Flutter uses an asynchronous message-passing system for that communication.
I have a notification in my Wear OS application with an action, and I've been searching how to send a post request when the notification action is triggered. Is there a way to do this?
I know that Android Wear 2.0 has Internet capabilities, and I've seen examples of opening a browser with a notification, but nothing for sending an HTTP request.
NotificationManager notificationManager = (NotificationManager) context.GetSystemService(Context.NotificationService);
Intent respondIntent = new Intent(context, typeof(AlarmReceiver));
PendingIntent respontPendingIntent = PendingIntent.GetActivity(context, 0, respondIntent, PendingIntentFlags.UpdateCurrent);
Notification.Action action = new Notification.Action(Resource.Drawable.generic_confirmation,"hello", respontPendingIntent);
var noti = new Notification.Builder(context)
.SetContentTitle("Title").SetContentText("content text")
.SetSmallIcon(Resource.Drawable.pills)
.AddAction(action);
notificationManager.Notify(notificationId, noti.Build());
That's what I have so far (currently the action doesn't do anything).
There are many different ways to accomplish this, but the common theme is that a PendingIntent is just a hook to some other component of your app where the work actually happens. You don't put your HTTP request in the Intent, as it were, you put it in the app component that the Intent invokes.
In your case, rather than opening the AlarmReceiver Activity from your 'PendingIntent', you'll probably want to launch something like an IntentService or a BroadcastReceiver instead and put your network operations in there. If you also need to open AlarmReceiver, you can do that in your BroadcastReceiver as well.
Which component to use depends on the bigger picture of what your app is doing, and is beyond the scope of a StackOverflow answer. But this is pretty basic Android app-architecture stuff, really.
I have an indexedDB database used in a web app on my iPhone.
Lately it started to take more time to start. After diagnosing this case for some time I've found that it happens because of indexedDB.open() running for 10+ seconds.
Here is a little code example
var db;
var promise = utils.promise();
var openRequest = indexedDB.open(this.dbName, this.version);
openRequest.onsuccess = function(evt) {
db = openRequest.result;
promise.resolve();
};
openRequest.onerror = function(evt) {
promise.reject();
onError(evt, 'Database open');
};
Database itself didn't change lately so much. Also I don't have lots of data. It has around 300 records.
Any idea how to diagnose such an issue?
UPD may be related https://bugs.chromium.org/p/chromium/issues/detail?id=402980
Apparently it was a result of iOS update (from 11.1.* to 11.2.*).
I have my web app added to the Home Screen. And as far as I understand when you do iOS updates the web app container is moved to a new iOS environment but conserves some features from the original iOS version (probably something related to WebView used for web app but I am not sure).
So I have added my web app to Home Screen again and it starts without delays.
I'm working on embedding a soft phone into a web page that will go into Odoo (web based ERP system). It will allow inbound and outbound calls for employees.
The token expires every hour. So this means the user will have to refresh the page every hour. I could do an http refresh but if the user is on a call when it does the refresh it will knock them off the call.
How do we get around this so we can build a fully working dialer?
Twilio evangelist here.
I'd suggest using JavaScript to do an asynchronous HTTP request to get a new token from your server and then updating the instance of client with it.
Hope that helps.
Another Twilio evangelist here!
You can actually listen for the offline event on the Twilio.Device object. From the documentation:
.offline( handler(device) )
Register a handler function to be called when the offline event is
fired. This is triggered when the connection to Twilio drops or the
device's capability token is invalid/expired. In either of these
scenarios, the device cannot receive incoming connections or make
outgoing connections. If the token expires during an active connection
the offline event handler will be called, but the connection will not
be terminated. In this situation you will have to call
Twilio.Device.setup() with a valid token before attempting or
receiving the next connection.
So you want something like:
Twilio.Device.offline(function(device) {
fetchTokenFromServer(function(token) {
device.setup(token);
});
});
where fetchTokenFromServer makes the HTTP request that Devin suggested in his answer.
Let me know if this helps.
I just ran into this issue so hopefully my solution can help you and others.
I was using twilio.js v1.3 and tried implementing my offline callback like #philnash recommended, but kept getting the error device.setup is not a function. I then tried using Twilio.Device.setup(newToken) and was able to get the capability token refreshed but also ended up getting a new error: Cannot read property 'setToken' of undefined.
I ended up having to use twilio.js v1.4 to make the error go away. My working solution looks like this:
Twilio.Device.offline(function(device) {
$.ajax(urlToGetNewToken, type: 'get').done(function(newToken) {
Twilio.Device.setup(newToken)
})
})