// 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;
        }
        public static Encoding GetEncodingFromHeaders(HttpWorkerRequest workerRequest)
        {
            if (workerRequest == null)
                throw new ArgumentNullException("workerRequest");

            string userAgent = workerRequest.GetKnownRequestHeader(HttpWorkerRequest.HeaderUserAgent);
            if (userAgent != null && CultureInfo.InvariantCulture.CompareInfo.IsPrefix(userAgent, "UP"))
            {
                string text = workerRequest.GetUnknownRequestHeader("x-up-devcap-post-charset");
                if (!string.IsNullOrEmpty(text))
                {
                    try
                    {
                        return Encoding.GetEncoding(text);
                    }
                    catch
                    {
                    }
                }
            }
            if (!workerRequest.HasEntityBody())
            {
                return null;
            }
            string contentType = workerRequest.GetKnownRequestHeader(HttpWorkerRequest.HeaderContentType);
            if (contentType == null)
            {
                return null;
            }
            string attributeFromHeader = GetAttributeFromHeader(contentType, "charset");
            if (attributeFromHeader == null)
            {
                return null;
            }
            Encoding result = null;
            try
            {
                result = Encoding.GetEncoding(attributeFromHeader);
            }
            catch
            {
            }
            return result;
        }
        internal UploadHttpRequest(HttpContext context)
        {
            _request = context.Request;
            _worker = GetWorkerRequest(context);

            // TODO: should we silently ignore?
            if (_worker == null)
                throw new HttpException("Could not intercept worker.");

            string fileSizeHeader = _worker.GetUnknownRequestHeader("X-File-Size");

            if (string.IsNullOrEmpty(fileSizeHeader) || !long.TryParse(fileSizeHeader, out _contentLength))
                _contentLength = long.Parse(_worker.GetKnownRequestHeader(HttpWorkerRequest.HeaderContentLength));
        }