예제 #1
0
        public static HandshakeResponse Parse(string [] headerParts)
        {
            var statusLine = headerParts [0].Split (new char [] { ' ' }, 3);
              if (statusLine.Length != 3)
            throw new ArgumentException ("Invalid status line: " + headerParts [0]);

              var headers = new WebHeaderCollection ();
              for (int i = 1; i < headerParts.Length; i++)
            headers.SetInternally (headerParts [i], true);

              return new HandshakeResponse {
            Headers = headers,
            ProtocolVersion = new Version (statusLine [0].Substring (5)),
            Reason = statusLine [2],
            StatusCode = statusLine [1]
              };
        }
예제 #2
0
        internal void SendHeaders(bool closing, MemoryStream stream)
        {
            if (_contentType != null)
            {
                var contentType = _contentEncoding != null &&
                                  _contentType.IndexOf("charset=", StringComparison.Ordinal) == -1
                          ? _contentType + "; charset=" + _contentEncoding.WebName
                          : _contentType;

                _headers.SetInternally("Content-Type", contentType, true);
            }

            if (_headers ["Server"] == null)
            {
                _headers.SetInternally("Server", "websocket-sharp/1.0", true);
            }

            var provider = CultureInfo.InvariantCulture;

            if (_headers ["Date"] == null)
            {
                _headers.SetInternally("Date", DateTime.UtcNow.ToString("r", provider), true);
            }

            if (!_chunked)
            {
                if (!_contentLengthSet && closing)
                {
                    _contentLengthSet = true;
                    _contentLength    = 0;
                }

                if (_contentLengthSet)
                {
                    _headers.SetInternally("Content-Length", _contentLength.ToString(provider), true);
                }
            }

            var version = _context.Request.ProtocolVersion;

            if (!_contentLengthSet && !_chunked && version >= HttpVersion.Version11)
            {
                _chunked = true;
            }

            /* Apache forces closing the connection for these status codes:
             * - HttpStatusCode.BadRequest            400
             * - HttpStatusCode.RequestTimeout        408
             * - HttpStatusCode.LengthRequired        411
             * - HttpStatusCode.RequestEntityTooLarge 413
             * - HttpStatusCode.RequestUriTooLong     414
             * - HttpStatusCode.InternalServerError   500
             * - HttpStatusCode.ServiceUnavailable    503
             */
            var connClose = _statusCode == 400 ||
                            _statusCode == 408 ||
                            _statusCode == 411 ||
                            _statusCode == 413 ||
                            _statusCode == 414 ||
                            _statusCode == 500 ||
                            _statusCode == 503;

            if (!connClose)
            {
                connClose = !_context.Request.KeepAlive;
            }

            // They sent both KeepAlive: true and Connection: close!?
            if (!_keepAlive || connClose)
            {
                _headers.SetInternally("Connection", "close", true);
                connClose = true;
            }

            if (_chunked)
            {
                _headers.SetInternally("Transfer-Encoding", "chunked", true);
            }

            int reuses = _context.Connection.Reuses;

            if (reuses >= 100)
            {
                _forceCloseChunked = true;
                if (!connClose)
                {
                    _headers.SetInternally("Connection", "close", true);
                    connClose = true;
                }
            }

            if (!connClose)
            {
                _headers.SetInternally(
                    "Keep-Alive", String.Format("timeout=15,max={0}", 100 - reuses), true);

                if (_context.Request.ProtocolVersion <= HttpVersion.Version10)
                {
                    _headers.SetInternally("Connection", "keep-alive", true);
                }
            }

            if (_location != null)
            {
                _headers.SetInternally("Location", _location, true);
            }

            if (_cookies != null)
            {
                foreach (Cookie cookie in _cookies)
                {
                    _headers.SetInternally("Set-Cookie", cookie.ToResponseString(), true);
                }
            }

            var encoding = _contentEncoding ?? Encoding.Default;
            var writer   = new StreamWriter(stream, encoding, 256);

            writer.Write("HTTP/{0} {1} {2}\r\n", _version, _statusCode, _statusDescription);

            var headers = _headers.ToStringMultiValue(true);

            writer.Write(headers);
            writer.Flush();

            var preamble = encoding.CodePage == 65001 ? 3 : encoding.GetPreamble().Length;

            if (_outputStream == null)
            {
                _outputStream = _context.Connection.GetResponseStream();
            }

            // Assumes that the stream was at position 0.
            stream.Position = preamble;
            _headersSent    = true;
        }
예제 #3
0
        internal void AddHeader(string header)
        {
            var colon = header.IndexOf(':');

            if (colon == -1)
            {
                _context.ErrorMessage = "Invalid header";
                return;
            }

            var name = header.Substring(0, colon).Trim();
            var val  = header.Substring(colon + 1).Trim();

            _headers.SetInternally(name, val, false);

            var lower = name.ToLower(CultureInfo.InvariantCulture);

            if (lower == "accept")
            {
                _acceptTypes = new List <string> (val.SplitHeaderValue(',')).ToArray();
                return;
            }

            if (lower == "accept-language")
            {
                _userLanguages = val.Split(',');
                return;
            }

            if (lower == "content-length")
            {
                long length;
                if (Int64.TryParse(val, out length) && length >= 0)
                {
                    _contentLength       = length;
                    _contentLengthWasSet = true;
                }
                else
                {
                    _context.ErrorMessage = "Invalid Content-Length header";
                }

                return;
            }

            if (lower == "content-type")
            {
                var contents = val.Split(';');
                foreach (var content in contents)
                {
                    var tmp = content.Trim();
                    if (tmp.StartsWith("charset"))
                    {
                        var charset = tmp.GetValue("=");
                        if (charset != null && charset.Length > 0)
                        {
                            try {
                                _contentEncoding = Encoding.GetEncoding(charset);
                            }
                            catch {
                                _context.ErrorMessage = "Invalid Content-Type header";
                            }
                        }

                        break;
                    }
                }

                return;
            }

            if (lower == "referer")
            {
                _referer = val.ToUri();
            }
        }
예제 #4
0
        public static HandshakeRequest Parse(string [] headerParts)
        {
            var requestLine = headerParts [0].Split (new [] { ' ' }, 3);
              if (requestLine.Length != 3)
            throw new ArgumentException ("Invalid request line: " + headerParts [0]);

              var headers = new WebHeaderCollection ();
              for (int i = 1; i < headerParts.Length; i++)
            headers.SetInternally (headerParts [i], false);

              return new HandshakeRequest {
            Headers = headers,
            HttpMethod = requestLine [0],
            ProtocolVersion = new Version (requestLine [2].Substring (5)),
            RequestUri = requestLine [1]
              };
        }
예제 #5
0
    internal static HandshakeResponse Parse (string[] headerParts)
    {
      var statusLine = headerParts[0].Split (new[] { ' ' }, 3);
      if (statusLine.Length != 3)
        throw new ArgumentException ("Invalid status line: " + headerParts[0]);

      var headers = new WebHeaderCollection ();
      for (int i = 1; i < headerParts.Length; i++)
        headers.SetInternally (headerParts[i], true);

      var res = new HandshakeResponse (new Version (statusLine[0].Substring (5)), headers);
      res._code = statusLine[1];
      res._reason = statusLine[2];

      return res;
    }
예제 #6
0
    internal static HttpRequest Parse (string[] headerParts)
    {
      var requestLine = headerParts[0].Split (new[] { ' ' }, 3);
      if (requestLine.Length != 3)
        throw new ArgumentException ("Invalid request line: " + headerParts[0]);

      var headers = new WebHeaderCollection ();
      for (int i = 1; i < headerParts.Length; i++)
        headers.SetInternally (headerParts[i], false);

      return new HttpRequest (
        requestLine[0], requestLine[1], new Version (requestLine[2].Substring (5)), headers);
    }
        internal void AddHeader(string header)
        {
            var colon = header.IndexOf(':');

            if (colon == -1)
            {
                _context.ErrorMessage = "Invalid header";
                return;
            }

            var name = header.Substring(0, colon).Trim();
            var val  = header.Substring(colon + 1).Trim();

            _headers.SetInternally(name, val, false);

            var lower = name.ToLower(CultureInfo.InvariantCulture);

            if (lower == "accept")
            {
                _acceptTypes = new List <string> (val.SplitHeaderValue(',')).ToArray();
                return;
            }

            if (lower == "accept-language")
            {
                _userLanguages = val.Split(',');
                return;
            }

            if (lower == "content-length")
            {
                long len;
                if (Int64.TryParse(val, out len) && len >= 0)
                {
                    _contentLength       = len;
                    _contentLengthWasSet = true;
                }
                else
                {
                    _context.ErrorMessage = "Invalid Content-Length header";
                }

                return;
            }

            if (lower == "content-type")
            {
                try {
                    _contentEncoding = HttpUtility.GetEncoding(val);
                }
                catch {
                    _context.ErrorMessage = "Invalid Content-Type header";
                }

                return;
            }

            if (lower == "referer")
            {
                _referer = val.ToUri();
            }
        }