2010-04-14 10:28:33 -07:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
2010-04-21 15:01:01 -07:00
|
|
|
|
using System.Diagnostics;
|
2010-04-14 10:28:33 -07:00
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
2010-12-02 15:53:31 -08:00
|
|
|
|
using System.Text.RegularExpressions;
|
2010-04-14 10:28:33 -07:00
|
|
|
|
using System.Web;
|
|
|
|
|
using System.Web.Hosting;
|
|
|
|
|
using Orchard.Specs.Util;
|
|
|
|
|
|
2010-04-20 14:13:14 -07:00
|
|
|
|
namespace Orchard.Specs.Hosting {
|
|
|
|
|
public static class RequestExtensions {
|
|
|
|
|
public static RequestDetails SendRequest(this WebHost webHost, string urlPath, IDictionary<string, IEnumerable<string>> postData) {
|
2010-04-21 15:01:01 -07:00
|
|
|
|
|
2010-04-14 12:50:00 -07:00
|
|
|
|
var physicalPath = Bleroy.FluentPath.Path.Get(webHost.PhysicalDirectory);
|
2010-04-14 10:28:33 -07:00
|
|
|
|
|
2010-11-29 16:01:46 -08:00
|
|
|
|
urlPath = StripVDir(urlPath, webHost.VirtualDirectory);
|
2010-04-20 14:13:14 -07:00
|
|
|
|
var details = new RequestDetails {
|
2010-04-23 17:05:28 -07:00
|
|
|
|
HostName = webHost.HostName,
|
2010-04-20 14:13:14 -07:00
|
|
|
|
UrlPath = urlPath,
|
2010-04-14 10:28:33 -07:00
|
|
|
|
Page = physicalPath
|
|
|
|
|
.Combine(urlPath.TrimStart('/', '\\'))
|
2010-11-29 16:01:46 -08:00
|
|
|
|
.GetRelativePath(physicalPath)
|
2010-04-14 10:28:33 -07:00
|
|
|
|
};
|
|
|
|
|
|
2010-04-21 15:01:01 -07:00
|
|
|
|
if (!string.IsNullOrEmpty(webHost.Cookies)) {
|
|
|
|
|
details.RequestHeaders.Add("Cookie", webHost.Cookies);
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-20 14:13:14 -07:00
|
|
|
|
if (postData != null) {
|
|
|
|
|
var requestBodyText = postData
|
2010-04-21 15:01:01 -07:00
|
|
|
|
.SelectMany(kv => kv.Value.Select(v => new { k = kv.Key, v }))
|
|
|
|
|
.Select((kv, n) => new { p = HttpUtility.UrlEncode(kv.k) + "=" + HttpUtility.UrlEncode(kv.v), n })
|
2010-04-20 14:13:14 -07:00
|
|
|
|
.Aggregate("", (a, x) => a + (x.n == 0 ? "" : "&") + x.p);
|
|
|
|
|
details.PostData = Encoding.Default.GetBytes(requestBodyText);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
webHost.Execute(() => {
|
2010-04-14 10:28:33 -07:00
|
|
|
|
var output = new StringWriter();
|
2010-04-21 15:01:01 -07:00
|
|
|
|
var worker = new Worker(details, output);
|
|
|
|
|
HttpRuntime.ProcessRequest(worker);
|
2010-04-14 10:28:33 -07:00
|
|
|
|
details.ResponseText = output.ToString();
|
|
|
|
|
});
|
|
|
|
|
|
2010-04-21 15:01:01 -07:00
|
|
|
|
string setCookie;
|
|
|
|
|
if (details.ResponseHeaders.TryGetValue("Set-Cookie", out setCookie)) {
|
|
|
|
|
Trace.WriteLine(string.Format("Set-Cookie: {0}", setCookie));
|
2010-12-02 15:53:31 -08:00
|
|
|
|
var cookieName = setCookie.Split(';')[0].Split('=')[0];
|
|
|
|
|
DateTime expires;
|
|
|
|
|
if (!string.IsNullOrEmpty(webHost.Cookies)
|
|
|
|
|
&& setCookie.Contains("expires=")
|
|
|
|
|
&& DateTime.TryParse(setCookie.Split(new[] { "expires=" }, 2, StringSplitOptions.None)[1].Split(';')[0], out expires)
|
|
|
|
|
&& expires < DateTime.Now) {
|
|
|
|
|
// remove
|
|
|
|
|
Trace.WriteLine(string.Format("Removing cookie: {0}", cookieName));
|
|
|
|
|
webHost.Cookies = Regex.Replace(webHost.Cookies, string.Format("{0}=[^;]*;?", cookieName), "");
|
|
|
|
|
}
|
|
|
|
|
else if (!string.IsNullOrEmpty(webHost.Cookies)
|
|
|
|
|
&& Regex.IsMatch(webHost.Cookies, string.Format("\b{0}=", cookieName))) {
|
|
|
|
|
// replace
|
|
|
|
|
Trace.WriteLine(string.Format("Replacing cookie: {0}", cookieName));
|
|
|
|
|
webHost.Cookies = Regex.Replace(webHost.Cookies, string.Format("{0}=[^;]*(;?)", cookieName), string.Format("{0}$1", setCookie.Split(';')[0]));
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
// add
|
|
|
|
|
Trace.WriteLine(string.Format("Adding cookie: {0}", cookieName));
|
|
|
|
|
webHost.Cookies = (webHost.Cookies + ';' + setCookie.Split(';').FirstOrDefault()).Trim(';');
|
|
|
|
|
}
|
|
|
|
|
Trace.WriteLine(string.Format("Cookie jar: {0}", webHost.Cookies));
|
2010-04-21 15:01:01 -07:00
|
|
|
|
}
|
|
|
|
|
|
2010-04-14 10:28:33 -07:00
|
|
|
|
return details;
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-29 16:01:46 -08:00
|
|
|
|
private static string StripVDir(string urlPath, string virtualDirectory) {
|
2010-12-10 21:09:53 -08:00
|
|
|
|
if (urlPath == "/")
|
|
|
|
|
return urlPath;
|
|
|
|
|
|
2010-11-29 16:01:46 -08:00
|
|
|
|
return urlPath.StartsWith(virtualDirectory, StringComparison.OrdinalIgnoreCase)
|
|
|
|
|
? urlPath.Substring(virtualDirectory.Length)
|
|
|
|
|
: urlPath;
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-20 14:13:14 -07:00
|
|
|
|
public static RequestDetails SendRequest(this WebHost webHost, string urlPath) {
|
|
|
|
|
return webHost.SendRequest(urlPath, null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class Worker : SimpleWorkerRequest {
|
2010-04-14 18:22:23 -07:00
|
|
|
|
private readonly RequestDetails _details;
|
|
|
|
|
private readonly TextWriter _output;
|
2010-04-14 10:28:33 -07:00
|
|
|
|
|
|
|
|
|
public Worker(RequestDetails details, TextWriter output)
|
2010-04-20 14:13:14 -07:00
|
|
|
|
: base(details.Page, details.Query, output) {
|
2010-04-14 10:28:33 -07:00
|
|
|
|
_details = details;
|
|
|
|
|
_output = output;
|
2010-04-20 14:13:14 -07:00
|
|
|
|
PostContentType = "application/x-www-form-urlencoded";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string PostContentType { get; set; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public override String GetHttpVerbName() {
|
|
|
|
|
if (_details.PostData == null)
|
|
|
|
|
return base.GetHttpVerbName();
|
|
|
|
|
|
|
|
|
|
return "POST";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override string GetKnownRequestHeader(int index) {
|
|
|
|
|
if (index == HeaderContentLength) {
|
|
|
|
|
if (_details.PostData != null)
|
|
|
|
|
return _details.PostData.Length.ToString();
|
|
|
|
|
}
|
|
|
|
|
else if (index == HeaderContentType) {
|
|
|
|
|
if (_details.PostData != null)
|
|
|
|
|
return PostContentType;
|
|
|
|
|
}
|
2010-04-21 15:01:01 -07:00
|
|
|
|
else if (index == HeaderCookie) {
|
|
|
|
|
string value;
|
|
|
|
|
if (_details.RequestHeaders.TryGetValue("Cookie", out value))
|
|
|
|
|
return value;
|
|
|
|
|
}
|
2010-04-23 17:05:28 -07:00
|
|
|
|
else if (index==HeaderHost) {
|
|
|
|
|
return _details.HostName;
|
|
|
|
|
}
|
2010-04-20 14:13:14 -07:00
|
|
|
|
return base.GetKnownRequestHeader(index);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override byte[] GetPreloadedEntityBody() {
|
|
|
|
|
if (_details.PostData != null)
|
|
|
|
|
return _details.PostData;
|
|
|
|
|
|
|
|
|
|
return base.GetPreloadedEntityBody();
|
2010-04-14 10:28:33 -07:00
|
|
|
|
}
|
|
|
|
|
|
2010-04-20 14:13:14 -07:00
|
|
|
|
public override void SendStatus(int statusCode, string statusDescription) {
|
2010-04-14 10:28:33 -07:00
|
|
|
|
_details.StatusCode = statusCode;
|
|
|
|
|
_details.StatusDescription = statusDescription;
|
|
|
|
|
|
|
|
|
|
base.SendStatus(statusCode, statusDescription);
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-21 15:01:01 -07:00
|
|
|
|
public override void SendKnownResponseHeader(int index, string value) {
|
2010-11-18 10:24:26 -08:00
|
|
|
|
switch (index) {
|
|
|
|
|
case HeaderSetCookie:
|
|
|
|
|
_details.ResponseHeaders.Add("Set-Cookie", value);
|
|
|
|
|
break;
|
|
|
|
|
case HeaderLocation:
|
|
|
|
|
_details.ResponseHeaders.Add("Location", value);
|
|
|
|
|
break;
|
|
|
|
|
case HeaderContentType:
|
|
|
|
|
_details.ResponseHeaders.Add("Content-Type", value);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
_details.ResponseHeaders.Add("known header #" + index, value);
|
|
|
|
|
break;
|
2010-04-21 15:01:01 -07:00
|
|
|
|
}
|
|
|
|
|
base.SendKnownResponseHeader(index, value);
|
|
|
|
|
}
|
|
|
|
|
public override void SendUnknownResponseHeader(string name, string value) {
|
|
|
|
|
_details.ResponseHeaders.Add(name, value);
|
|
|
|
|
|
|
|
|
|
base.SendUnknownResponseHeader(name, value);
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-20 14:13:14 -07:00
|
|
|
|
public override void SendResponseFromFile(string filename, long offset, long length) {
|
2010-04-14 10:28:33 -07:00
|
|
|
|
_output.Write(File.ReadAllText(filename));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-04-14 18:22:23 -07:00
|
|
|
|
|