Sometimes when starting the app, all requests will timeout with these logs :
| request: <NSMutableURLRequest: 0x170006aa0> { URL: http://#host#/api/settings?version=1428591014 }
| response: nil
| json: nil
| error: Optional(Error Domain=NSURLErrorDomain Code=-1001 "La requête a expiré." UserInfo=0x1740f0380 {NSUnderlyingError=0x174056440 "L’opération n’a pas pu s’achever. (kCFErrorDomainCFNetwork erreur -1001.)", NSErrorFailingURLStringKey=http://#host#/api/settings?version=1428591014, NSErrorFailingURLKey=http://#host#/api/settings?version=1428591014, NSLocalizedDescription=La requête a expiré.})
and here is an example of code responsible for the request call:
Alamofire.request(AppRouter.Settings.RetrieveAppSettings(Settings.sharedInstance.version))
.validate(contentType: ["application/json"])
.validate(statusCode: [200])
.responseJSON { (req, res, json, error) in
if error != nil {
// log error to local file
}
else {
// do something with data
}
}
When it happens, all the requests will fail with the same logs. One have to kill the app manually (home button) and restart it again and then all requests will succeed…
Anyone have some ideas plz ?
I had this same problem as far as I remember. It's a question of http connections not being allowed per default with newer versions of Xcode. I experienced the problem when switching to the Xcode-beta 7.0, but might have been earlier versions as well.
Try adding the following to your info.plist:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>--- YOUR DOMAIN NAME HERE - EXAMPLE: example.com ---</key>
<dict>
<key>NSIncludeSubdomains</key>
<true/>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
This allows http connections to the domain you want. Add as many domains you want as key dict pairs in the dict corresponding to NSExceptionDomains.
To insert this as XML, right click info.plist and click "Open as" -> "Source code".
Then add the above XML just before the tags at the end of the document.
Hope this works out for you :)
Related
I have a simple WKWebView in macOS. I'm facing issues with redirection when visiting a page without www that then redirects to the subdomain www.
As far as I could find out I'd simply have to allow the navigation request and the webView should handle everything itself. But the redirect never actually happens. The webView ends up in a redirect loop, calling didReceiveServerRedirectForProvisionalNavigation: over and over again until finally failing with Error Domain=NSURLErrorDomain Code=-1007 "too many HTTP redirects"
Safari, other browsers and clients do indeed succeed, what makes me believe that it's not a server issue.
Also when I enter the address redirected to directly, it does work without any issues.
I implemented the WKNavigationDelegate protocol as follows:
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
if ([navigationAction navigationType] == WKNavigationTypeOther) {
if ([[[[navigationAction request] URL] host] isEqualToString:[[[self webView] URL] host]]) {
decisionHandler(WKNavigationActionPolicyAllow);
NSLog(#"allowed");
return;
}
decisionHandler(WKNavigationActionPolicyCancel);
NSLog(#"cancelled: %#", [navigationAction request]);
}
else {
decisionHandler(WKNavigationActionPolicyAllow);
}
}
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation {
NSLog(#"provisional navigation started");
}
- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation; {
NSLog(#"provisional navigation received redirect");
}
I'm expecting the webView to accept and actually follow the redirect after I answered using WKNavigationActionPolicyAllow.
When I execute a request the following happens:
decidePolicyForNavigationAction: for main domain name
I respond with allow
didStartProvisionalNavigation:
decidePolicyForNavigationAction: for redirect with subdomain
I respond with allow
didReceiveServerRedirectForProvisionalNavigation:
Back to 6.
Do I have to somehow "commit" the redirect or do it manually myself?
Any ideas or did I miss something completely?
Stupid me. Really. Embarrassingly stupid.
My table now has my face embossed.
My original code was cut down for overview until a point where I deleted my issue...
I'm working on a special use case where the host name is not in the URL. I connect to a multi-site web server via it's IP and set the Host header accordingly to get the desired page.
When redirected I copy the request, set the header accordingly and resend the request. Guess what? Responding to a redirect by sending the same Host: header will result in another redirect. Grr.
I'll leave this here for public amusement to a day or two
I have an Ionic 2 application that calls a Spring Boot API to send push notifications to other devices. The API is configured with HTTPS.
The API POST request works on everything except iOS.
My SSL certificate on the server is self signed (maybe that's it?).
Works on:
ionic serve
Android
Postman
curl
Here is the request:
public sendNotificationRequest(title: string, action: string, name: string, tokens: any, notifications: boolean) {
// Check if user turned off notifications
if(!notifications) {
return;
}
let headers = new Headers({'Content-Type': 'application/json'});
headers.append('Authorization', 'Basic ' + btoa(this.username_decrypted + ':' + this.password_decrypted));
let body = this.formObj(tokens, title, action, name);
console.log(body);
this.http.post("https://<some-url>",
body, { headers: headers }
).subscribe((response) => {
console.log("HTTPS RESPONSE");
console.log(response);
}, function(error) {
console.log("HTTPS ERROR");
console.log(error);
});
}
The header responses are as follows:
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
And the this error is received:
{
"_body":
{"isTrusted":true},
"status":0,"ok":false,
"statusText":"",
"headers":{},
"type":3,
"url":null
}
Spring Boot API:
#CrossOrigin
#RequestMapping(value="/notifications", method=RequestMethod.POST, consumes=MediaType.APPLICATION_JSON_VALUE, produces=MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<NotificationParent> sendNotifications(#RequestBody NotificationParent objs) {
...
return new ResponseEntity<NotificationParent>(objs, HttpStatus.OK);
}
I am assuming its an iOS security issue, but I have no idea.
I had a same problem too. Removing the WkWebView solves the issue.
ionic cordova plugin remove cordova-plugin-wkwebview-engine
More info:
https://forum.ionicframework.com/t/ios10-http-requests-blocked/67663/2?u=profitsventure
After this plugin removed I can make http request via iOS
I think your assumption is correct-- an iOS security issue. In iOS there is something called App Transport Security that disallows, by default, connections over HTTP and connections with self-signed certificates.
You have to add
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
to the Info.plist of your project to allow your self-signed traffic.
See this answer as well as the below links for more info.
http://blog.ionic.io/preparing-for-ios-9/
https://gist.github.com/mlynch/284699d676fe9ed0abfa
https://developer.apple.com/library/prerelease/content/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW33
For iOS devices, the default WebViewEngine always uses CORS, to disable it temporarily, add the <preference name="CordovaWebViewEngine" value="CDVUIWebViewEngine" /> to the config.xml. However, the downgrading to UIWebViewEngine has bad performance. Solving it in the server side is the right solution.
The HTTP server should be configured to have the right response to the CORS OPTIONS preflight request. The key point is that the Access-Control-Allow-Headers can not be “*” and should include any custom headers used in your app. Below is my setting that works:
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: *
Access-Control-Allow-Headers: Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers, MyCustomHeader
For me the fix was to use #ionic-native/http instead of #angular/http.
Ionic native HTTP docs: https://ionicframework.com/docs/native/http/
Here's what lead me to that workaround https://blog.ionicframework.com/wkwebview-for-all-a-new-webview-for-ionic/
I want to install SSL(Comodo wildcard certificate, ex: "*.test.com")
in Vapor Web framework, the "servers.json" I got is:
{
"default": {
"port": "$PORT:443",
"host": "api.test.com",
"securityLayer": "tls",
"tls": {
"certificates": "chain",
"certificateFile": "/path/ssl-bundle.crt",
"chainFile": "/path/ssl-bundle.crt",
"privateKeyFile": "/path/key.pem",
"signature": "signedFile",
"caCertificateFile": "/path/AddTrustExternalCARoot.crt"
}
}
}
I already make sure that "public/private" key matches already using openssl command. And about the certificateFile part like "ssl-bundle.crt", I also tried "*.test.com.crt" with the "key.pem" as well(still pass the validation using openssl, the only difference is one is test.com's certificate, the other is bundle certificate, combined by correct orders already.). Besides, all certs and key's format are correct as well. And I also make sure the cert/key files location is correct so that the Vapor can find these files. But I still can't launch the server correctly, and always display the error.
I try to locate the exact location in xcode, but I can only see it fails in this method: "tls_accept_fds()", which is in tls_server.c of CLibreSSL library.
Also, I saw the error message the xcode displayed to me:
After use debug mode to trace, I can only know that it seems the program throws the error in "SSL_set_rfd()" or "SSL_set_rfd()", but I don't know exactly. The xcode only shows this to me, and I can't find any other error messages in the debug console. As result, so far I can only make sure that the error should be in this block:
int
tls_accept_fds(struct tls *ctx, struct tls **cctx, int fd_read, int fd_write)
{
struct tls *conn_ctx = NULL;
// I pass this block
if ((ctx->flags & TLS_SERVER) == 0) {
tls_set_errorx(ctx, "not a server context");
goto err;
}
// I pass this block
if ((conn_ctx = tls_server_conn(ctx)) == NULL) {
tls_set_errorx(ctx, "connection context failure");
goto err;
}
// I pass this block
if ((conn_ctx->ssl_conn = SSL_new(ctx->ssl_ctx)) == NULL) {
tls_set_errorx(ctx, "ssl failure");
goto err;
}
// I pass this block
if (SSL_set_app_data(conn_ctx->ssl_conn, conn_ctx) != 1) {
tls_set_errorx(ctx, "ssl application data failure");
goto err;
}
// The error occurs here, in SSL_set_rfd or SSL_set_wfd, it will then go to err part: "*cctx = NULL;", not even go into the if block.
if (SSL_set_rfd(conn_ctx->ssl_conn, fd_read) != 1 ||
SSL_set_wfd(conn_ctx->ssl_conn, fd_write) != 1) {
tls_set_errorx(ctx, "ssl file descriptor failure");
goto err;
}
*cctx = conn_ctx;
return (0);
err:
tls_free(conn_ctx);
*cctx = NULL;
return (-1);
}
So, the above is all the info I got right now, and I can't find the solution on the internet for several days already...
Could anyone give me any hint about how to install SSL in Vapor web framework? I can correctly install the SSL in Apache, Nginx, Tomcat, etc already. But never success in Vapor, it seems like C library issue, but I don't know the real reason why it fails, thank you very much for any possible help.
The bug has been found and fixed here: https://github.com/vapor/tls/pull/27
I'm using OS X Server 4.1.3 and an iPhone 6 with iOS9 Beta-4.
When I try to connect to the OS X Server ("skw.local") with
let urlPath: String = "https://skw.local/"
let url: NSURL = NSURL(string: urlPath)!
let request: NSMutableURLRequest = NSMutableURLRequest(URL: url)
let sessionConfig = NSURLSessionConfiguration.defaultSessionConfiguration()
let sesh = NSURLSession(configuration: sessionConfig)
let task = sesh.dataTaskWithRequest(request) {(data, response, error) -> Void in
if error == nil {
print("Response: \(response)")
}
else {
print(error, appendNewline: true)
}
}
task.resume()
I get the following error:
NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9813)
You might be connecting to a server that is pretending to be “skw.local” which could put your confidential information at risk."
I have tried bypassing the NSAppTransportSecurity requirements by adding the following to my Info.plist:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key><true/>
</dict>
but I get the same errors.
Anyone else having similar trouble?
edit: I also posted this over on apple's dev forum
When I register for CoreWLAN notifications (with a retained interface) like this:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(recieveNetworkNotificationAndRedirectToMainThread:)
name:CWSSIDDidChangeNotification
object:nil];
I receive the notification only when I have all entitlements disabled. None of the default entitlements allow me to receive this (or other CoreWLAN) notification.
Any ideas?
10.7.4
Edit 1:
The Entitlements Reference page did not provide any assistance.
Edit 2:
Faking the notification works fine:
[[NSNotificationCenter defaultCenter]
postNotificationName:CWSSIDDidChangeNotification
object:self];
And none of the other CoreWLAN notifications are received either.
I am sure that this is a simple entitlement that I'm missing... Here is the entitlement file with the temp exception for Growl (removing the temp exception has no effect either):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.device.usb</key>
<true/>
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.network.server</key>
<true/>
<key>com.apple.security.temporary-exception.apple-events</key>
<string>com.Growl.GrowlHelperApp</string>
<key>com.apple.security.temporary-exception.mach-lookup.global-name</key>
<string>GrowlApplicationBridgePathway</string>
</dict>
</plist>
Edit 3:
Compiling for 10.6 using the old k-prefixed notification names has no effect either.
Edit 4:
More information from the logs:
AppName (39009) deny system-socket
Process: AppName [39009] Path:
/Users/username/Library/Developer/Xcode/DerivedData/AppName-fnxrpqnodsouovcaxgiocvnfpqor/Build/Products/Release/AppName/Contents/MacOS/AppName
Load Address: 0x10d23f000 Identifier: AppName Version:
??? (???) Code Type: X86-64 (Native) Parent Process:
debugserver [39007]
Date/Time: 2012-07-20 13:17:11.851 -0700 OS Version: Mac OS
X 10.7.4 (11E2705) Report Version: 7
Backtrace: 0 libsystem_kernel.dylib 0x00007fff98704e76
socket + 10 1 CoreWLAN 0x00007fff951f4a6f
Apple80211EventMonitoringInit2 + 53 2 CoreWLAN
0x00007fff951e6dc4 -[CWInterface initWithInterfaceName:] + 1358 3
CoreWLAN 0x00007fff951e412d +[CWInterface
interfaceWithName:] + 52 4 CoreWLAN
0x00007fff951e41a8 +[CWInterface interface] + 98
Edit 5:
Found this reference to deny system-socket in sandboxd, but no help yet.
I am able to get SSID changes and updates with my app sandboxed using the networknotifier code in hardwaregrowler - I think because its looking for specific notifications.
http://code.google.com/p/growl/source/browse/Extras/HardwareGrowler/?name=default
Once I am notified of a change:
if(wif==nil){
wif = [CWInterface interface];
[wif retain];
}
if(!wif.serviceActive){
skip=TRUE;
}
if(wif.ssid==nil){
skip=TRUE;
}
if(!skip)
if(wif){
NSLog(#"We are on the WiFi network: %#",wif.ssid);
}