public string GetUrlAndQueryParams(Dictionary <string, string> query) { if (query == null) { throw new ArgumentNullException(nameof(query)); } int qpos = RawUrl.IndexOf('?'); query.Clear(); if (qpos < 0) { return(RawUrl); } else { string url = RawUrl.Substring(0, qpos); foreach (string qp in RawUrl.Substring(qpos + 1).Split('&')) { string qptrimmed = qp.Trim(); if (qptrimmed.Length == 0) { continue; } string[] vp = qptrimmed.Split('='); query[vp[0]] = vp.Length < 2 ? string.Empty : vp[1]; } return(url); } }
protected internal HttpRequest(HttpListenerRequest request) { Request = request; PathInfo = RawUrl.Split(new[] { '?' }, 2)[0]; Name = $"{HttpMethod} {PathInfo}"; Id = Guid.NewGuid().Truncate(); Advanced = new AdvancedHttpRequest(request); /*ContentEncoding = request.ContentEncoding; * if (request.ContentType == null) * { * ContentEncoding = Encoding.UTF8; * }*/ ContentEncoding = Encoding.UTF8; try { int index = request?.RawUrl?.IndexOf("?") ?? -1; if (index >= 0) { QueryString = HttpUtility.ParseQueryString(Request.RawUrl.Substring(index + 1), ContentEncoding); } } catch { QueryString = request.QueryString; } }
/// <summary> /// Process URL path string. /// </summary> /// <param name="path"></param> public Url(string path) { _path = path; ParameterCount = 0; // process url parameters string[] splitUrlQuestionMark = RawUrl.Split('?'); // url contains one ? and is not empty or null before and after ? if (splitUrlQuestionMark.Length == 2 && !String.IsNullOrEmpty(splitUrlQuestionMark[0]) && !String.IsNullOrEmpty(splitUrlQuestionMark[1])) { // split at & and remove fragments string[] splitUrlParams = splitUrlQuestionMark[1].Split("&"); splitUrlParams[splitUrlParams.GetUpperBound(0)] = splitUrlParams.Last().Split("#").First(); foreach (var param in splitUrlParams) { string[] urlParams = param.Split("="); if (urlParams.Length != 2) { break; } ParameterCount++; Parameter[urlParams[0]] = urlParams[1]; } } }
protected internal HttpRequest(Mono.Net.HttpListenerRequest request) { Request = request; PathInfo = RawUrl.Split(new[] { '?' }, 2)[0]; Name = $"{HttpMethod} {PathInfo}"; Id = Guid.NewGuid().Truncate(); Advanced = new AdvancedHttpRequest(request); }
internal void FinishInitialization() { var host = UserHostName; if (ProtocolVersion > HttpVersion.Version10 && string.IsNullOrEmpty(host)) { _context.ErrorMessage = "Invalid host name"; return; } Uri rawUri = null; var path = RawUrl.ToLowerInvariant().MaybeUri() && Uri.TryCreate(RawUrl, UriKind.Absolute, out rawUri) ? rawUri.PathAndQuery : RawUrl; if (string.IsNullOrEmpty(host)) { host = UserHostAddress; } if (rawUri != null) { host = rawUri.Host; } var colon = host.IndexOf(':'); if (colon >= 0) { host = host.Substring(0, colon); } // var baseUri = $"{(IsSecureConnection ? "https" : "http")}://{host}:{LocalEndPoint.Port}"; var baseUri = $"http://{host}:{LocalEndPoint.Port}"; if (!Uri.TryCreate(baseUri + path, UriKind.Absolute, out _url)) { _context.ErrorMessage = WebUtility.HtmlEncode("Invalid url: " + baseUri + path); return; } CreateQueryString(_url.Query); // Use reference source HttpListenerRequestUriBuilder to process url. // Fixes #29927 _url = HttpListenerRequestUriBuilder.GetRequestUri(RawUrl, _url); if (!_clSet) { if (string.Compare(HttpMethod, "POST", StringComparison.OrdinalIgnoreCase) == 0 || string.Compare(HttpMethod, "PUT", StringComparison.OrdinalIgnoreCase) == 0) { return; } } if (string.Compare(Headers["Expect"], "100-continue", StringComparison.OrdinalIgnoreCase) == 0) { _context.Connection.GetResponseStream().InternalWrite(HttpStatus100, 0, HttpStatus100.Length); } }
protected internal HttpRequest(HttpListenerRequest request) { Request = request; HttpMethod = (HttpMethod)Enum.Parse(typeof(HttpMethod), Request.HttpMethod); PathInfo = RawUrl.Split(new[] { '?' }, 2)[0]; Name = $"{HttpMethod} {PathInfo}"; Id = Guid.NewGuid().Truncate(); Advanced = new AdvancedHttpRequest(request); }
internal HttpRequest(HttpListenerRequest request) { _request = request; HttpMethod = (HttpMethod)Enum.Parse(typeof(HttpMethod), _request.HttpMethod); PathInfo = (RawUrl.Split(new[] { '?' }, 2))[0]; using (var reader = new StreamReader(_request.InputStream, _request.ContentEncoding)) { Payload = reader.ReadToEnd(); } }
private void SplitUrl() { //check for fragment first, because everything after the first # is a fragment if (RawUrl.Contains('#')) { var parts = RawUrl.Split("#", 2, StringSplitOptions.RemoveEmptyEntries); RawUrl = parts[0]; //everything before the # belongs to the url _fragment = parts[1]; //everytihng after the # belongs to the fragment } //a valid url can be split into two parts var extracted = RawUrl.Split("?", 2, StringSplitOptions.RemoveEmptyEntries); if (!string.IsNullOrEmpty(extracted[0])) { //set the path var segmentsRaw = new ArrayList(); foreach (var segment in extracted[0].Split("/", StringSplitOptions.RemoveEmptyEntries)) { segmentsRaw.Add(segment); //adds everything to the arraylist } var sb = new StringBuilder(); if (segmentsRaw.Count > 0) { foreach (string rawSegment in segmentsRaw.ToArray()) { sb.Append("/"); sb.Append(rawSegment); } } else { sb.Append("/"); //no segments means root was requested } Path = sb.ToString(); _segments = sb.ToString().Split("/", StringSplitOptions.RemoveEmptyEntries); } if (extracted.Length > 1 && !string.IsNullOrEmpty(extracted[1])) { //these should be the parameters, which are separated by "&" var keyValuePairs = extracted[1].Split("&", StringSplitOptions.RemoveEmptyEntries); foreach (var pair in keyValuePairs) { //name=flo //age=20 //the key value pairs are seperated by "=" var keyValue = pair.Split("=", 2, StringSplitOptions.RemoveEmptyEntries); //should only be 2 items Parameter.Add(keyValue[0], keyValue[1]); } } }
private string BuildPageUrl(int page) { if (page == CurrentPage) { return("javascript:void(0);"); } StringBuilder builder = new StringBuilder(RawUrl); builder.Append(RawUrl.LastIndexOf('?') >= 0 ? "&" : "?"); builder.AppendFormat("size={0}", SizePerPage); builder.AppendFormat("&page={0}", page); return(builder.ToString()); }
internal void FinishInitialization() { var host = UserHostName; if (ProtocolVersion > HttpVersion.Version10 && string.IsNullOrEmpty(host)) { _context.ErrorMessage = "Invalid host name"; return; } var rawUri = UriUtility.StringToAbsoluteUri(RawUrl.ToLowerInvariant()); var path = rawUri?.PathAndQuery ?? RawUrl; if (string.IsNullOrEmpty(host)) { host = rawUri?.Host ?? UserHostAddress; } var colon = host.LastIndexOf(':'); if (colon >= 0) { host = host.Substring(0, colon); } // var baseUri = $"{(IsSecureConnection ? "https" : "http")}://{host}:{LocalEndPoint.Port}"; var baseUri = $"http://{host}:{LocalEndPoint.Port}"; if (!Uri.TryCreate(baseUri + path, UriKind.Absolute, out _url)) { _context.ErrorMessage = WebUtility.HtmlEncode($"Invalid url: {baseUri}{path}"); return; } CreateQueryString(_url.Query); if (ContentLength64 == 0 && (HttpVerb == HttpVerb.Post || HttpVerb == HttpVerb.Put)) { return; } if (string.Compare(Headers["Expect"], "100-continue", StringComparison.OrdinalIgnoreCase) == 0) { _context.Connection.GetResponseStream().InternalWrite(HttpStatus100, 0, HttpStatus100.Length); } }
private void DoParse() { string[] lines = _rawRequestHeaders.Split(new[] { "\r\n" }, StringSplitOptions.None); string[] action = lines[0].Split(' '); HttpMethod = action[0]; RawUrl = action[1]; Protocol = action[2]; string[] path = RawUrl.Split('?'); FilePath = HttpUtility.UrlDecode(path[0]); if (path.Length == 2) { QueryString = path[1]; } Headers = new NameValueCollection(); bool isCompletedHeader = false; for (var i = 1; i < lines.Length; i++) { var line = lines[i]; if (string.IsNullOrEmpty(line)) { isCompletedHeader = true; continue; } if (isCompletedHeader) { //header后面是一个空白行,空白行后面所有内容是Body Body = string.Join("\r\n", lines.Where((l, index) => index >= i)); break; } else { int iSeparator = line.IndexOf(":"); Headers.Add(line.Substring(0, iSeparator), line.Remove(0, iSeparator + 1).TrimStart()); } } }
private void setParameters(int parameterIndex, int?fragmentIndex = null) { if (parameterIndex > -1) { var lastIndex = RawUrl.Length; if (fragmentIndex != null && fragmentIndex > 0) { lastIndex = fragmentIndex.Value; } parameterIndex++; var parameterString = RawUrl.Substring(parameterIndex, lastIndex - parameterIndex); var keyValues = parameterString.Split("&"); foreach (var keyValueString in keyValues) { var keyValue = keyValueString.Split("="); Parameter.Add(keyValue[0], keyValue[1]); } } }
private void DoParse() { string[] lines = _rawRequestHeaders.Split(new[] { "\r\n" }, StringSplitOptions.None); string[] actions = lines[0].Split(' '); HttpMethod = actions[0]; RawUrl = actions[1]; Protocol = actions[2]; string[] path = RawUrl.Split('?'); FilePath = HttpUtility.UrlDecode(path[0]); if (path.Length == 2) { QueryString = path[1]; } Headers = new NameValueCollection(); bool headerComplete = false; for (int i = 1; i < lines.Length; i++) { string line = lines[i]; if (string.IsNullOrEmpty(line)) { headerComplete = true; continue; } if (headerComplete) { EntityBody = line; } else { int separator = line.IndexOf(":"); Headers.Add(line.Substring(0, separator), line.Substring(separator + 1, line.Length - separator - 1).TrimStart()); } } }
private void ensureprameter() { if (result == null) { result = new Dictionary <string, string>(); //"/test.jpg?x=1&y=2" if (RawUrl != null) { if (RawUrl.Contains('?')) { int index = RawUrl.IndexOf('?'); string sub = RawUrl.Substring(index + 1); string[] prams = sub.Split('&'); for (int i = 0; i < prams.Length; i++) { string[] pairs = prams[i].Split('='); result.Add(pairs[0], pairs[1]); } } } } }
private void DoParse() { string[] lines = _rawRequestHeaders.Split(new[] { "\r\n" }, StringSplitOptions.None); string[] actions = lines[0].Split(' '); HttpMethod = actions[0]; RawUrl = actions[1]; Protocol = actions[2]; string[] path = RawUrl.Split('?'); if (path[0].IndexOf('.') == -1 && !path[0].EndsWith("/", StringComparison.Ordinal)) { FilePath = HttpUtility.UrlDecode(path[0] + "/"); } else { FilePath = HttpUtility.UrlDecode(path[0]); } if (path.Length == 2) { QueryString = path[1]; } Headers = new Dictionary <string, string>(); for (int i = 1; i < lines.Length; i++) { string line = lines[i]; if (string.IsNullOrEmpty(line)) { break; } int separator = line.IndexOf(":"); Headers.Add(line.Substring(0, separator), line.Substring(separator + 1).TrimStart()); } KeepAlive = Headers["Connection"] == null ? false : Headers["Connection"] == "keep-alive"; GZip = Headers["Accept-Encoding"] == null ? false : (Headers["Accept-Encoding"].IndexOf("gzip") != -1); }
public string GetUrlAndQueryParams(List <KeyValuePair <string, string> > query) { if (query == null) { throw new ArgumentNullException(nameof(query)); } int qpos = RawUrl.IndexOf('?'); query.Clear(); if (qpos < 0) { return(RawUrl); } else { string url = RawUrl.Substring(0, qpos); foreach (string qp in RawUrl.Substring(qpos + 1).Split('&')) { string qptrimmed = qp.Trim(); if (qptrimmed.Length == 0) { continue; } string[] vp = qptrimmed.Split('='); if (vp.Length < 2) { query.Add(new KeyValuePair <string, string>(vp[0], string.Empty)); } else { query.Add(new KeyValuePair <string, string>(vp[0], vp[1])); } } return(url); } }
public RushContext(HttpContext context) { this.HttpContext = context; HttpVerb verb = HttpVerb.Unsupported; Enum.TryParse(context.Request.RequestType, true, out verb); this.Verb = verb; this.RawUrl = context.Request.AppRelativeCurrentExecutionFilePath.Replace("~/", ""); string[] segments = RawUrl.Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries); if (segments.Length == 3) { this.Controller = segments[1] + "Controller"; this.Resource = segments[2]; } if (segments.Length == 4) { this.Controller = segments[1] + "Controller"; this.Resource = segments[2]; this.Id = segments[3]; } this.Headers = new Dictionary <string, string>(); foreach (var key in context.Request.Headers.AllKeys) { this.Headers[key] = context.Request.Headers[key]; } this.QueryString = new Dictionary <string, string>(); foreach (var key in context.Request.QueryString.AllKeys) { this.QueryString[key] = context.Request.QueryString[key]; } }
internal void FinishInitialization() { var host = UserHostName; if (ProtocolVersion > HttpVersion.Version10 && string.IsNullOrEmpty(host)) { _context.ErrorMessage = "Invalid host name"; return; } string path; Uri rawUri = null; if (MaybeUri(RawUrl.ToLowerInvariant()) && Uri.TryCreate(RawUrl, UriKind.Absolute, out rawUri)) { path = rawUri.PathAndQuery; } else { path = RawUrl; } if (string.IsNullOrEmpty(host)) { host = UserHostAddress; } if (rawUri != null) { host = rawUri.Host; } var colon = host.IndexOf(':'); if (colon >= 0) { host = host.Substring(0, colon); } var baseUri = $"{((IsSecureConnection) ? "https" : "http")}://{host}:{LocalEndPoint.Port}"; if (!Uri.TryCreate(baseUri + path, UriKind.Absolute, out _url)) { _context.ErrorMessage = WebUtility.HtmlEncode("Invalid url: " + baseUri + path); return; } CreateQueryString(_url.Query); // Use reference source HttpListenerRequestUriBuilder to process url. // Fixes #29927 _url = HttpListenerRequestUriBuilder.GetRequestUri(RawUrl, _url.Scheme, _url.Authority, _url.LocalPath, _url.Query); #if CHUNKED if (ProtocolVersion >= HttpVersion.Version11) { var tEncoding = Headers["Transfer-Encoding"]; _isChunked = (tEncoding != null && string.Compare(tEncoding, "chunked", StringComparison.OrdinalIgnoreCase) == 0); // 'identity' is not valid! if (tEncoding != null && !_isChunked) { return; } } #endif if (!_isChunked && !_clSet) { if (string.Compare(HttpMethod, "POST", StringComparison.OrdinalIgnoreCase) == 0 || string.Compare(HttpMethod, "PUT", StringComparison.OrdinalIgnoreCase) == 0) { return; } } if (string.Compare(Headers["Expect"], "100-continue", StringComparison.OrdinalIgnoreCase) == 0) { var output = _context.Connection.GetResponseStream(); output.InternalWrite(_100Continue, 0, _100Continue.Length); } }
/// <summary> /// 构建http请求对象 /// </summary> /// <param name="stream"></param> /// <param name="size"></param> internal HttpRequest(Stream stream, int size) { handler = stream; bytes = new byte[size]; var data = GetRequestData(handler); var rows = Regex.Split(data, Environment.NewLine); //Request URL & Method & Version var first = Regex.Split(rows[0], @"(\s+)") .Where(e => e.Trim() != string.Empty) .ToArray(); if (first.Length > 0) { switch (first[0]) { case "GET": Method = HttpMethodType.GET; break; case "POST": Method = HttpMethodType.POST; break; case "PUT": Method = HttpMethodType.PUT; break; case "DELETE": Method = HttpMethodType.DELETE; break; case "HEAD": Method = HttpMethodType.HEAD; break; case "CONNECT": Method = HttpMethodType.CONNECT; break; case "OPTIONS": Method = HttpMethodType.OPTIONS; break; case "TRACE": Method = HttpMethodType.TRACE; break; default: Method = HttpMethodType.UNKNOWN; break; } } if (first.Length > 1) { RawUrl = Uri.UnescapeDataString(first[1]); } if (first.Length > 2) { ProtocolVersion = first[2]; } // 判定是不是安全连接 IsSSL = ProtocolVersion.ToLower().IndexOf("https") != -1; //Request Headers headers = GetRequestHeaders(rows); //Request Body Body = GetRequestBody(rows); var contentLength = GetHeader(RequestHeaders.ContentLength); if (int.TryParse(contentLength, out var length) && Body.Length != length) { do { length = stream.Read(bytes, 0, bytes.Length); Body += Encoding.UTF8.GetString(bytes, 0, length); } while (Body.Length != length); } // 获取get数据 if (RawUrl.Contains('?')) { GetValue = RawUrl.Split('?')[1]; GetParams = GetRequestParameters(GetValue); } else { GetParams = new Dictionary <string, string>(); } // 获取消息体数据 if (!string.IsNullOrEmpty(Body)) { PostValue = Body; PostParams = GetRequestParameters(PostValue); } else { PostParams = new Dictionary <string, string>(); } }
public override int GetHashCode() { unchecked { return((Size != null ? Size.GetHashCode() : 0) ^ (Filename != null ? Filename.GetHashCode() : 0) ^ (RawUrl != null ? RawUrl.GetHashCode() : 0) ^ (Content != null ? Content.GetHashCode() : 0) ^ (Type != null ? Type.GetHashCode() : 0) ^ (Language != null ? Language.GetHashCode() : 0)); } }
public HTTPHeader(String myHeader) : this() { PlainHeader = myHeader; HttpStatusCode = HTTPStatusCodes.OK; KeepAlive = false; String[] ProtocolArray; // Split the Request into lines String[] RequestParts = myHeader.Split(new string[] { Environment.NewLine }, StringSplitOptions.None); if (RequestParts.Length == 0) { HttpStatusCode = HTTPStatusCodes.BadRequest; return; } #region Header first line // The first line containing the information about the HTTPMethod, the current folder/myPath (destination) and the protocol // e.g: PROPFIND /file/file Name HTTP/1.1 String[] HTTPMethodHeader = RequestParts[0].Split(new char[] { ' ' }); if (HTTPMethodHeader.Length < 3) { HttpStatusCode = HTTPStatusCodes.BadRequest; return; } // This is a response if (HTTPMethodHeader[0].StartsWith("HTTP")) { Protocol = HTTPMethodHeader[0]; ProtocolArray = Protocol.Split(_SlashSeperator); ProtocolName = ProtocolArray[0].ToLower(); ProtocolVersion = new Version(ProtocolArray[1]); HttpStatusCode = (HTTPStatusCodes)Enum.Parse(typeof(HTTPStatusCodes), HTTPMethodHeader[1]); } // This is a request else { if (!Enum.IsDefined(typeof(HTTPMethods), HTTPMethodHeader[0])) { //HttpStatusCode = HTTPStatusCodes.NotImplemented; HttpMethod = HTTPMethods.UNKNOWN; HttpMethodString = HTTPMethodHeader[0]; //return; //throw new Exception("Invalid HTTP Method " + HTTPMethodHeader[0]); } else { HttpMethod = (HTTPMethods)Enum.Parse(typeof(HTTPMethods), HTTPMethodHeader[0]); HttpMethodString = HTTPMethodHeader[0]; } // Decode UTF-8 Hex encoding "%C3%B6" -> "ö" etc... Destination = RawUrl = HTTPMethodHeader[1];// HttpUtility.UrlDecode(HTTPMethodHeader[1]); //if (Destination.Length > 1 && Destination.EndsWith("/") && !Destination.Contains("/?")) //{ // RawUrl = HttpUtility.UrlDecode(HTTPMethodHeader[1]);//.TrimEnd(((String)"/").ToCharArray()); // if (RawUrl[RawUrl.Length-1] == '/') // { // RawUrl = RawUrl.Substring(0, RawUrl.Length - 1); // } // Destination = RawUrl; //} // Parse QueryString after '?' and maybe fix the Destination var _Questionmark = RawUrl.IndexOf('?'); if (_Questionmark > -1) { Destination = RawUrl.Substring(0, _Questionmark); QueryString = HttpUtility.ParseQueryString(RawUrl.Substring(_Questionmark + 1)); } //!svn/vcc/default var _Exclamationmark = RawUrl.IndexOf('!'); if (_Exclamationmark > -1) { SVNParameters = RawUrl.Substring(_Exclamationmark + 1); Destination = RawUrl.Substring(0, _Exclamationmark - 1); if (Destination == "") { Destination = "/"; } } Protocol = HTTPMethodHeader[2]; ProtocolArray = Protocol.Split(_SlashSeperator); ProtocolName = ProtocolArray[0].ToLower(); ProtocolVersion = new Version(ProtocolArray[1]); RawUrl = HTTPMethodHeader[1]; } #endregion if (ProtocolVersion >= new Version(1, 1)) { KeepAlive = true; } #region Parse all other Header informations Headers = new NameValueCollection(); AcceptTypes = new List <AcceptType>(); for (Int16 i = 1; i < RequestParts.Length; i++) { // The Header is finished if (RequestParts[i] == String.Empty) { break; } // Should never happen, however if (!RequestParts[i].Contains(':')) { continue; } String Key = RequestParts[i].Substring(0, RequestParts[i].IndexOf(':')); String Value = RequestParts[i].Substring(Key.Length + 1).Trim(); if (Key.ToLower() == "accept") { if (Value.Contains(",")) { UInt32 place = 0; foreach (var acc in Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) { AcceptTypes.Add(new AcceptType(acc.Trim(), place++)); } } else { AcceptTypes.Add(new AcceptType(Value.Trim())); } } else if (Key.ToLower() == "content-length") { UInt64.TryParse(Value, out _ContentLength); } else if (Key.ToLower() == "content-type") { ContentType = new System.Net.Mime.ContentType(Value); } else if (Key.ToLower() == "host") { HostName = Value; } else if (Key.ToLower() == "accept-encoding") { AcceptEncoding = Value; } /* * try * { * ContentEncoding = Encoding.GetEncoding(Value); * } * catch * { * ContentEncoding = Encoding.UTF8; * } * */ else if (Key.ToLower() == "user-agent") { if (Value.Contains("Microsoft-WebDAV-MiniRedir")) { ClientType = ClientTypes.MicrosoftWebDAVMiniRedir; } else if (Value.Contains("MSIE 7")) { ClientType = ClientTypes.MSInternetExplorer7; } else if (Value.Contains("MSIE 8")) { ClientType = ClientTypes.MSInternetExplorer8; } else if (Value.Contains("Firefox")) { ClientType = ClientTypes.Firefox; } else if (Value.ToLower().Contains("svn")) { ClientType = ClientTypes.SVN; } else { ClientType = ClientTypes.Other; } } else if (Key.ToLower() == "connection" && Value.ToLower().Contains("keep-alive")) { KeepAlive = true; } else if (Key.ToLower() == "authorization") { try { Authorization = new HTTPCredentials(Value); } catch (Exception) { //NLOG: temporarily commented //_Logger.ErrorException("could not parse authorization of HTTPHeader", ex); } } else { Headers.Add(Key, Value); } } AcceptTypes.Sort(); //AcceptTypes.Sort(new Comparison<AcceptType>((at1, at2) => //{ // if (at1.Quality > at2.Quality) return 1; // else if (at1.Quality == at2.Quality) return 0; // else return -1; // //if (at2.Quality > at1.Quality) return -1; // //else return 1; // //return at1.Quality.CompareTo(at2.Quality); //} // )); #endregion }
public override int GetHashCode() { unchecked { return((Filename != null ? Filename.GetHashCode() : 0) ^ (Additions != null ? Additions.GetHashCode() : 0) ^ (Deletions != null ? Deletions.GetHashCode() : 0) ^ (Changes != null ? Changes.GetHashCode() : 0) ^ (Status != null ? Status.GetHashCode() : 0) ^ (RawUrl != null ? RawUrl.GetHashCode() : 0) ^ (BlobUrl != null ? BlobUrl.GetHashCode() : 0) ^ (Patch != null ? Patch.GetHashCode() : 0) ^ (ContentsUrl != null ? ContentsUrl.GetHashCode() : 0)); } }