-
-
Save vitalymak/06744e66e74eda106a98b1162dabf476 to your computer and use it in GitHub Desktop.
GCDWebServer Cors proxy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import GCDWebServer | |
let webserver = GCDWebServer() | |
let proxy = CorsProxy(webserver: webserver!, urlPrefix: "/CORS/") | |
webserver.startWithPort(8080, bonjourName: nil) | |
// $ curl -i -H "Origin: test-site" http://127.0.0.1/CORS/http://my/test/site | |
// HTTP/1.1 200 OK | |
// Access-Control-Allow-Origin: test-site | |
// Server: GCDWebServer | |
// Access-Control-Allow-Credentials: true | |
// Connection: Close | |
// Access-Control-Allow-Methods: PUT,POST,GET,PATCH,DELETE | |
// Cache-Control: no-cache |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import GCDWebServer | |
class CorsProxy { | |
init(webserver : GCDWebServer!, urlPrefix: String) { | |
var prefix = | |
(urlPrefix.hasPrefix("/") ? "" : "/") | |
+ urlPrefix | |
+ (urlPrefix.hasSuffix("/") ? "" : "/") | |
let pattern = "^" + NSRegularExpression.escapedPatternForString(prefix) + ".*" | |
webserver.addHandlerForMethod("POST", pathRegex: pattern, requestClass: GCDWebServerDataRequest.self, processBlock:{ req in | |
return self.sendProxyResult(prefix, req: req) | |
}) | |
webserver.addHandlerForMethod("PUT", pathRegex: pattern, requestClass: GCDWebServerDataRequest.self, processBlock:{ req in | |
return self.sendProxyResult(prefix, req: req) | |
}) | |
webserver.addHandlerForMethod("PATCH", pathRegex: pattern, requestClass: GCDWebServerDataRequest.self, processBlock:{ req in | |
return self.sendProxyResult(prefix, req: req) | |
}) | |
webserver.addHandlerForMethod("DELETE", pathRegex: pattern, requestClass: GCDWebServerDataRequest.self, processBlock:{ req in | |
return self.sendProxyResult(prefix, req: req) | |
}) | |
webserver.addHandlerForMethod("GET", pathRegex: pattern, requestClass: GCDWebServerRequest.self, processBlock:{ req in | |
return self.sendProxyResult(prefix, req: req) | |
}) | |
webserver.addHandlerForMethod("OPTIONS", pathRegex: pattern, requestClass: GCDWebServerRequest.self, processBlock:{ req in | |
return self.sendCorsHeaders(prefix, req: req) | |
}) | |
} | |
func sendProxyResult(prefix: String, req: GCDWebServerRequest) -> GCDWebServerResponse! { | |
let query = req.URL.query == nil ? "" : "?" + req.URL.query! | |
var url = NSURL(string: req.path.substringFromIndex(prefix.endIndex) + query) | |
if (url == nil) { return sendError("Invalid URL") } | |
var err: NSErrorPointer = nil | |
var urlResp: NSURLResponse? | |
let urlReq = NSMutableURLRequest(URL: url!, cachePolicy: NSURLRequestCachePolicy.ReloadIgnoringLocalCacheData, timeoutInterval: 320000) | |
urlReq.HTTPMethod = req.method | |
urlReq.allHTTPHeaderFields = req.headers | |
urlReq.allHTTPHeaderFields?["Host"] = url!.host | |
if (req.hasBody()) { | |
urlReq.HTTPBody = (req as! GCDWebServerDataRequest).data | |
} | |
let output = NSURLConnection.sendSynchronousRequest(urlReq | |
, returningResponse: &urlResp | |
, error: err) | |
if (urlResp == nil) { | |
return sendError(output == nil ? nil : NSString(data: output!, encoding: NSUTF8StringEncoding) as? String); | |
} | |
var httpResponse = urlResp as! NSHTTPURLResponse | |
let resp = GCDWebServerDataResponse(data: output == nil ? NSData() : output, contentType: "application/x-unknown") | |
resp.statusCode = httpResponse.statusCode | |
for key in httpResponse.allHeaderFields { | |
if (toString(key.0) == "Content-Encoding") { continue; } | |
resp.setValue(toString(key.1), forAdditionalHeader: toString(key.0)) | |
} | |
if (output != nil) { | |
resp.setValue(String(output!.length), forAdditionalHeader: "Content-Length") | |
} | |
return resp | |
} | |
func sendCorsHeaders(prefix: String, req: GCDWebServerRequest) -> GCDWebServerResponse! { | |
let resp = GCDWebServerResponse() | |
resp.setValue(toString(req.headers["Origin"]), forAdditionalHeader: "Access-Control-Allow-Origin") | |
resp.setValue("PUT,POST,GET,PATCH,DELETE", forAdditionalHeader: "Access-Control-Allow-Methods") | |
resp.setValue("true", forAdditionalHeader: "Access-Control-Allow-Credentials") | |
return resp | |
} | |
func sendError(error: String?) -> GCDWebServerResponse! { | |
var msg = error == nil ? "An error occured" : error! | |
let errorData = msg.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true) | |
let resp = GCDWebServerDataResponse(data: errorData, contentType: "text/plain") | |
resp.statusCode = 500 | |
return resp | |
} | |
func toString(v: AnyObject?) -> String! { | |
if (v == nil) { return ""; } | |
return String(stringInterpolationSegment: v!) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment