| | | 1 | | using System; |
| | | 2 | | using System.Collections.Generic; |
| | | 3 | | using System.Linq; |
| | | 4 | | using System.Text; |
| | | 5 | | using System.Net; |
| | | 6 | | using JetBrains.Annotations; |
| | | 7 | | using WireMock.Models; |
| | | 8 | | using WireMock.Util; |
| | | 9 | | using WireMock.Validation; |
| | | 10 | | |
| | | 11 | | namespace WireMock |
| | | 12 | | { |
| | | 13 | | /// <summary> |
| | | 14 | | /// The RequestMessage. |
| | | 15 | | /// </summary> |
| | | 16 | | public class RequestMessage |
| | | 17 | | { |
| | | 18 | | /// <summary> |
| | | 19 | | /// Gets the Client IP Address. |
| | | 20 | | /// </summary> |
| | 60 | 21 | | public string ClientIP { get; } |
| | | 22 | | |
| | | 23 | | /// <summary> |
| | | 24 | | /// Gets the url (relative). |
| | | 25 | | /// </summary> |
| | 60 | 26 | | public string Url { get; } |
| | | 27 | | |
| | | 28 | | /// <summary> |
| | | 29 | | /// Gets the AbsoluteUrl. |
| | | 30 | | /// </summary> |
| | 54 | 31 | | public string AbsoluteUrl { get; } |
| | | 32 | | |
| | | 33 | | /// <summary> |
| | | 34 | | /// Gets the DateTime. |
| | | 35 | | /// </summary> |
| | 101 | 36 | | public DateTime DateTime { get; set; } |
| | | 37 | | |
| | | 38 | | /// <summary> |
| | | 39 | | /// Gets the path (relative). |
| | | 40 | | /// </summary> |
| | 615 | 41 | | public string Path { get; } |
| | | 42 | | |
| | | 43 | | /// <summary> |
| | | 44 | | /// Gets the AbsolutePath. |
| | | 45 | | /// </summary> |
| | 255 | 46 | | public string AbsolutePath { get; } |
| | | 47 | | |
| | | 48 | | /// <summary> |
| | | 49 | | /// Gets the path segments. |
| | | 50 | | /// </summary> |
| | 3 | 51 | | public string[] PathSegments { get; } |
| | | 52 | | |
| | | 53 | | /// <summary> |
| | | 54 | | /// Gets the absolute path segments. |
| | | 55 | | /// </summary> |
| | 1 | 56 | | public string[] AbsolutePathSegments { get; } |
| | | 57 | | |
| | | 58 | | /// <summary> |
| | | 59 | | /// Gets the method. |
| | | 60 | | /// </summary> |
| | 350 | 61 | | public string Method { get; } |
| | | 62 | | |
| | | 63 | | /// <summary> |
| | | 64 | | /// Gets the headers. |
| | | 65 | | /// </summary> |
| | 188 | 66 | | public IDictionary<string, WireMockList<string>> Headers { get; } |
| | | 67 | | |
| | | 68 | | /// <summary> |
| | | 69 | | /// Gets the cookies. |
| | | 70 | | /// </summary> |
| | 74 | 71 | | public IDictionary<string, string> Cookies { get; } |
| | | 72 | | |
| | | 73 | | /// <summary> |
| | | 74 | | /// Gets the query. |
| | | 75 | | /// </summary> |
| | 103 | 76 | | public IDictionary<string, WireMockList<string>> Query { get; } |
| | | 77 | | |
| | | 78 | | /// <summary> |
| | | 79 | | /// Gets the raw query. |
| | | 80 | | /// </summary> |
| | 200 | 81 | | public string RawQuery { get; } |
| | | 82 | | |
| | | 83 | | /// <summary> |
| | | 84 | | /// The original body as string, this is defined when Body or BodyAsJson are not null. |
| | | 85 | | /// </summary> |
| | 107 | 86 | | public string Body { get; } |
| | | 87 | | |
| | | 88 | | /// <summary> |
| | | 89 | | /// The body (as JSON object). |
| | | 90 | | /// </summary> |
| | 300 | 91 | | public object BodyAsJson { get; set; } |
| | | 92 | | |
| | | 93 | | /// <summary> |
| | | 94 | | /// The body (as bytearray). |
| | | 95 | | /// </summary> |
| | 270 | 96 | | public byte[] BodyAsBytes { get; set; } |
| | | 97 | | |
| | | 98 | | /// <summary> |
| | | 99 | | /// Gets the Host |
| | | 100 | | /// </summary> |
| | 201 | 101 | | public string Host { get; } |
| | | 102 | | |
| | | 103 | | /// <summary> |
| | | 104 | | /// Gets the protocol |
| | | 105 | | /// </summary> |
| | 201 | 106 | | public string Protocol { get; } |
| | | 107 | | |
| | | 108 | | /// <summary> |
| | | 109 | | /// Gets the port |
| | | 110 | | /// </summary> |
| | 201 | 111 | | public int Port { get; } |
| | | 112 | | |
| | | 113 | | /// <summary> |
| | | 114 | | /// Gets the origin |
| | | 115 | | /// </summary> |
| | 1 | 116 | | public string Origin { get; } |
| | | 117 | | |
| | | 118 | | /// <summary> |
| | | 119 | | /// The body encoding. |
| | | 120 | | /// </summary> |
| | 87 | 121 | | public Encoding BodyEncoding { get; } |
| | | 122 | | |
| | | 123 | | /// <summary> |
| | | 124 | | /// Initializes a new instance of the <see cref="RequestMessage"/> class. |
| | | 125 | | /// </summary> |
| | | 126 | | /// <param name="urlDetails">The original url details.</param> |
| | | 127 | | /// <param name="method">The HTTP method.</param> |
| | | 128 | | /// <param name="clientIP">The client IP Address.</param> |
| | | 129 | | /// <param name="body">The body.</param> |
| | | 130 | | /// <param name="headers">The headers.</param> |
| | | 131 | | /// <param name="cookies">The cookies.</param> |
| | 200 | 132 | | public RequestMessage([NotNull] UrlDetails urlDetails, [NotNull] string method, [NotNull] string clientIP, [CanB |
| | 200 | 133 | | { |
| | 200 | 134 | | Check.NotNull(urlDetails, nameof(urlDetails)); |
| | 200 | 135 | | Check.NotNull(method, nameof(method)); |
| | 200 | 136 | | Check.NotNull(clientIP, nameof(clientIP)); |
| | | 137 | | |
| | 200 | 138 | | AbsoluteUrl = urlDetails.AbsoluteUrl.ToString(); |
| | 200 | 139 | | Url = urlDetails.Url.ToString(); |
| | 200 | 140 | | Protocol = urlDetails.Url.Scheme; |
| | 200 | 141 | | Host = urlDetails.Url.Host; |
| | 200 | 142 | | Port = urlDetails.Url.Port; |
| | 200 | 143 | | Origin = $"{Protocol}://{Host}:{Port}"; |
| | | 144 | | |
| | 200 | 145 | | AbsolutePath = WebUtility.UrlDecode(urlDetails.AbsoluteUrl.AbsolutePath); |
| | 200 | 146 | | Path = WebUtility.UrlDecode(urlDetails.Url.AbsolutePath); |
| | 200 | 147 | | PathSegments = Path.Split('/').Skip(1).ToArray(); |
| | 200 | 148 | | AbsolutePathSegments = AbsolutePath.Split('/').Skip(1).ToArray(); |
| | | 149 | | |
| | 200 | 150 | | Method = method; |
| | 200 | 151 | | ClientIP = clientIP; |
| | | 152 | | |
| | 200 | 153 | | Body = body?.BodyAsString; |
| | 200 | 154 | | BodyEncoding = body?.Encoding; |
| | 200 | 155 | | BodyAsJson = body?.BodyAsJson; |
| | 200 | 156 | | BodyAsBytes = body?.BodyAsBytes; |
| | | 157 | | |
| | 366 | 158 | | Headers = headers?.ToDictionary(header => header.Key, header => new WireMockList<string>(header.Value)); |
| | 200 | 159 | | Cookies = cookies; |
| | 200 | 160 | | RawQuery = WebUtility.UrlDecode(urlDetails.Url.Query); |
| | 200 | 161 | | Query = ParseQuery(RawQuery); |
| | 200 | 162 | | } |
| | | 163 | | |
| | | 164 | | private static IDictionary<string, WireMockList<string>> ParseQuery(string queryString) |
| | 200 | 165 | | { |
| | 200 | 166 | | if (string.IsNullOrEmpty(queryString)) |
| | 187 | 167 | | { |
| | 187 | 168 | | return null; |
| | | 169 | | } |
| | | 170 | | |
| | 13 | 171 | | if (queryString.StartsWith("?")) |
| | 13 | 172 | | { |
| | 13 | 173 | | queryString = queryString.Substring(1); |
| | 13 | 174 | | } |
| | | 175 | | |
| | 13 | 176 | | return queryString.Split(new[] { '&' }, StringSplitOptions.RemoveEmptyEntries) |
| | 13 | 177 | | .Aggregate(new Dictionary<string, WireMockList<string>>(), |
| | 13 | 178 | | (dict, term) => |
| | 33 | 179 | | { |
| | 33 | 180 | | string[] parts = term.Split(new[] { '=' }, StringSplitOptions.RemoveEmptyEntries); |
| | 33 | 181 | | string key = parts[0]; |
| | 33 | 182 | | if (!dict.ContainsKey(key)) |
| | 28 | 183 | | { |
| | 28 | 184 | | dict.Add(key, new WireMockList<string>()); |
| | 28 | 185 | | } |
| | 13 | 186 | | |
| | 33 | 187 | | if (parts.Length == 2) |
| | 30 | 188 | | { |
| | 30 | 189 | | string[] values = parts[1].Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries); |
| | 30 | 190 | | dict[key].AddRange(values); |
| | 30 | 191 | | } |
| | 13 | 192 | | |
| | 33 | 193 | | return dict; |
| | 33 | 194 | | }); |
| | 200 | 195 | | } |
| | | 196 | | |
| | | 197 | | /// <summary> |
| | | 198 | | /// Get a query parameter. |
| | | 199 | | /// </summary> |
| | | 200 | | /// <param name="key">The key.</param> |
| | | 201 | | /// <returns>The query parameter.</returns> |
| | | 202 | | public WireMockList<string> GetParameter(string key) |
| | 16 | 203 | | { |
| | 16 | 204 | | if (Query == null) |
| | 2 | 205 | | { |
| | 2 | 206 | | return null; |
| | | 207 | | } |
| | | 208 | | |
| | 14 | 209 | | return Query.ContainsKey(key) ? Query[key] : null; |
| | 16 | 210 | | } |
| | | 211 | | } |
| | | 212 | | } |