| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | using System; |
| | using System.Collections.Generic; |
| | using System.Linq; |
| | using System.Net.Http; |
| | using System.Text; |
| | using System.Text.RegularExpressions; |
| |
|
| | using Google.Apis.Http; |
| | using Google.Apis.Logging; |
| | using Google.Apis.Util; |
| |
|
| | namespace Google.Apis.Requests |
| | { |
| | |
| | |
| | public class RequestBuilder |
| | { |
| | static RequestBuilder() |
| | { |
| | UriPatcher.PatchUriQuirks(); |
| | } |
| |
|
| | private static readonly ILogger Logger = ApplicationContext.Logger.ForType<RequestBuilder>(); |
| |
|
| | |
| | private static Regex PathParametersPattern = new Regex(@"{[^{}]*}*"); |
| |
|
| | |
| | private static IEnumerable<string> SupportedMethods = new List<string> |
| | { |
| | HttpConsts.Get, HttpConsts.Post, HttpConsts.Put, HttpConsts.Delete, HttpConsts.Patch |
| | }; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | private IDictionary<string, IList<string>> PathParameters { get; set; } |
| |
|
| | |
| | |
| | |
| | private List<KeyValuePair<string, string>> QueryParameters { get; set; } |
| |
|
| | |
| | public Uri BaseUri { get; set; } |
| |
|
| | |
| | |
| | |
| | |
| | public string Path { get; set; } |
| |
|
| | |
| | private string method; |
| |
|
| | |
| | |
| | public string Method |
| | { |
| | get { return method; } |
| | set |
| | { |
| | if (!SupportedMethods.Contains(value)) |
| | throw new ArgumentOutOfRangeException("Method"); |
| | method = value; |
| | } |
| | } |
| |
|
| | |
| | |
| | public RequestBuilder() |
| | { |
| | PathParameters = new Dictionary<string, IList<string>>(); |
| | QueryParameters = new List<KeyValuePair<string, string>>(); |
| | Method = HttpConsts.Get; |
| | } |
| |
|
| | |
| | public Uri BuildUri() |
| | { |
| | var restPath = BuildRestPath(); |
| |
|
| | if (QueryParameters.Count > 0) |
| | { |
| | |
| | restPath.Append(restPath.ToString().Contains("?") ? "&" : "?"); |
| |
|
| | |
| | restPath.Append(String.Join("&", QueryParameters.Select( |
| | x => string.IsNullOrEmpty(x.Value) ? |
| | Uri.EscapeDataString(x.Key) : |
| | String.Format("{0}={1}", Uri.EscapeDataString(x.Key), Uri.EscapeDataString(x.Value))) |
| | .ToArray())); |
| | } |
| |
|
| | return UriJoin(this.BaseUri, restPath.ToString()); |
| | } |
| |
|
| | private Uri UriJoin(Uri baseUri, string path) |
| | { |
| | |
| | |
| | if (path == "") |
| | { |
| | return baseUri; |
| | } |
| | var baseUriStr = baseUri.AbsoluteUri; |
| | if (path.StartsWith("/", StringComparison.Ordinal)) |
| | { |
| | |
| | baseUriStr = Regex.Replace(baseUriStr, "^([^:]+://[^/]+)/.*$", "$1"); |
| | } |
| | else |
| | { |
| | if (!path.StartsWith("?", StringComparison.Ordinal) && |
| | !path.StartsWith("#", StringComparison.Ordinal)) |
| | { |
| | while (!baseUriStr.EndsWith("/", StringComparison.Ordinal)) |
| | { |
| | baseUriStr = baseUriStr.Substring(0, baseUriStr.Length - 1); |
| | } |
| | } |
| | } |
| | return new Uri(baseUriStr + path); |
| | } |
| |
|
| | |
| | private const string OPERATORS = "+#./;?&|!@="; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | private StringBuilder BuildRestPath() |
| | { |
| | if (string.IsNullOrEmpty(Path)) |
| | { |
| | return new StringBuilder(string.Empty); |
| | } |
| |
|
| | var restPath = new StringBuilder(Path); |
| | var matches = PathParametersPattern.Matches(restPath.ToString()); |
| | foreach (var match in matches) |
| | { |
| | var matchStr = match.ToString(); |
| | |
| | var content = matchStr.Substring(1, matchStr.Length - 2); |
| |
|
| | var op = string.Empty; |
| | |
| | if (OPERATORS.Contains(content[0].ToString())) |
| | { |
| | op = content[0].ToString(); |
| | content = content.Substring(1); |
| | } |
| |
|
| | var newContent = new StringBuilder(); |
| |
|
| | |
| | var parameters = content.Split(','); |
| | for (var index = 0; index < parameters.Length; ++index) |
| | { |
| | var parameter = parameters[index]; |
| |
|
| | var parameterName = parameter; |
| | var containStar = false; |
| | var numOfChars = 0; |
| |
|
| | |
| | if (parameterName[parameterName.Length - 1] == '*') |
| | { |
| | containStar = true; |
| | parameterName = parameterName.Substring(0, parameterName.Length - 1); |
| | } |
| | |
| | if (parameterName.Contains(":")) |
| | { |
| | if (!int.TryParse(parameterName.Substring(parameterName.IndexOf(':') + 1), out numOfChars)) |
| | { |
| | throw new ArgumentException( |
| | string.Format("Can't parse number after ':' in Path \"{0}\". Parameter is \"{1}\"", |
| | Path, parameterName), Path); |
| | } |
| | parameterName = parameterName.Substring(0, parameterName.IndexOf(':')); |
| | } |
| |
|
| | |
| | var joiner = op; |
| | var start = op; |
| | switch (op) |
| | { |
| | case "+": |
| | start = index == 0 ? "" : ","; |
| | joiner = ","; |
| | break; |
| | case ".": |
| | if (!containStar) |
| | { |
| | joiner = ","; |
| | } |
| | break; |
| | case "/": |
| | if (!containStar) |
| | { |
| | joiner = ","; |
| | } |
| | break; |
| | case "#": |
| | start = index == 0 ? "#" : ","; |
| | joiner = ","; |
| | break; |
| |
|
| | case "?": |
| | start = (index == 0 ? "?" : "&") + parameterName + "="; |
| | joiner = ","; |
| | if (containStar) |
| | { |
| | joiner = "&" + parameterName + "="; |
| | } |
| | break; |
| | case "&": |
| | case ";": |
| | start = op + parameterName + "="; |
| | joiner = ","; |
| | if (containStar) |
| | { |
| | joiner = op + parameterName + "="; |
| | } |
| | break; |
| | |
| | default: |
| | if (index > 0) |
| | { |
| | start = ","; |
| | } |
| | joiner = ","; |
| | break; |
| | } |
| |
|
| | |
| | if (PathParameters.ContainsKey(parameterName)) |
| | { |
| | var value = string.Join(joiner, PathParameters[parameterName]); |
| |
|
| | |
| | if (numOfChars != 0 && numOfChars < value.Length) |
| | { |
| | value = value.Substring(0, numOfChars); |
| | } |
| |
|
| | if (op != "+" && op != "#" && PathParameters[parameterName].Count == 1) |
| | { |
| | value = Uri.EscapeDataString(value); |
| | } |
| |
|
| | value = start + value; |
| | newContent.Append(value); |
| | } |
| | else |
| | { |
| | throw new ArgumentException( |
| | string.Format("Path \"{0}\" misses a \"{1}\" parameter", Path, parameterName), Path); |
| | } |
| | } |
| |
|
| | if (op == ";") |
| | { |
| | if (newContent[newContent.Length - 1] == '=') |
| | { |
| | newContent = newContent.Remove(newContent.Length - 1, 1); |
| | } |
| | newContent = newContent.Replace("=;", ";"); |
| | } |
| | restPath = restPath.Replace(matchStr, newContent.ToString()); |
| | } |
| | return restPath; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | public void AddParameter(RequestParameterType type, string name, string value) |
| | { |
| | name.ThrowIfNull("name"); |
| | if (value == null) |
| | { |
| | Logger.Warning("Add parameter should not get null values. type={0}, name={1}", type, name); |
| | return; |
| | } |
| | switch (type) |
| | { |
| | case RequestParameterType.Path: |
| | if (!PathParameters.ContainsKey(name)) |
| | { |
| | PathParameters[name] = new List<string> { value }; |
| | } |
| | else |
| | { |
| | PathParameters[name].Add(value); |
| | } |
| | break; |
| | case RequestParameterType.Query: |
| | QueryParameters.Add(new KeyValuePair<string, string>(name, value)); |
| | break; |
| | default: |
| | throw new ArgumentOutOfRangeException("type"); |
| | } |
| | } |
| |
|
| | |
| | public HttpRequestMessage CreateRequest() |
| | { |
| | return new HttpRequestMessage(new HttpMethod(Method), BuildUri()); |
| | } |
| | } |
| | } |
| |
|