static void Redirect (HttpWorkerRequest wr, string location) { string host = wr.GetKnownRequestHeader (HttpWorkerRequest.HeaderHost); wr.SendStatus (301, "Moved Permanently"); wr.SendUnknownResponseHeader ("Connection", "close"); wr.SendUnknownResponseHeader ("Date", DateTime.Now.ToUniversalTime ().ToString ("r")); wr.SendUnknownResponseHeader ("Location", String.Format ("{0}://{1}{2}", wr.GetProtocol(), host, location)); Encoding enc = Encoding.ASCII; wr.SendUnknownResponseHeader ("Content-Type", "text/html; charset=" + enc.WebName); string content = String.Format (CONTENT301, host, location); byte [] contentBytes = enc.GetBytes (content); wr.SendUnknownResponseHeader ("Content-Length", contentBytes.Length.ToString ()); wr.SendResponseFromMemory (contentBytes, contentBytes.Length); wr.FlushResponse (true); wr.CloseConnection (); }
// Determines whether or not a given HttpWorkerRequest meets the requirements for "same-origin" // as called out in these two documents: // - http://tools.ietf.org/html/rfc6454 (Web Origin) // - http://tools.ietf.org/html/rfc6455 (WebSockets) public static bool IsSameOriginRequest(HttpWorkerRequest workerRequest) { string hostHeader = workerRequest.GetKnownRequestHeader(HttpWorkerRequest.HeaderHost); if (String.IsNullOrEmpty(hostHeader)) { // RFC 6455 (Sec. 4.1) and RFC 2616 (Sec. 14.23) make the "Host" header mandatory return false; } string secWebSocketOriginHeader = workerRequest.GetUnknownRequestHeader("Origin"); if (String.IsNullOrEmpty(secWebSocketOriginHeader)) { // RFC 6455 (Sec. 4.1) makes the "Origin" header mandatory for browser clients. // Phone apps, console clients, and similar non-browser clients aren't required to send the header, // but this method isn't intended for those use cases anyway, so we can fail them. (Note: it's still // possible for a non-browser app to send the appropriate Origin header.) return false; } // create URI instances from both the "Host" and the "Origin" headers Uri hostHeaderUri = null; Uri originHeaderUri = null; bool urisCreatedSuccessfully = Uri.TryCreate(workerRequest.GetProtocol() + "://" + hostHeader.Trim(), UriKind.Absolute, out hostHeaderUri) // RFC 2616 (Sec. 14.23): "Host" header doesn't contain the scheme, so we need to prepend && Uri.TryCreate(secWebSocketOriginHeader.Trim(), UriKind.Absolute, out originHeaderUri); if (!urisCreatedSuccessfully) { // construction of one of the Uri instances failed return false; } // RFC 6454 (Sec. 4), schemes must be normalized to lowercase. (And for WebSockets we only // support HTTP / HTTPS anyway.) if (originHeaderUri.Scheme != "http" && originHeaderUri.Scheme != "https") { return false; } // RFC 6454 (Sec. 5), comparisons should be ordinal. The Uri class will automatically // fill in the Port property using the default value for the scheme if the provided input doesn't // explicitly contain a port number. return hostHeaderUri.Scheme == originHeaderUri.Scheme && hostHeaderUri.Host == originHeaderUri.Host && hostHeaderUri.Port == originHeaderUri.Port; }