Enables chinese endpoint for JS API

fix #10
This commit is contained in:
Flávio Caetano 2017-10-10 11:58:14 -03:00
parent 4789110253
commit 43d9ae7495
12 changed files with 122 additions and 19 deletions

View File

@ -254,7 +254,7 @@
attributes = {
LastSwiftUpdateCheck = 0830;
LastUpgradeCheck = 0820;
ORGANIZATIONNAME = CocoaPods;
ORGANIZATIONNAME = ReCaptcha;
TargetAttributes = {
607FACCF1AFB9204008FA782 = {
CreatedOnToolsVersion = 6.3.1;

View File

@ -198,4 +198,50 @@ class ReCaptchaWebViewManager__Tests: XCTestCase {
waitForExpectations(timeout: 3)
}
// MARK: Setup
func test__Key_Setup() {
let exp = expectation(description: "setup key")
var result: ReCaptchaWebViewManager.Response?
// Validate
let manager = ReCaptchaWebViewManager(messageBody: "{token: key}", apiKey: apiKey)
manager.configureWebView { _ in
XCTFail("should not ask to configure the webview")
}
manager.validate(on: presenterView) { response in
result = response
exp.fulfill()
}
waitForExpectations(timeout: 3)
XCTAssertNotNil(result)
XCTAssertNil(result?.error)
XCTAssertEqual(result?.value, apiKey)
}
func test__Endpoint_Setup() {
let exp = expectation(description: "setup endpoint")
let endpoint = String(describing: arc4random())
var result: ReCaptchaWebViewManager.Response?
let manager = ReCaptchaWebViewManager(messageBody: "{token: endpoint}", endpoint: endpoint)
manager.configureWebView { _ in
XCTFail("should not ask to configure the webview")
}
manager.validate(on: presenterView) { response in
result = response
exp.fulfill()
}
waitForExpectations(timeout: 3)
XCTAssertNotNil(result)
XCTAssertNil(result?.error)
XCTAssertEqual(result?.value, endpoint)
}
}

View File

@ -12,12 +12,18 @@ import Foundation
extension ReCaptchaWebViewManager {
convenience init(messageBody: String, apiKey: String? = nil) {
convenience init(messageBody: String, apiKey: String? = nil, endpoint: String? = nil) {
let localhost = URL(string: "http://localhost")!
let html = Bundle(for: ReCaptchaWebViewManager__Tests.self)
.path(forResource: "mock", ofType: "html")
.flatMap { try? String(contentsOfFile: $0) }
.map { String(format: $0, "%@", messageBody) }
.map { String(format: $0, arguments: ["message": messageBody]) }
self.init(html: html!, apiKey: apiKey ?? String(arc4random()), baseURL: URL(string: "http://localhost")!)
self.init(
html: html!,
apiKey: apiKey ?? String(arc4random()),
baseURL: localhost,
endpoint: endpoint ?? localhost.absoluteString
)
}
}

View File

@ -2,10 +2,11 @@
<head>
<meta name="viewport" content="width=device-width" />
<script type="text/javascript">
var key = "%@";
var key = "${apiKey}";
var execute = function() {
window.webkit.messageHandlers.recaptcha.postMessage(%@);
window.webkit.messageHandlers.recaptcha.postMessage(${message});
}
var endpoint = "${endpoint}";
</script>
</head>
<body>

View File

@ -63,6 +63,19 @@ recaptcha.rx.validate(on: view)
})
```
#### Alternte endpoint
If your app has firewall limitations that may be blocking Google's API, the JS endpoint may be changed on initialization.
It'll then point to `https://www.recaptcha.net/recaptcha/api.js`:
``` swift
public enum Endpoint {
case default, alternate
}
let recaptcha = try? ReCaptcha(endpoint: .alternate) // Defaults to `default` when unset
```
## License
ReCaptcha is available under the MIT license. See the LICENSE file for more info.

View File

@ -26,7 +26,7 @@
var onloadCallback = function() {
grecaptcha.render('submit', {
'sitekey' : '%@',
'sitekey' : '${apiKey}',
'callback' : onSubmit,
'size': 'invisible'
});
@ -35,6 +35,6 @@
</head>
<body>
<span id="submit" style="visibility: hidden;"></span>
<script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit" async defer></script>
<script src="${endpoint}" async defer></script>
</body>
</html>

View File

@ -1,6 +1,6 @@
//
// NSError+ReCaptcha.swift
// Pods
// ReCaptcha
//
// Created by Flávio Caetano on 22/03/17.
//

View File

@ -1,6 +1,6 @@
//
// ReCaptcha.swift
// Pods
// ReCaptcha
//
// Created by Flávio Caetano on 22/03/17.
//
@ -20,6 +20,22 @@ open class ReCaptcha: ReCaptchaWebViewManager {
}
}
/** The JS API endpoint to be loaded onto the HTML file.
- default: Google's default endpoint. Points to https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit
- alternate: Alternate endpoint. Points to https://www.recaptcha.net/recaptcha/api.js
*/
public enum Endpoint {
case `default`, alternate
fileprivate var url: String {
switch self {
case .default: return "https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit"
case .alternate: return "https://www.recaptcha.net/recaptcha/api.js"
}
}
}
/** Internal data model for DI in unit tests
*/
struct Config {
@ -73,8 +89,9 @@ open class ReCaptcha: ReCaptchaWebViewManager {
A key may be aquired here: https://www.google.com/recaptcha/admin#list
- parameter apiKey: The API key to be provided to Google's ReCaptcha. Overrides the Info.plist entry.
- parameter baseURL: A url domain to be load onto the webview. Overrides the Info.plist entry.
- parameter apiKey: The API key to be provided to Google's ReCaptcha. Overrides the Info.plist entry. Defaults to `nil`.
- parameter baseURL: A url domain to be load onto the webview. Overrides the Info.plist entry. Defaults to `nil`.
- parameter endpoint: The JS API endpoint to be loaded onto the HTML file. Defaults to `.default`.
- Throws:
- `NSError.ReCaptchaCode.htmlLoadError` if is unable to load the HTML embedded in the bundle.
@ -82,13 +99,13 @@ open class ReCaptcha: ReCaptchaWebViewManager {
- `NSError.ReCaptchaCode.baseURLNotFound` if a `baseURL` is not provided and can't find one in the project's Info.plist.
- Rethrows any exceptions thrown by `String(contentsOfFile:)`
*/
public init(apiKey: String? = nil, baseURL: URL? = nil) throws {
public init(apiKey: String? = nil, baseURL: URL? = nil, endpoint: Endpoint = .default) throws {
let infoDict = Bundle.main.infoDictionary
let plistApiKey = infoDict?[Constants.InfoDictKeys.APIKey] as? String
let plistDomain = (infoDict?[Constants.InfoDictKeys.Domain] as? String).flatMap(URL.init(string:))
let config = try Config(apiKey: apiKey, infoPlistKey: plistApiKey, baseURL: baseURL, infoPlistURL: plistDomain)
super.init(html: config.html, apiKey: config.apiKey, baseURL: config.baseURL)
super.init(html: config.html, apiKey: config.apiKey, baseURL: config.baseURL, endpoint: endpoint.url)
}
}

View File

@ -1,6 +1,6 @@
//
// ReCaptchaDecoder.swift
// Pods
// ReCaptcha
//
// Created by Flávio Caetano on 22/03/17.
//

View File

@ -1,6 +1,6 @@
//
// ReCaptchaWebViewManager.swift
// Pods
// ReCaptcha
//
// Created by Flávio Caetano on 22/03/17.
//
@ -39,15 +39,16 @@ open class ReCaptchaWebViewManager: NSObject {
- html: The HTML string to be loaded onto the webview
- apiKey: The Google's ReCaptcha API Key
- baseURL: The URL configured with the API Key
- endpoint: The JS API endpoint to be loaded onto the HTML file.
*/
init(html: String, apiKey: String, baseURL: URL) {
init(html: String, apiKey: String, baseURL: URL, endpoint: String) {
super.init()
decoder = ReCaptchaDecoder { [weak self] result in
self?.handle(result: result)
}
let formattedHTML = String(format: html, apiKey)
let formattedHTML = String(format: html, arguments: ["apiKey": apiKey, "endpoint": endpoint])
if let window = UIApplication.shared.keyWindow {
setupWebview(on: window, html: formattedHTML, url: baseURL)

View File

@ -1,6 +1,6 @@
//
// ReCaptcha+Rx.swift
// Pods
// ReCaptcha
//
// Created by Flávio Caetano on 11/04/17.
//

View File

@ -0,0 +1,19 @@
//
// String+Dict.swift
// ReCaptcha
//
// Created by Flávio Caetano on 10/10/17.
//
//
import Foundation
extension String {
init(format: String, arguments: [String: CustomStringConvertible]) {
self.init(describing: arguments.reduce(format)
{ (format: String, args: (key: String, value: CustomStringConvertible)) -> String in
format.replacingOccurrences(of: "${\(args.key)}", with: args.value.description)
})
}
}