update to service stack v4

pull/702/head
Luke Pulverenti 11 years ago
parent 1b1bcabbb1
commit f32212d160

@ -3,7 +3,7 @@ using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using ServiceStack.ServiceHost;
using ServiceStack;
using System;
using System.Collections.Generic;
using System.Linq;

@ -2,10 +2,10 @@
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Logging;
using ServiceStack.Common.Web;
using ServiceStack.ServiceHost;
using ServiceStack.Web;
using System;
using System.Collections.Generic;
using System.Net.Http.Headers;
namespace MediaBrowser.Api
{
@ -32,11 +32,10 @@ namespace MediaBrowser.Api
/// <param name="request">The http request wrapper</param>
/// <param name="response">The http response wrapper</param>
/// <param name="requestDto">The request DTO</param>
public void RequestFilter(IHttpRequest request, IHttpResponse response, object requestDto)
public void RequestFilter(IRequest request, IResponse response, object requestDto)
{
//This code is executed before the service
var auth = GetAuthorization(request);
var auth = GetAuthorizationDictionary(request);
if (auth != null)
{
@ -74,9 +73,9 @@ namespace MediaBrowser.Api
/// </summary>
/// <param name="httpReq">The HTTP req.</param>
/// <returns>Dictionary{System.StringSystem.String}.</returns>
public static Dictionary<string, string> GetAuthorization(IHttpRequest httpReq)
private static Dictionary<string, string> GetAuthorizationDictionary(IRequest httpReq)
{
var auth = httpReq.Headers[HttpHeaders.Authorization];
var auth = httpReq.Headers["Authorization"];
return GetAuthorization(auth);
}
@ -86,11 +85,9 @@ namespace MediaBrowser.Api
/// </summary>
/// <param name="httpReq">The HTTP req.</param>
/// <returns>Dictionary{System.StringSystem.String}.</returns>
public static AuthorizationInfo GetAuthorization(IRequestContext httpReq)
public static AuthorizationInfo GetAuthorization(IRequest httpReq)
{
var header = httpReq.GetHeader("Authorization");
var auth = GetAuthorization(header);
var auth = GetAuthorizationDictionary(httpReq);
string userId;
string deviceId;

@ -1,12 +1,12 @@
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Logging;
using ServiceStack.ServiceHost;
using System;
using System.Collections.Generic;
using System.Linq;
using ServiceStack.Web;
namespace MediaBrowser.Api
{
@ -32,7 +32,12 @@ namespace MediaBrowser.Api
/// Gets or sets the request context.
/// </summary>
/// <value>The request context.</value>
public IRequestContext RequestContext { get; set; }
public IRequest Request { get; set; }
public string GetHeader(string name)
{
return Request.Headers[name];
}
/// <summary>
/// To the optimized result.
@ -43,7 +48,7 @@ namespace MediaBrowser.Api
protected object ToOptimizedResult<T>(T result)
where T : class
{
return ResultFactory.GetOptimizedResult(RequestContext, result);
return ResultFactory.GetOptimizedResult(Request, result);
}
/// <summary>
@ -59,7 +64,7 @@ namespace MediaBrowser.Api
protected object ToOptimizedResultUsingCache<T>(Guid cacheKey, DateTime lastDateModified, TimeSpan? cacheDuration, Func<T> factoryFn)
where T : class
{
return ResultFactory.GetOptimizedResultUsingCache(RequestContext, cacheKey, lastDateModified, cacheDuration, factoryFn);
return ResultFactory.GetOptimizedResultUsingCache(Request, cacheKey, lastDateModified, cacheDuration, factoryFn);
}
/// <summary>
@ -76,7 +81,7 @@ namespace MediaBrowser.Api
protected object ToCachedResult<T>(Guid cacheKey, DateTime lastDateModified, TimeSpan? cacheDuration, Func<T> factoryFn, string contentType)
where T : class
{
return ResultFactory.GetCachedResult(RequestContext, cacheKey, lastDateModified, cacheDuration, factoryFn, contentType);
return ResultFactory.GetCachedResult(Request, cacheKey, lastDateModified, cacheDuration, factoryFn, contentType);
}
/// <summary>
@ -86,7 +91,7 @@ namespace MediaBrowser.Api
/// <returns>System.Object.</returns>
protected object ToStaticFileResult(string path)
{
return ResultFactory.GetStaticFileResult(RequestContext, path);
return ResultFactory.GetStaticFileResult(Request, path);
}
private readonly char[] _dashReplaceChars = new[] { '?', '/' };

@ -9,7 +9,7 @@ using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Querying;
using ServiceStack.ServiceHost;
using ServiceStack;
using System;
using System.Collections.Generic;
using System.Linq;

@ -2,7 +2,7 @@
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Serialization;
using ServiceStack.ServiceHost;
using ServiceStack;
using System;
using System.Threading;
using System.Threading.Tasks;

@ -1,7 +1,7 @@
using MediaBrowser.Common.Net;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Net;
using ServiceStack.ServiceHost;
using ServiceStack;
using System;
using System.Collections.Generic;
using System.Globalization;

@ -4,7 +4,7 @@ using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Dto;
using ServiceStack.ServiceHost;
using ServiceStack;
using System;
using System.Collections.Generic;
using System.IO;

@ -1,7 +1,7 @@
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Entities;
using ServiceStack.ServiceHost;
using ServiceStack;
using System;
using System.IO;
using System.Linq;

@ -1,6 +1,6 @@
using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Entities;
using ServiceStack.ServiceHost;
using ServiceStack;
namespace MediaBrowser.Api.Images
{

@ -11,8 +11,7 @@ using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using ServiceStack.ServiceHost;
using ServiceStack.Text.Controller;
using ServiceStack;
using System;
using System.Collections.Generic;
using System.Drawing;
@ -20,6 +19,8 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using ServiceStack.Text.Controller;
using ServiceStack.Web;
namespace MediaBrowser.Api.Images
{
@ -453,7 +454,7 @@ namespace MediaBrowser.Api.Images
/// <returns>Task{List{ImageInfo}}.</returns>
private List<ImageInfo> GetItemByNameImageInfos(GetItemByNameImageInfos request)
{
var pathInfo = PathInfo.Parse(RequestContext.PathInfo);
var pathInfo = PathInfo.Parse(Request.PathInfo);
var type = pathInfo.GetArgumentValue<string>(0);
var item = GetItemByName(request.Name, type, _libraryManager);
@ -599,7 +600,7 @@ namespace MediaBrowser.Api.Images
public object Get(GetItemByNameImage request)
{
var pathInfo = PathInfo.Parse(RequestContext.PathInfo);
var pathInfo = PathInfo.Parse(Request.PathInfo);
var type = pathInfo.GetArgumentValue<string>(0);
var item = GetItemByName(request.Name, type, _libraryManager);
@ -613,21 +614,21 @@ namespace MediaBrowser.Api.Images
/// <param name="request">The request.</param>
public void Post(PostUserImage request)
{
var pathInfo = PathInfo.Parse(RequestContext.PathInfo);
var pathInfo = PathInfo.Parse(Request.PathInfo);
var id = new Guid(pathInfo.GetArgumentValue<string>(1));
request.Type = (ImageType)Enum.Parse(typeof(ImageType), pathInfo.GetArgumentValue<string>(3), true);
var item = _userManager.Users.First(i => i.Id == id);
var task = PostImage(item, request.RequestStream, request.Type, RequestContext.ContentType);
var task = PostImage(item, request.RequestStream, request.Type, Request.ContentType);
Task.WaitAll(task);
}
public void Post(PostItemByNameImage request)
{
var pathInfo = PathInfo.Parse(RequestContext.PathInfo);
var pathInfo = PathInfo.Parse(Request.PathInfo);
var type = pathInfo.GetArgumentValue<string>(0);
var name = pathInfo.GetArgumentValue<string>(1);
@ -635,7 +636,7 @@ namespace MediaBrowser.Api.Images
var item = GetItemByName(name, type, _libraryManager);
var task = PostImage(item, request.RequestStream, request.Type, RequestContext.ContentType);
var task = PostImage(item, request.RequestStream, request.Type, Request.ContentType);
Task.WaitAll(task);
}
@ -646,28 +647,28 @@ namespace MediaBrowser.Api.Images
/// <param name="request">The request.</param>
public void Post(PostItemImage request)
{
var pathInfo = PathInfo.Parse(RequestContext.PathInfo);
var pathInfo = PathInfo.Parse(Request.PathInfo);
var id = new Guid(pathInfo.GetArgumentValue<string>(1));
request.Type = (ImageType)Enum.Parse(typeof(ImageType), pathInfo.GetArgumentValue<string>(3), true);
var item = _libraryManager.GetItemById(id);
var task = PostImage(item, request.RequestStream, request.Type, RequestContext.ContentType);
var task = PostImage(item, request.RequestStream, request.Type, Request.ContentType);
Task.WaitAll(task);
}
public void Post(PostChannelImage request)
{
var pathInfo = PathInfo.Parse(RequestContext.PathInfo);
var pathInfo = PathInfo.Parse(Request.PathInfo);
var id = pathInfo.GetArgumentValue<string>(2);
request.Type = (ImageType)Enum.Parse(typeof(ImageType), pathInfo.GetArgumentValue<string>(4), true);
var item = _liveTv.GetChannel(id);
var task = PostImage(item, request.RequestStream, request.Type, RequestContext.ContentType);
var task = PostImage(item, request.RequestStream, request.Type, Request.ContentType);
Task.WaitAll(task);
}
@ -713,7 +714,7 @@ namespace MediaBrowser.Api.Images
/// <param name="request">The request.</param>
public void Delete(DeleteItemByNameImage request)
{
var pathInfo = PathInfo.Parse(RequestContext.PathInfo);
var pathInfo = PathInfo.Parse(Request.PathInfo);
var type = pathInfo.GetArgumentValue<string>(0);
var item = GetItemByName(request.Name, type, _libraryManager);
@ -742,7 +743,7 @@ namespace MediaBrowser.Api.Images
/// <param name="request">The request.</param>
public void Post(UpdateItemByNameImageIndex request)
{
var pathInfo = PathInfo.Parse(RequestContext.PathInfo);
var pathInfo = PathInfo.Parse(Request.PathInfo);
var type = pathInfo.GetArgumentValue<string>(0);
var item = GetItemByName(request.Name, type, _libraryManager);
@ -899,22 +900,22 @@ namespace MediaBrowser.Api.Images
{
if (format == ImageOutputFormat.Bmp)
{
return MimeTypes.GetMimeType("i.bmp");
return Common.Net.MimeTypes.GetMimeType("i.bmp");
}
if (format == ImageOutputFormat.Gif)
{
return MimeTypes.GetMimeType("i.gif");
return Common.Net.MimeTypes.GetMimeType("i.gif");
}
if (format == ImageOutputFormat.Jpg)
{
return MimeTypes.GetMimeType("i.jpg");
return Common.Net.MimeTypes.GetMimeType("i.jpg");
}
if (format == ImageOutputFormat.Png)
{
return MimeTypes.GetMimeType("i.png");
return Common.Net.MimeTypes.GetMimeType("i.png");
}
return MimeTypes.GetMimeType(path);
return Common.Net.MimeTypes.GetMimeType(path);
}
/// <summary>

@ -2,12 +2,12 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using ServiceStack.Service;
using ServiceStack.ServiceHost;
using ServiceStack;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using ServiceStack.Web;
namespace MediaBrowser.Api.Images
{

@ -8,14 +8,14 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
using ServiceStack.ServiceHost;
using ServiceStack.Text.Controller;
using ServiceStack;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using ServiceStack.Text.Controller;
namespace MediaBrowser.Api.Images
{
@ -181,7 +181,7 @@ namespace MediaBrowser.Api.Images
public object Get(GetItemByNameRemoteImageProviders request)
{
var pathInfo = PathInfo.Parse(RequestContext.PathInfo);
var pathInfo = PathInfo.Parse(Request.PathInfo);
var type = pathInfo.GetArgumentValue<string>(0);
var item = GetItemByName(request.Name, type, _libraryManager);
@ -212,7 +212,7 @@ namespace MediaBrowser.Api.Images
public object Get(GetItemByNameRemoteImages request)
{
var pathInfo = PathInfo.Parse(RequestContext.PathInfo);
var pathInfo = PathInfo.Parse(Request.PathInfo);
var type = pathInfo.GetArgumentValue<string>(0);
var item = GetItemByName(request.Name, type, _libraryManager);
@ -264,7 +264,7 @@ namespace MediaBrowser.Api.Images
public void Post(DownloadItemByNameRemoteImage request)
{
var pathInfo = PathInfo.Parse(RequestContext.PathInfo);
var pathInfo = PathInfo.Parse(Request.PathInfo);
var type = pathInfo.GetArgumentValue<string>(0);
var item = GetItemByName(request.Name, type, _libraryManager);

@ -2,7 +2,7 @@
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Querying;
using ServiceStack.ServiceHost;
using ServiceStack;
using System;
using System.Collections.Generic;
using System.Linq;

@ -2,7 +2,7 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
using ServiceStack.ServiceHost;
using ServiceStack;
using System;
using System.Linq;
using System.Threading;

@ -6,7 +6,7 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using ServiceStack.ServiceHost;
using ServiceStack;
using System;
using System.Linq;
using System.Threading;

@ -1,7 +1,7 @@
using MediaBrowser.Common;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using ServiceStack.ServiceHost;
using ServiceStack;
using System;
using System.Collections.Generic;
using System.Linq;

@ -4,7 +4,7 @@ using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using ServiceStack.ServiceHost;
using ServiceStack;
using System;
using System.Collections.Generic;
using System.IO;

@ -8,7 +8,7 @@ using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying;
using ServiceStack.ServiceHost;
using ServiceStack;
using System;
using System.Collections;
using System.Collections.Generic;

@ -1,7 +1,7 @@
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Model.LiveTv;
using MediaBrowser.Model.Querying;
using ServiceStack.ServiceHost;
using ServiceStack;
using System;
using System.Collections.Generic;
using System.Linq;

@ -1,7 +1,7 @@
using MediaBrowser.Controller.Localization;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Globalization;
using ServiceStack.ServiceHost;
using ServiceStack;
using System.Collections.Generic;
using System.Linq;

@ -38,6 +38,14 @@
<RunPostBuildEvent>Always</RunPostBuildEvent>
</PropertyGroup>
<ItemGroup>
<Reference Include="ServiceStack.Interfaces, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.Text, Version=3.9.70.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Text.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="Microsoft.CSharp" />
@ -48,15 +56,6 @@
<HintPath>..\packages\morelinq.1.0.16006\lib\net35\MoreLinq.dll</HintPath>
</Reference>
<Reference Include="System.Xml" />
<Reference Include="ServiceStack.Common">
<HintPath>..\packages\ServiceStack.Common.3.9.70\lib\net35\ServiceStack.Common.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.Interfaces">
<HintPath>..\packages\ServiceStack.Common.3.9.70\lib\net35\ServiceStack.Interfaces.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.Text">
<HintPath>..\packages\ServiceStack.Text.3.9.70\lib\net35\ServiceStack.Text.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\SharedVersion.cs">

@ -3,7 +3,7 @@ using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using ServiceStack.ServiceHost;
using ServiceStack;
namespace MediaBrowser.Api
{

@ -1,10 +1,10 @@
using MediaBrowser.Controller.Notifications;
using MediaBrowser.Model.Notifications;
using ServiceStack.ServiceHost;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using ServiceStack;
namespace MediaBrowser.Api
{

@ -7,7 +7,7 @@ using MediaBrowser.Common.Constants;
using MediaBrowser.Common.Net;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Serialization;
using ServiceStack.ServiceHost;
using ServiceStack;
namespace MediaBrowser.Api
{

@ -2,7 +2,7 @@
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Updates;
using MediaBrowser.Model.Updates;
using ServiceStack.ServiceHost;
using ServiceStack;
using System;
using System.Collections.Generic;
using System.Linq;

@ -791,7 +791,7 @@ namespace MediaBrowser.Api.Playback
var media = (IHasMediaStreams)item;
var url = RequestContext.PathInfo;
var url = Request.PathInfo;
if (!request.AudioCodec.HasValue)
{

@ -6,7 +6,7 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.IO;
using ServiceStack.ServiceHost;
using ServiceStack;
using System;
namespace MediaBrowser.Api.Playback.Hls

@ -1,7 +1,7 @@
using MediaBrowser.Controller;
using MediaBrowser.Model.Logging;
using ServiceStack.ServiceHost;
using ServiceStack.Text.Controller;
using ServiceStack.Web;
using System;
using System.IO;
using System.Linq;
@ -13,7 +13,7 @@ namespace MediaBrowser.Api.Playback.Hls
public ILogger Logger { get; set; }
public IServerApplicationPaths ApplicationPaths { get; set; }
public void ResponseFilter(IHttpRequest req, IHttpResponse res, object response)
public void ResponseFilter(IRequest req, IResponse res, object response)
{
var pathInfo = PathInfo.Parse(req.PathInfo);
var itemId = pathInfo.GetArgumentValue<string>(1);

@ -1,5 +1,5 @@
using MediaBrowser.Controller;
using ServiceStack.ServiceHost;
using ServiceStack;
using System;
using System.IO;
using System.Linq;
@ -87,11 +87,11 @@ namespace MediaBrowser.Api.Playback.Hls
{
OnBeginRequest(request.PlaylistId);
var file = request.PlaylistId + Path.GetExtension(RequestContext.PathInfo);
var file = request.PlaylistId + Path.GetExtension(Request.PathInfo);
file = Path.Combine(_appPaths.EncodedMediaCachePath, file);
return ResultFactory.GetStaticFileResult(RequestContext, file, FileShare.ReadWrite);
return ResultFactory.GetStaticFileResult(Request, file, FileShare.ReadWrite);
}
public void Delete(StopEncodingProcess request)
@ -106,13 +106,13 @@ namespace MediaBrowser.Api.Playback.Hls
/// <returns>System.Object.</returns>
public object Get(GetHlsVideoSegment request)
{
var file = request.SegmentId + Path.GetExtension(RequestContext.PathInfo);
var file = request.SegmentId + Path.GetExtension(Request.PathInfo);
file = Path.Combine(_appPaths.EncodedMediaCachePath, file);
OnBeginRequest(request.PlaylistId);
return ResultFactory.GetStaticFileResult(RequestContext, file);
return ResultFactory.GetStaticFileResult(Request, file);
}
/// <summary>
@ -122,11 +122,11 @@ namespace MediaBrowser.Api.Playback.Hls
/// <returns>System.Object.</returns>
public object Get(GetHlsAudioSegment request)
{
var file = request.SegmentId + Path.GetExtension(RequestContext.PathInfo);
var file = request.SegmentId + Path.GetExtension(Request.PathInfo);
file = Path.Combine(_appPaths.EncodedMediaCachePath, file);
return ResultFactory.GetStaticFileResult(RequestContext, file, FileShare.ReadWrite);
return ResultFactory.GetStaticFileResult(Request, file, FileShare.ReadWrite);
}
/// <summary>

@ -5,7 +5,7 @@ using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.IO;
using ServiceStack.ServiceHost;
using ServiceStack;
using System;
namespace MediaBrowser.Api.Playback.Hls

@ -6,7 +6,7 @@ using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.IO;
using ServiceStack.ServiceHost;
using ServiceStack;
using System.Collections.Generic;
namespace MediaBrowser.Api.Playback.Progressive

@ -102,7 +102,7 @@ namespace MediaBrowser.Api.Playback.Progressive
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
private void AddDlnaHeaders(StreamState state, IDictionary<string, string> responseHeaders, bool isStaticallyStreamed)
{
var timeSeek = RequestContext.GetHeader("TimeSeekRange.dlna.org");
var timeSeek = GetHeader("TimeSeekRange.dlna.org");
if (!string.IsNullOrEmpty(timeSeek))
{
@ -110,7 +110,7 @@ namespace MediaBrowser.Api.Playback.Progressive
return;
}
var transferMode = RequestContext.GetHeader("transferMode.dlna.org");
var transferMode = GetHeader("transferMode.dlna.org");
responseHeaders["transferMode.dlna.org"] = string.IsNullOrEmpty(transferMode) ? "Streaming" : transferMode;
var contentFeatures = string.Empty;
@ -210,12 +210,12 @@ namespace MediaBrowser.Api.Playback.Progressive
if (request.Static)
{
return ResultFactory.GetStaticFileResult(RequestContext, state.Item.Path, FileShare.Read, responseHeaders, isHeadRequest);
return ResultFactory.GetStaticFileResult(Request, state.Item.Path, FileShare.Read, responseHeaders, isHeadRequest);
}
if (outputPathExists && !ApiEntryPoint.Instance.HasActiveTranscodingJob(outputPath, TranscodingJobType.Progressive))
{
return ResultFactory.GetStaticFileResult(RequestContext, outputPath, FileShare.Read, responseHeaders, isHeadRequest);
return ResultFactory.GetStaticFileResult(Request, outputPath, FileShare.Read, responseHeaders, isHeadRequest);
}
return GetStreamResult(state, responseHeaders, isHeadRequest).Result;
@ -307,7 +307,7 @@ namespace MediaBrowser.Api.Playback.Progressive
return new ImageService(UserManager, LibraryManager, ApplicationPaths, null, ItemRepository, DtoService, ImageProcessor, null)
{
Logger = Logger,
RequestContext = RequestContext,
Request = Request,
ResultFactory = ResultFactory
}.Get(request);

@ -1,7 +1,6 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Model.Logging;
using ServiceStack.Service;
using ServiceStack.ServiceHost;
using ServiceStack.Web;
using System;
using System.Collections.Generic;
using System.IO;

@ -7,7 +7,7 @@ using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.IO;
using ServiceStack.ServiceHost;
using ServiceStack;
using System;
using System.IO;

@ -1,5 +1,4 @@
using ServiceStack.Service;
using ServiceStack.ServiceHost;
using ServiceStack.Web;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;

@ -1,5 +1,5 @@
using MediaBrowser.Model.Dto;
using ServiceStack.ServiceHost;
using ServiceStack;
namespace MediaBrowser.Api.Playback
{

@ -5,12 +5,13 @@ using MediaBrowser.Common.Updates;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Plugins;
using MediaBrowser.Model.Serialization;
using ServiceStack.ServiceHost;
using ServiceStack.Text.Controller;
using ServiceStack;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using ServiceStack.Text.Controller;
using ServiceStack.Web;
namespace MediaBrowser.Api
{
@ -79,7 +80,6 @@ namespace MediaBrowser.Api
/// </summary>
[Route("/Plugins/SecurityInfo", "GET")]
[Api(("Gets plugin registration information"))]
[Restrict(VisibilityTo = EndpointAttributes.None)]
public class GetPluginSecurityInfo : IReturn<PluginSecurityInfo>
{
}
@ -89,14 +89,12 @@ namespace MediaBrowser.Api
/// </summary>
[Route("/Plugins/SecurityInfo", "POST")]
[Api("Updates plugin registration information")]
[Restrict(VisibilityTo = EndpointAttributes.None)]
public class UpdatePluginSecurityInfo : PluginSecurityInfo, IReturnVoid
{
}
[Route("/Plugins/RegistrationRecords/{Name}", "GET")]
[Api("Gets registration status for a feature")]
[Restrict(VisibilityTo = EndpointAttributes.None)]
public class GetRegistrationStatus
{
[ApiMember(Name = "Name", Description = "Feature Name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
@ -224,7 +222,7 @@ namespace MediaBrowser.Api
{
// We need to parse this manually because we told service stack not to with IRequiresRequestStream
// https://code.google.com/p/servicestack/source/browse/trunk/Common/ServiceStack.Text/ServiceStack.Text/Controller/PathInfo.cs
var pathInfo = PathInfo.Parse(RequestContext.PathInfo);
var pathInfo = PathInfo.Parse(Request.PathInfo);
var id = new Guid(pathInfo.GetArgumentValue<string>(1));
var plugin = _appHost.Plugins.First(p => p.Id == id);

@ -1,11 +1,11 @@
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.ScheduledTasks;
using MediaBrowser.Model.Tasks;
using ServiceStack.ServiceHost;
using ServiceStack.Text.Controller;
using ServiceStack;
using System;
using System.Collections.Generic;
using System.Linq;
using ServiceStack.Text.Controller;
namespace MediaBrowser.Api.ScheduledTasks
{
@ -205,7 +205,7 @@ namespace MediaBrowser.Api.ScheduledTasks
{
// We need to parse this manually because we told service stack not to with IRequiresRequestStream
// https://code.google.com/p/servicestack/source/browse/trunk/Common/ServiceStack.Text/ServiceStack.Text/Controller/PathInfo.cs
var pathInfo = PathInfo.Parse(RequestContext.PathInfo);
var pathInfo = PathInfo.Parse(Request.PathInfo);
var id = new Guid(pathInfo.GetArgumentValue<string>(1));
var task = TaskManager.ScheduledTasks.FirstOrDefault(i => i.Id == id);

@ -7,7 +7,7 @@ using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Search;
using ServiceStack.ServiceHost;
using ServiceStack;
using System;
using System.Collections;
using System.Collections.Generic;

@ -2,7 +2,7 @@
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Session;
using ServiceStack.ServiceHost;
using ServiceStack;
using System;
using System.Collections.Generic;
using System.Linq;

@ -5,7 +5,7 @@ using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Querying;
using ServiceStack.ServiceHost;
using ServiceStack;
using System;
using System.Collections.Generic;
using System.Linq;

@ -6,7 +6,7 @@ using MediaBrowser.Controller.IO;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.System;
using ServiceStack.ServiceHost;
using ServiceStack;
using System;
using System.IO;
using System.Threading.Tasks;

@ -3,7 +3,7 @@ using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using ServiceStack.ServiceHost;
using ServiceStack;
namespace MediaBrowser.Api
{

@ -6,7 +6,7 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying;
using ServiceStack.ServiceHost;
using ServiceStack;
using System;
using System.Collections.Generic;
using System.Linq;

@ -5,7 +5,7 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Querying;
using ServiceStack.ServiceHost;
using ServiceStack;
using System;
using System.Collections.Generic;
using System.Linq;

@ -4,7 +4,7 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Querying;
using ServiceStack.ServiceHost;
using ServiceStack;
using System;
using System.Collections.Generic;
using System.Linq;

@ -2,7 +2,7 @@
using System.Linq;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying;
using ServiceStack.ServiceHost;
using ServiceStack;
using System;
namespace MediaBrowser.Api.UserLibrary

@ -5,7 +5,7 @@ using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying;
using ServiceStack.ServiceHost;
using ServiceStack;
using System;
using System.Collections.Generic;
using System.Linq;

@ -4,7 +4,7 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Querying;
using ServiceStack.ServiceHost;
using ServiceStack;
using System;
using System.Collections.Generic;
using System.Linq;

@ -2,11 +2,11 @@
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using ServiceStack.ServiceHost;
using ServiceStack.Text.Controller;
using ServiceStack;
using System;
using System.Threading;
using System.Threading.Tasks;
using ServiceStack.Text.Controller;
namespace MediaBrowser.Api.UserLibrary
{
@ -158,7 +158,7 @@ namespace MediaBrowser.Api.UserLibrary
/// <param name="request">The request.</param>
public object Post(MarkItemByNameFavorite request)
{
var pathInfo = PathInfo.Parse(RequestContext.PathInfo);
var pathInfo = PathInfo.Parse(Request.PathInfo);
var type = pathInfo.GetArgumentValue<string>(3);
var task = MarkFavorite(request.UserId, type, request.Name, true);
@ -172,7 +172,7 @@ namespace MediaBrowser.Api.UserLibrary
/// <param name="request">The request.</param>
public object Post(UpdateItemByNameRating request)
{
var pathInfo = PathInfo.Parse(RequestContext.PathInfo);
var pathInfo = PathInfo.Parse(Request.PathInfo);
var type = pathInfo.GetArgumentValue<string>(3);
var task = MarkLike(request.UserId, type, request.Name, request.Likes);
@ -186,7 +186,7 @@ namespace MediaBrowser.Api.UserLibrary
/// <param name="request">The request.</param>
public object Delete(UnmarkItemByNameFavorite request)
{
var pathInfo = PathInfo.Parse(RequestContext.PathInfo);
var pathInfo = PathInfo.Parse(Request.PathInfo);
var type = pathInfo.GetArgumentValue<string>(3);
var task = MarkFavorite(request.UserId, type, request.Name, false);
@ -200,7 +200,7 @@ namespace MediaBrowser.Api.UserLibrary
/// <param name="request">The request.</param>
public object Delete(DeleteItemByNameRating request)
{
var pathInfo = PathInfo.Parse(RequestContext.PathInfo);
var pathInfo = PathInfo.Parse(Request.PathInfo);
var type = pathInfo.GetArgumentValue<string>(3);
var task = MarkLike(request.UserId, type, request.Name, null);

@ -10,7 +10,7 @@ using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying;
using ServiceStack.ServiceHost;
using ServiceStack;
using System;
using System.Collections.Generic;
using System.Linq;

@ -5,7 +5,7 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Querying;
using ServiceStack.ServiceHost;
using ServiceStack;
using System;
using System.Collections.Generic;
using System.Linq;

@ -4,7 +4,7 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Querying;
using ServiceStack.ServiceHost;
using ServiceStack;
using System;
using System.Collections.Generic;
using System.Linq;

@ -4,7 +4,7 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Querying;
using ServiceStack.ServiceHost;
using ServiceStack;
using System;
using System.Collections.Generic;
using System.Linq;

@ -1,5 +1,4 @@
using System.Globalization;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
@ -8,9 +7,10 @@ using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying;
using ServiceStack.ServiceHost;
using ServiceStack;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@ -694,7 +694,7 @@ namespace MediaBrowser.Api.UserLibrary
private SessionInfo GetSession()
{
var auth = AuthorizationRequestFilterAttribute.GetAuthorization(RequestContext);
var auth = AuthorizationRequestFilterAttribute.GetAuthorization(Request);
return _sessionManager.Sessions.First(i => string.Equals(i.DeviceId, auth.DeviceId) &&
string.Equals(i.Client, auth.Client) &&

@ -4,7 +4,7 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Querying;
using ServiceStack.ServiceHost;
using ServiceStack;
using System;
using System.Collections.Generic;
using System.Globalization;

@ -4,12 +4,12 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Users;
using ServiceStack.ServiceHost;
using ServiceStack.Text.Controller;
using ServiceStack;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ServiceStack.Text.Controller;
namespace MediaBrowser.Api
{
@ -269,13 +269,13 @@ namespace MediaBrowser.Api
/// Posts the specified request.
/// </summary>
/// <param name="request">The request.</param>
public void Post(AuthenticateUser request)
public async Task Post(AuthenticateUser request)
{
// No response needed. Will throw an exception on failure.
var result = AuthenticateUser(request).Result;
await AuthenticateUser(request).ConfigureAwait(false);
}
public object Post(AuthenticateUserByName request)
public async Task<object> Post(AuthenticateUserByName request)
{
var user = _userManager.Users.FirstOrDefault(i => string.Equals(request.Username, i.Name, StringComparison.OrdinalIgnoreCase));
@ -284,7 +284,7 @@ namespace MediaBrowser.Api
throw new ArgumentException(string.Format("User {0} not found.", request.Username));
}
var result = AuthenticateUser(new AuthenticateUser { Id = user.Id, Password = request.Password }).Result;
var result = await AuthenticateUser(new AuthenticateUser { Id = user.Id, Password = request.Password }).ConfigureAwait(false);
return ToOptimizedResult(result);
}
@ -356,7 +356,7 @@ namespace MediaBrowser.Api
{
// We need to parse this manually because we told service stack not to with IRequiresRequestStream
// https://code.google.com/p/servicestack/source/browse/trunk/Common/ServiceStack.Text/ServiceStack.Text/Controller/PathInfo.cs
var pathInfo = PathInfo.Parse(RequestContext.PathInfo);
var pathInfo = PathInfo.Parse(Request.PathInfo);
var id = new Guid(pathInfo.GetArgumentValue<string>(1));
var dtoUser = request;

@ -2,7 +2,7 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Querying;
using ServiceStack.ServiceHost;
using ServiceStack;
using System;
using System.Linq;

@ -1,6 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="morelinq" version="1.0.16006" targetFramework="net45" />
<package id="ServiceStack.Common" version="3.9.70" targetFramework="net45" />
<package id="ServiceStack.Text" version="3.9.70" targetFramework="net45" />
</packages>

@ -444,11 +444,6 @@ namespace MediaBrowser.Common.Implementations
catch (Exception ex)
{
Logger.Error("Error creating {0}", ex, type.Name);
#if DEBUG
throw;
#endif
// Don't blow up in release mode
return null;
}

@ -37,6 +37,10 @@
<RunPostBuildEvent>Always</RunPostBuildEvent>
</PropertyGroup>
<ItemGroup>
<Reference Include="ServiceStack.Text, Version=3.9.70.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Text.dll</HintPath>
</Reference>
<Reference Include="SharpCompress">
<HintPath>..\packages\sharpcompress.0.10.1.3\lib\net40\SharpCompress.dll</HintPath>
</Reference>
@ -50,9 +54,6 @@
<Reference Include="NLog">
<HintPath>..\packages\NLog.2.1.0\lib\net45\NLog.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.Text">
<HintPath>..\packages\ServiceStack.Text.3.9.70\lib\net35\ServiceStack.Text.dll</HintPath>
</Reference>
<Reference Include="SimpleInjector">
<HintPath>..\packages\SimpleInjector.2.3.6\lib\net40-client\SimpleInjector.dll</HintPath>
</Reference>

@ -166,7 +166,7 @@ namespace MediaBrowser.Common.Implementations.Serialization
/// </summary>
private void Configure()
{
ServiceStack.Text.JsConfig.DateHandler = ServiceStack.Text.JsonDateHandler.ISO8601;
ServiceStack.Text.JsConfig.DateHandler = ServiceStack.Text.DateHandler.ISO8601;
ServiceStack.Text.JsConfig.ExcludeTypeInfo = true;
ServiceStack.Text.JsConfig.IncludeNullValues = false;
ServiceStack.Text.JsConfig.AlwaysUseUtc = true;

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="NLog" version="2.1.0" targetFramework="net45" />
<package id="ServiceStack.Text" version="3.9.70" targetFramework="net45" />
<package id="sharpcompress" version="0.10.1.3" targetFramework="net45" />
<package id="SimpleInjector" version="2.3.6" targetFramework="net45" />
</packages>

@ -38,15 +38,6 @@
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="ServiceStack.Common">
<HintPath>..\packages\ServiceStack.Common.3.9.70\lib\net35\ServiceStack.Common.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.Interfaces">
<HintPath>..\packages\ServiceStack.Common.3.9.70\lib\net35\ServiceStack.Interfaces.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.Text">
<HintPath>..\packages\ServiceStack.Text.3.9.70\lib\net35\ServiceStack.Text.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\SharedVersion.cs">
@ -69,15 +60,11 @@
<Compile Include="Configuration\IApplicationPaths.cs" />
<Compile Include="Net\HttpRequestOptions.cs" />
<Compile Include="Net\HttpResponseInfo.cs" />
<Compile Include="Net\IHasResultFactory.cs" />
<Compile Include="Net\IHttpResultFactory.cs" />
<Compile Include="Net\IServerManager.cs" />
<Compile Include="Net\IWebSocketListener.cs" />
<Compile Include="IApplicationHost.cs" />
<Compile Include="Net\IHttpClient.cs" />
<Compile Include="Net\IHttpServer.cs" />
<Compile Include="Net\INetworkManager.cs" />
<Compile Include="Net\IRestfulService.cs" />
<Compile Include="Net\IWebSocket.cs" />
<Compile Include="Net\IWebSocketConnection.cs" />
<Compile Include="Net\IWebSocketServer.cs" />
@ -105,7 +92,6 @@
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj">

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="ServiceStack.Common" version="3.9.70" targetFramework="net45" />
<package id="ServiceStack.Text" version="3.9.70" targetFramework="net45" />
</packages>

@ -58,6 +58,10 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="ServiceStack.Interfaces, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Data" />
@ -123,6 +127,10 @@
<Compile Include="LiveTv\SeriesTimerInfo.cs" />
<Compile Include="LiveTv\TimerInfo.cs" />
<Compile Include="Localization\ILocalizationManager.cs" />
<Compile Include="Net\IHasResultFactory.cs" />
<Compile Include="Net\IHttpResultFactory.cs" />
<Compile Include="Net\IHttpServer.cs" />
<Compile Include="Net\IRestfulService.cs" />
<Compile Include="Notifications\INotificationsRepository.cs" />
<Compile Include="Notifications\NotificationUpdateEventArgs.cs" />
<Compile Include="Persistence\MediaStreamQuery.cs" />

@ -1,12 +1,13 @@
using ServiceStack.ServiceHost;
using MediaBrowser.Common.Net;
using ServiceStack.Web;
namespace MediaBrowser.Common.Net
namespace MediaBrowser.Controller.Net
{
/// <summary>
/// Interface IHasResultFactory
/// Services that require a ResultFactory should implement this
/// </summary>
public interface IHasResultFactory : IRequiresRequestContext
public interface IHasResultFactory : IRequiresRequest
{
/// <summary>
/// Gets or sets the result factory.

@ -1,10 +1,10 @@
using ServiceStack.ServiceHost;
using System;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using ServiceStack.Web;
namespace MediaBrowser.Common.Net
namespace MediaBrowser.Controller.Net
{
/// <summary>
/// Interface IHttpResultFactory
@ -36,7 +36,7 @@ namespace MediaBrowser.Common.Net
/// <param name="result">The result.</param>
/// <param name="responseHeaders">The response headers.</param>
/// <returns>System.Object.</returns>
object GetOptimizedResult<T>(IRequestContext requestContext, T result, IDictionary<string, string> responseHeaders = null)
object GetOptimizedResult<T>(IRequest requestContext, T result, IDictionary<string, string> responseHeaders = null)
where T : class;
/// <summary>
@ -50,7 +50,7 @@ namespace MediaBrowser.Common.Net
/// <param name="factoryFn">The factory function that creates the response object.</param>
/// <param name="responseHeaders">The response headers.</param>
/// <returns>System.Object.</returns>
object GetOptimizedResultUsingCache<T>(IRequestContext requestContext, Guid cacheKey, DateTime lastDateModified, TimeSpan? cacheDuration, Func<T> factoryFn, IDictionary<string, string> responseHeaders = null)
object GetOptimizedResultUsingCache<T>(IRequest requestContext, Guid cacheKey, DateTime lastDateModified, TimeSpan? cacheDuration, Func<T> factoryFn, IDictionary<string, string> responseHeaders = null)
where T : class;
/// <summary>
@ -65,7 +65,7 @@ namespace MediaBrowser.Common.Net
/// <param name="contentType">Type of the content.</param>
/// <param name="responseHeaders">The response headers.</param>
/// <returns>System.Object.</returns>
object GetCachedResult<T>(IRequestContext requestContext, Guid cacheKey, DateTime lastDateModified, TimeSpan? cacheDuration, Func<T> factoryFn, string contentType, IDictionary<string, string> responseHeaders = null)
object GetCachedResult<T>(IRequest requestContext, Guid cacheKey, DateTime lastDateModified, TimeSpan? cacheDuration, Func<T> factoryFn, string contentType, IDictionary<string, string> responseHeaders = null)
where T : class;
/// <summary>
@ -80,7 +80,7 @@ namespace MediaBrowser.Common.Net
/// <param name="responseHeaders">The response headers.</param>
/// <param name="isHeadRequest">if set to <c>true</c> [is head request].</param>
/// <returns>System.Object.</returns>
object GetStaticResult(IRequestContext requestContext, Guid cacheKey, DateTime? lastDateModified,
object GetStaticResult(IRequest requestContext, Guid cacheKey, DateTime? lastDateModified,
TimeSpan? cacheDuration, string contentType, Func<Task<Stream>> factoryFn,
IDictionary<string, string> responseHeaders = null, bool isHeadRequest = false);
@ -93,6 +93,6 @@ namespace MediaBrowser.Common.Net
/// <param name="responseHeaders">The response headers.</param>
/// <param name="isHeadRequest">if set to <c>true</c> [is head request].</param>
/// <returns>System.Object.</returns>
object GetStaticFileResult(IRequestContext requestContext, string path, FileShare fileShare = FileShare.Read, IDictionary<string, string> responseHeaders = null, bool isHeadRequest = false);
object GetStaticFileResult(IRequest requestContext, string path, FileShare fileShare = FileShare.Read, IDictionary<string, string> responseHeaders = null, bool isHeadRequest = false);
}
}

@ -1,7 +1,8 @@
using MediaBrowser.Common.Net;
using System;
using System.Collections.Generic;
namespace MediaBrowser.Common.Net
namespace MediaBrowser.Controller.Net
{
/// <summary>
/// Interface IHttpServer
@ -18,7 +19,7 @@ namespace MediaBrowser.Common.Net
/// Starts the specified server name.
/// </summary>
/// <param name="urlPrefix">The URL.</param>
void Start(string urlPrefix);
void StartServer(string urlPrefix);
/// <summary>
/// Gets a value indicating whether [supports web sockets].

@ -1,6 +1,6 @@
using ServiceStack.ServiceHost;
using ServiceStack;
namespace MediaBrowser.Common.Net
namespace MediaBrowser.Controller.Net
{
/// <summary>
/// Interface IRestfulService

@ -1,5 +1,6 @@
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Plugins;
using MediaBrowser.Model.Logging;
using MediaBrowser.Server.Implementations.Udp;

@ -0,0 +1,53 @@
using MediaBrowser.Common;
using ServiceStack.Configuration;
namespace MediaBrowser.Server.Implementations.HttpServer
{
/// <summary>
/// Class ContainerAdapter
/// </summary>
class ContainerAdapter : IContainerAdapter, IRelease
{
/// <summary>
/// The _app host
/// </summary>
private readonly IApplicationHost _appHost;
/// <summary>
/// Initializes a new instance of the <see cref="ContainerAdapter" /> class.
/// </summary>
/// <param name="appHost">The app host.</param>
public ContainerAdapter(IApplicationHost appHost)
{
_appHost = appHost;
}
/// <summary>
/// Resolves this instance.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns>``0.</returns>
public T Resolve<T>()
{
return _appHost.Resolve<T>();
}
/// <summary>
/// Tries the resolve.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns>``0.</returns>
public T TryResolve<T>()
{
return _appHost.TryResolve<T>();
}
/// <summary>
/// Releases the specified instance.
/// </summary>
/// <param name="instance">The instance.</param>
public void Release(object instance)
{
// Leave this empty so SS doesn't try to dispose our objects
}
}
}

@ -0,0 +1,533 @@
using Funq;
using MediaBrowser.Common;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Logging;
using ServiceStack;
using ServiceStack.Configuration;
using ServiceStack.Host;
using ServiceStack.Host.Handlers;
using ServiceStack.Host.HttpListener;
using ServiceStack.Logging;
using ServiceStack.Web;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.HttpServer
{
public delegate void DelReceiveWebRequest(HttpListenerContext context);
public class HttpListenerHost : ServiceStackHost, IHttpServer
{
private string ServerName { get; set; }
private string HandlerPath { get; set; }
private string DefaultRedirectPath { get; set; }
private readonly ILogger _logger;
public string UrlPrefix { get; private set; }
private readonly List<IRestfulService> _restServices = new List<IRestfulService>();
private HttpListener Listener { get; set; }
protected bool IsStarted = false;
private readonly List<AutoResetEvent> _autoResetEvents = new List<AutoResetEvent>();
private readonly ContainerAdapter _containerAdapter;
private readonly ConcurrentDictionary<string, string> _localEndPoints = new ConcurrentDictionary<string, string>(StringComparer.OrdinalIgnoreCase);
public event EventHandler<WebSocketConnectEventArgs> WebSocketConnected;
/// <summary>
/// Gets the local end points.
/// </summary>
/// <value>The local end points.</value>
public IEnumerable<string> LocalEndPoints
{
get { return _localEndPoints.Keys.ToList(); }
}
public HttpListenerHost(IApplicationHost applicationHost, ILogManager logManager, string serviceName, string handlerPath, string defaultRedirectPath, params Assembly[] assembliesWithServices)
: base(serviceName, assembliesWithServices)
{
// https://github.com/ServiceStack/ServiceStack/blob/master/tests/ServiceStack.WebHost.IntegrationTests/Web.config#L4
Licensing.RegisterLicense("1001-e1JlZjoxMDAxLE5hbWU6VGVzdCBCdXNpbmVzcyxUeXBlOkJ1c2luZXNzLEhhc2g6UHVNTVRPclhvT2ZIbjQ5MG5LZE1mUTd5RUMzQnBucTFEbTE3TDczVEF4QUNMT1FhNXJMOWkzVjFGL2ZkVTE3Q2pDNENqTkQyUktRWmhvUVBhYTBiekJGUUZ3ZE5aZHFDYm9hL3lydGlwUHI5K1JsaTBYbzNsUC85cjVJNHE5QVhldDN6QkE4aTlvdldrdTgyTk1relY2eis2dFFqTThYN2lmc0JveHgycFdjPSxFeHBpcnk6MjAxMy0wMS0wMX0=");
DefaultRedirectPath = defaultRedirectPath;
ServerName = serviceName;
HandlerPath = handlerPath;
_logger = logManager.GetLogger("HttpServer");
LogManager.LogFactory = new ServerLogFactory(logManager);
_containerAdapter = new ContainerAdapter(applicationHost);
for (var i = 0; i < 2; i++)
{
_autoResetEvents.Add(new AutoResetEvent(false));
}
}
public override void Configure(Container container)
{
HostConfig.Instance.DefaultRedirectPath = DefaultRedirectPath;
HostConfig.Instance.MapExceptionToStatusCode = new Dictionary<Type, int>
{
{typeof (InvalidOperationException), 422},
{typeof (ResourceNotFoundException), 404},
{typeof (FileNotFoundException), 404},
{typeof (DirectoryNotFoundException), 404}
};
HostConfig.Instance.DebugMode = true;
HostConfig.Instance.LogFactory = LogManager.LogFactory;
// The Markdown feature causes slow startup times (5 mins+) on cold boots for some users
// Custom format allows images
HostConfig.Instance.EnableFeatures = Feature.Csv | Feature.Html | Feature.Json | Feature.Jsv | Feature.Metadata | Feature.Xml | Feature.CustomFormat;
container.Adapter = _containerAdapter;
//Plugins.Add(new SwaggerFeature());
Plugins.Add(new CorsFeature());
HostContext.GlobalResponseFilters.Add(new ResponseFilter(_logger).FilterResponse);
}
public override void OnAfterInit()
{
SetAppDomainData();
base.OnAfterInit();
}
public override void OnConfigLoad()
{
base.OnConfigLoad();
Config.HandlerFactoryPath = string.IsNullOrEmpty(HandlerPath)
? null
: HandlerPath;
Config.MetadataRedirectPath = string.IsNullOrEmpty(HandlerPath)
? "metadata"
: PathUtils.CombinePaths(HandlerPath, "metadata");
}
protected override ServiceController CreateServiceController(params Assembly[] assembliesWithServices)
{
var types = _restServices.Select(r => r.GetType()).ToArray();
return new ServiceController(this, () => types);
}
public virtual void SetAppDomainData()
{
//Required for Mono to resolve VirtualPathUtility and Url.Content urls
var domain = Thread.GetDomain(); // or AppDomain.Current
domain.SetData(".appDomain", "1");
domain.SetData(".appVPath", "/");
domain.SetData(".appPath", domain.BaseDirectory);
if (string.IsNullOrEmpty(domain.GetData(".appId") as string))
{
domain.SetData(".appId", "1");
}
if (string.IsNullOrEmpty(domain.GetData(".domainId") as string))
{
domain.SetData(".domainId", "1");
}
}
public override ServiceStackHost Start(string listeningAtUrlBase)
{
StartListener(listeningAtUrlBase);
return this;
}
/// <summary>
/// Starts the Web Service
/// </summary>
/// <param name="listeningAtUrlBase">
/// A Uri that acts as the base that the server is listening on.
/// Format should be: http://127.0.0.1:8080/ or http://127.0.0.1:8080/somevirtual/
/// Note: the trailing slash is required! For more info see the
/// HttpListener.Prefixes property on MSDN.
/// </param>
protected void StartListener(string listeningAtUrlBase)
{
// *** Already running - just leave it in place
if (IsStarted)
return;
if (Listener == null)
Listener = new HttpListener();
HostContext.Config.HandlerFactoryPath = ListenerRequest.GetHandlerPathIfAny(listeningAtUrlBase);
UrlPrefix = listeningAtUrlBase;
Listener.Prefixes.Add(listeningAtUrlBase);
_logger.Info("Adding HttpListener Prefixes");
Listener.Prefixes.Add(listeningAtUrlBase);
IsStarted = true;
_logger.Info("Starting HttpListner");
Listener.Start();
for (var i = 0; i < _autoResetEvents.Count; i++)
{
var index = i;
ThreadPool.QueueUserWorkItem(o => Listen(o, index));
}
}
private bool IsListening
{
get { return this.IsStarted && this.Listener != null && this.Listener.IsListening; }
}
// Loop here to begin processing of new requests.
private void Listen(object state, int index)
{
while (IsListening)
{
if (Listener == null) return;
try
{
Listener.BeginGetContext(c => ListenerCallback(c, index), Listener);
_autoResetEvents[index].WaitOne();
}
catch (Exception ex)
{
_logger.Error("Listen()", ex);
return;
}
if (Listener == null) return;
}
}
// Handle the processing of a request in here.
private void ListenerCallback(IAsyncResult asyncResult, int index)
{
var listener = asyncResult.AsyncState as HttpListener;
HttpListenerContext context = null;
if (listener == null) return;
try
{
if (!IsListening)
{
_logger.Debug("Ignoring ListenerCallback() as HttpListener is no longer listening");
return;
}
// The EndGetContext() method, as with all Begin/End asynchronous methods in the .NET Framework,
// blocks until there is a request to be processed or some type of data is available.
context = listener.EndGetContext(asyncResult);
}
catch (Exception ex)
{
// You will get an exception when httpListener.Stop() is called
// because there will be a thread stopped waiting on the .EndGetContext()
// method, and again, that is just the way most Begin/End asynchronous
// methods of the .NET Framework work.
var errMsg = ex + ": " + IsListening;
_logger.Warn(errMsg);
return;
}
finally
{
// Once we know we have a request (or exception), we signal the other thread
// so that it calls the BeginGetContext() (or possibly exits if we're not
// listening any more) method to start handling the next incoming request
// while we continue to process this request on a different thread.
_autoResetEvents[index].Set();
}
if (context == null) return;
var date = DateTime.Now;
Task.Factory.StartNew(async () =>
{
try
{
LogHttpRequest(context, index);
if (context.Request.IsWebSocketRequest)
{
ProcessWebSocketRequest(context);
return;
}
var localPath = context.Request.Url.LocalPath;
if (string.Equals(localPath, "/mediabrowser/", StringComparison.OrdinalIgnoreCase))
{
context.Response.Redirect(DefaultRedirectPath);
context.Response.Close();
return;
}
if (string.Equals(localPath, "/mediabrowser", StringComparison.OrdinalIgnoreCase))
{
context.Response.Redirect("mediabrowser/" + DefaultRedirectPath);
context.Response.Close();
return;
}
if (string.Equals(localPath, "/", StringComparison.OrdinalIgnoreCase))
{
context.Response.Redirect("mediabrowser/" + DefaultRedirectPath);
context.Response.Close();
return;
}
if (string.IsNullOrEmpty(localPath))
{
context.Response.Redirect("/mediabrowser/" + DefaultRedirectPath);
context.Response.Close();
return;
}
var url = context.Request.Url.ToString();
var endPoint = context.Request.RemoteEndPoint;
await ProcessRequestAsync(context).ConfigureAwait(false);
var duration = DateTime.Now - date;
if (EnableHttpRequestLogging)
{
LoggerUtils.LogResponse(_logger, context, url, endPoint, duration);
}
}
catch (Exception ex)
{
_logger.ErrorException("ProcessRequest failure", ex);
HandleError(ex, context, _logger);
}
});
}
/// <summary>
/// Logs the HTTP request.
/// </summary>
/// <param name="ctx">The CTX.</param>
private void LogHttpRequest(HttpListenerContext ctx, int index)
{
var endpoint = ctx.Request.LocalEndPoint;
if (endpoint != null)
{
var address = endpoint.ToString();
_localEndPoints.GetOrAdd(address, address);
}
if (EnableHttpRequestLogging)
{
LoggerUtils.LogRequest(_logger, ctx, index);
}
}
/// <summary>
/// Processes the web socket request.
/// </summary>
/// <param name="ctx">The CTX.</param>
/// <returns>Task.</returns>
private async Task ProcessWebSocketRequest(HttpListenerContext ctx)
{
#if !__MonoCS__
try
{
var webSocketContext = await ctx.AcceptWebSocketAsync(null).ConfigureAwait(false);
if (WebSocketConnected != null)
{
WebSocketConnected(this, new WebSocketConnectEventArgs { WebSocket = new NativeWebSocket(webSocketContext.WebSocket, _logger), Endpoint = ctx.Request.RemoteEndPoint.ToString() });
}
}
catch (Exception ex)
{
_logger.ErrorException("AcceptWebSocketAsync error", ex);
ctx.Response.StatusCode = 500;
ctx.Response.Close();
}
#endif
}
public static void HandleError(Exception ex, HttpListenerContext context, ILogger logger)
{
try
{
var errorResponse = new ErrorResponse
{
ResponseStatus = new ResponseStatus
{
ErrorCode = ex.GetType().GetOperationName(),
Message = ex.Message,
StackTrace = ex.StackTrace,
}
};
var operationName = context.Request.GetOperationName();
var httpReq = context.ToRequest(operationName);
var httpRes = httpReq.Response;
var contentType = httpReq.ResponseContentType;
var serializer = HostContext.ContentTypes.GetResponseSerializer(contentType);
if (serializer == null)
{
contentType = HostContext.Config.DefaultContentType;
serializer = HostContext.ContentTypes.GetResponseSerializer(contentType);
}
var httpError = ex as IHttpError;
if (httpError != null)
{
httpRes.StatusCode = httpError.Status;
httpRes.StatusDescription = httpError.StatusDescription;
}
else
{
httpRes.StatusCode = 500;
}
httpRes.ContentType = contentType;
serializer(httpReq, errorResponse, httpRes);
httpRes.Close();
}
catch (Exception errorEx)
{
logger.ErrorException("Error this.ProcessRequest(context)(Exception while writing error to the response)", errorEx);
}
}
/// <summary>
/// Shut down the Web Service
/// </summary>
public void Stop()
{
if (Listener != null)
{
Listener.Prefixes.Remove(UrlPrefix);
Listener.Close();
}
}
/// <summary>
/// Overridable method that can be used to implement a custom hnandler
/// </summary>
/// <param name="context"></param>
protected Task ProcessRequestAsync(HttpListenerContext context)
{
if (string.IsNullOrEmpty(context.Request.RawUrl))
return ((object)null).AsTaskResult();
var operationName = context.Request.GetOperationName();
var httpReq = context.ToRequest(operationName);
var httpRes = httpReq.Response;
var handler = HttpHandlerFactory.GetHandler(httpReq);
var serviceStackHandler = handler as IServiceStackHandler;
if (serviceStackHandler != null)
{
var restHandler = serviceStackHandler as RestHandler;
if (restHandler != null)
{
httpReq.OperationName = operationName = restHandler.RestPath.RequestType.GetOperationName();
}
var task = serviceStackHandler.ProcessRequestAsync(httpReq, httpRes, operationName);
task.ContinueWith(x => httpRes.Close());
return task;
}
return new NotImplementedException("Cannot execute handler: " + handler + " at PathInfo: " + httpReq.PathInfo)
.AsTaskException();
}
/// <summary>
/// Gets or sets a value indicating whether [enable HTTP request logging].
/// </summary>
/// <value><c>true</c> if [enable HTTP request logging]; otherwise, <c>false</c>.</value>
public bool EnableHttpRequestLogging { get; set; }
/// <summary>
/// Adds the rest handlers.
/// </summary>
/// <param name="services">The services.</param>
public void Init(IEnumerable<IRestfulService> services)
{
_restServices.AddRange(services);
ServiceController = CreateServiceController();
_logger.Info("Calling ServiceStack AppHost.Init");
Init();
}
/// <summary>
/// Releases the specified instance.
/// </summary>
/// <param name="instance">The instance.</param>
public override void Release(object instance)
{
// Leave this empty so SS doesn't try to dispose our objects
}
private bool _disposed;
private readonly object _disposeLock = new object();
protected virtual void Dispose(bool disposing)
{
if (_disposed) return;
base.Dispose();
lock (_disposeLock)
{
if (_disposed) return;
if (disposing)
{
Stop();
}
//release unmanaged resources here...
_disposed = true;
}
}
public override void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
public void StartServer(string urlPrefix)
{
Start(urlPrefix);
}
public bool SupportsWebSockets
{
get { return NativeWebSocket.IsSupported; }
}
}
}

@ -2,10 +2,8 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Logging;
using ServiceStack.Common;
using ServiceStack.Common.Web;
using ServiceStack.ServiceHost;
using System;
using System.Collections.Generic;
using System.Globalization;
@ -13,6 +11,8 @@ using System.IO;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using ServiceStack;
using ServiceStack.Web;
using MimeTypes = MediaBrowser.Common.Net.MimeTypes;
namespace MediaBrowser.Server.Implementations.HttpServer
@ -116,7 +116,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
/// <param name="responseHeaders">The response headers.</param>
/// <returns>System.Object.</returns>
/// <exception cref="System.ArgumentNullException">result</exception>
public object GetOptimizedResult<T>(IRequestContext requestContext, T result, IDictionary<string, string> responseHeaders = null)
public object GetOptimizedResult<T>(IRequest requestContext, T result, IDictionary<string, string> responseHeaders = null)
where T : class
{
if (result == null)
@ -156,7 +156,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
/// or
/// factoryFn
/// </exception>
public object GetOptimizedResultUsingCache<T>(IRequestContext requestContext, Guid cacheKey, DateTime lastDateModified, TimeSpan? cacheDuration, Func<T> factoryFn, IDictionary<string, string> responseHeaders = null)
public object GetOptimizedResultUsingCache<T>(IRequest requestContext, Guid cacheKey, DateTime lastDateModified, TimeSpan? cacheDuration, Func<T> factoryFn, IDictionary<string, string> responseHeaders = null)
where T : class
{
if (cacheKey == Guid.Empty)
@ -199,7 +199,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
/// <param name="responseHeaders">The response headers.</param>
/// <returns>System.Object.</returns>
/// <exception cref="System.ArgumentNullException">cacheKey</exception>
public object GetCachedResult<T>(IRequestContext requestContext, Guid cacheKey, DateTime lastDateModified, TimeSpan? cacheDuration, Func<T> factoryFn, string contentType, IDictionary<string, string> responseHeaders = null)
public object GetCachedResult<T>(IRequest requestContext, Guid cacheKey, DateTime lastDateModified, TimeSpan? cacheDuration, Func<T> factoryFn, string contentType, IDictionary<string, string> responseHeaders = null)
where T : class
{
if (cacheKey == Guid.Empty)
@ -256,7 +256,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
/// <param name="cacheDuration">Duration of the cache.</param>
/// <param name="contentType">Type of the content.</param>
/// <returns>System.Object.</returns>
private object GetCachedResult(IRequestContext requestContext, IDictionary<string, string> responseHeaders, Guid cacheKey, string cacheKeyString, DateTime? lastDateModified, TimeSpan? cacheDuration, string contentType)
private object GetCachedResult(IRequest requestContext, IDictionary<string, string> responseHeaders, Guid cacheKey, string cacheKeyString, DateTime? lastDateModified, TimeSpan? cacheDuration, string contentType)
{
responseHeaders["ETag"] = cacheKeyString;
@ -287,7 +287,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
/// <param name="isHeadRequest">if set to <c>true</c> [is head request].</param>
/// <returns>System.Object.</returns>
/// <exception cref="System.ArgumentNullException">path</exception>
public object GetStaticFileResult(IRequestContext requestContext, string path, FileShare fileShare = FileShare.Read, IDictionary<string, string> responseHeaders = null, bool isHeadRequest = false)
public object GetStaticFileResult(IRequest requestContext, string path, FileShare fileShare = FileShare.Read, IDictionary<string, string> responseHeaders = null, bool isHeadRequest = false)
{
if (string.IsNullOrEmpty(path))
{
@ -332,7 +332,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
/// <exception cref="System.ArgumentNullException">cacheKey
/// or
/// factoryFn</exception>
public object GetStaticResult(IRequestContext requestContext, Guid cacheKey, DateTime? lastDateModified, TimeSpan? cacheDuration, string contentType, Func<Task<Stream>> factoryFn, IDictionary<string, string> responseHeaders = null, bool isHeadRequest = false)
public object GetStaticResult(IRequest requestContext, Guid cacheKey, DateTime? lastDateModified, TimeSpan? cacheDuration, string contentType, Func<Task<Stream>> factoryFn, IDictionary<string, string> responseHeaders = null, bool isHeadRequest = false)
{
if (cacheKey == Guid.Empty)
{
@ -373,7 +373,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
/// <param name="requestContext">The request context.</param>
/// <param name="contentType">Type of the content.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
private bool ShouldCompressResponse(IRequestContext requestContext, string contentType)
private bool ShouldCompressResponse(IRequest requestContext, string contentType)
{
// It will take some work to support compression with byte range requests
if (!string.IsNullOrEmpty(requestContext.GetHeader("Range")))
@ -428,9 +428,11 @@ namespace MediaBrowser.Server.Implementations.HttpServer
/// <param name="compress">if set to <c>true</c> [compress].</param>
/// <param name="isHeadRequest">if set to <c>true</c> [is head request].</param>
/// <returns>Task{IHasOptions}.</returns>
private async Task<IHasOptions> GetStaticResult(IRequestContext requestContext, IDictionary<string, string> responseHeaders, string contentType, Func<Task<Stream>> factoryFn, bool compress, bool isHeadRequest)
private async Task<IHasOptions> GetStaticResult(IRequest requestContext, IDictionary<string, string> responseHeaders, string contentType, Func<Task<Stream>> factoryFn, bool compress, bool isHeadRequest)
{
if (!compress || string.IsNullOrEmpty(requestContext.CompressionType))
var requestedCompressionType = requestContext.GetCompressionType();
if (!compress || string.IsNullOrEmpty(requestedCompressionType))
{
var stream = await factoryFn().ConfigureAwait(false);
@ -471,9 +473,9 @@ namespace MediaBrowser.Server.Implementations.HttpServer
return new HttpResult(content, contentType);
}
var contents = content.Compress(requestContext.CompressionType);
var contents = content.Compress(requestedCompressionType);
return new CompressedResult(contents, requestContext.CompressionType, contentType);
return new CompressedResult(contents, requestedCompressionType, contentType);
}
/// <summary>
@ -548,7 +550,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
/// <param name="lastDateModified">The last date modified.</param>
/// <param name="cacheDuration">Duration of the cache.</param>
/// <returns><c>true</c> if [is not modified] [the specified cache key]; otherwise, <c>false</c>.</returns>
private bool IsNotModified(IRequestContext requestContext, Guid? cacheKey, DateTime? lastDateModified, TimeSpan? cacheDuration)
private bool IsNotModified(IRequest requestContext, Guid? cacheKey, DateTime? lastDateModified, TimeSpan? cacheDuration)
{
var isNotModified = true;

@ -1,642 +0,0 @@
using Funq;
using MediaBrowser.Common;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Net;
using MediaBrowser.Model.Logging;
using ServiceStack.Api.Swagger;
using ServiceStack.Common.Web;
using ServiceStack.Configuration;
using ServiceStack.Logging;
using ServiceStack.ServiceHost;
using ServiceStack.ServiceInterface.Cors;
using ServiceStack.Text;
using ServiceStack.WebHost.Endpoints;
using ServiceStack.WebHost.Endpoints.Extensions;
using ServiceStack.WebHost.Endpoints.Support;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.WebSockets;
using System.Reactive.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.HttpServer
{
/// <summary>
/// Class HttpServer
/// </summary>
public class HttpServer : HttpListenerBase, IHttpServer
{
/// <summary>
/// The logger
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// Gets the URL prefix.
/// </summary>
/// <value>The URL prefix.</value>
public string UrlPrefix { get; private set; }
/// <summary>
/// The _rest services
/// </summary>
private readonly List<IRestfulService> _restServices = new List<IRestfulService>();
/// <summary>
/// This subscribes to HttpListener requests and finds the appropriate BaseHandler to process it
/// </summary>
/// <value>The HTTP listener.</value>
private IDisposable HttpListener { get; set; }
/// <summary>
/// Occurs when [web socket connected].
/// </summary>
public event EventHandler<WebSocketConnectEventArgs> WebSocketConnected;
/// <summary>
/// Gets the default redirect path.
/// </summary>
/// <value>The default redirect path.</value>
private string DefaultRedirectPath { get; set; }
/// <summary>
/// Gets or sets the name of the server.
/// </summary>
/// <value>The name of the server.</value>
private string ServerName { get; set; }
/// <summary>
/// The _container adapter
/// </summary>
private readonly ContainerAdapter _containerAdapter;
private readonly ConcurrentDictionary<string, string> _localEndPoints = new ConcurrentDictionary<string, string>(StringComparer.OrdinalIgnoreCase);
/// <summary>
/// Gets the local end points.
/// </summary>
/// <value>The local end points.</value>
public IEnumerable<string> LocalEndPoints
{
get { return _localEndPoints.Keys.ToList(); }
}
/// <summary>
/// Initializes a new instance of the <see cref="HttpServer" /> class.
/// </summary>
/// <param name="applicationHost">The application host.</param>
/// <param name="logManager">The log manager.</param>
/// <param name="serverName">Name of the server.</param>
/// <param name="defaultRedirectpath">The default redirectpath.</param>
/// <exception cref="System.ArgumentNullException">urlPrefix</exception>
public HttpServer(IApplicationHost applicationHost, ILogManager logManager, string serverName, string defaultRedirectpath)
: base()
{
if (logManager == null)
{
throw new ArgumentNullException("logManager");
}
if (applicationHost == null)
{
throw new ArgumentNullException("applicationHost");
}
if (string.IsNullOrEmpty(serverName))
{
throw new ArgumentNullException("serverName");
}
if (string.IsNullOrEmpty(defaultRedirectpath))
{
throw new ArgumentNullException("defaultRedirectpath");
}
ServerName = serverName;
DefaultRedirectPath = defaultRedirectpath;
_logger = logManager.GetLogger("HttpServer");
LogManager.LogFactory = new ServerLogFactory(logManager);
EndpointHostConfig.Instance.ServiceStackHandlerFactoryPath = null;
EndpointHostConfig.Instance.MetadataRedirectPath = "metadata";
_containerAdapter = new ContainerAdapter(applicationHost);
}
/// <summary>
/// The us culture
/// </summary>
protected static readonly CultureInfo UsCulture = new CultureInfo("en-US");
/// <summary>
/// Configures the specified container.
/// </summary>
/// <param name="container">The container.</param>
public override void Configure(Container container)
{
JsConfig.DateHandler = JsonDateHandler.ISO8601;
JsConfig.ExcludeTypeInfo = true;
JsConfig.IncludeNullValues = false;
SetConfig(new EndpointHostConfig
{
DefaultRedirectPath = DefaultRedirectPath,
MapExceptionToStatusCode = {
{ typeof(InvalidOperationException), 422 },
{ typeof(ResourceNotFoundException), 404 },
{ typeof(FileNotFoundException), 404 },
{ typeof(DirectoryNotFoundException), 404 }
},
DebugMode = true,
ServiceName = ServerName,
LogFactory = LogManager.LogFactory,
// The Markdown feature causes slow startup times (5 mins+) on cold boots for some users
// Custom format allows images
EnableFeatures = Feature.Csv | Feature.Html | Feature.Json | Feature.Jsv | Feature.Metadata | Feature.Xml | Feature.CustomFormat
});
container.Adapter = _containerAdapter;
Plugins.Add(new SwaggerFeature());
Plugins.Add(new CorsFeature());
ResponseFilters.Add(FilterResponse);
}
/// <summary>
/// Filters the response.
/// </summary>
/// <param name="req">The req.</param>
/// <param name="res">The res.</param>
/// <param name="dto">The dto.</param>
private void FilterResponse(IHttpRequest req, IHttpResponse res, object dto)
{
// Try to prevent compatibility view
res.AddHeader("X-UA-Compatible", "IE=Edge");
var exception = dto as Exception;
if (exception != null)
{
_logger.ErrorException("Error processing request for {0}", exception, req.RawUrl);
if (!string.IsNullOrEmpty(exception.Message))
{
var error = exception.Message.Replace(Environment.NewLine, " ");
error = RemoveControlCharacters(error);
res.AddHeader("X-Application-Error-Code", error);
}
}
if (dto is CompressedResult)
{
// Per Google PageSpeed
// This instructs the proxies to cache two versions of the resource: one compressed, and one uncompressed.
// The correct version of the resource is delivered based on the client request header.
// This is a good choice for applications that are singly homed and depend on public proxies for user locality.
res.AddHeader("Vary", "Accept-Encoding");
}
var hasOptions = dto as IHasOptions;
if (hasOptions != null)
{
// Content length has to be explicitly set on on HttpListenerResponse or it won't be happy
string contentLength;
if (hasOptions.Options.TryGetValue("Content-Length", out contentLength) && !string.IsNullOrEmpty(contentLength))
{
var length = long.Parse(contentLength, UsCulture);
if (length > 0)
{
var response = (HttpListenerResponse)res.OriginalResponse;
response.ContentLength64 = length;
// Disable chunked encoding. Technically this is only needed when using Content-Range, but
// anytime we know the content length there's no need for it
response.SendChunked = false;
}
}
}
}
/// <summary>
/// Removes the control characters.
/// </summary>
/// <param name="inString">The in string.</param>
/// <returns>System.String.</returns>
private static string RemoveControlCharacters(string inString)
{
if (inString == null) return null;
var newString = new StringBuilder();
foreach (var ch in inString)
{
if (!char.IsControl(ch))
{
newString.Append(ch);
}
}
return newString.ToString();
}
/// <summary>
/// Starts the Web Service
/// </summary>
/// <param name="urlBase">A Uri that acts as the base that the server is listening on.
/// Format should be: http://127.0.0.1:8080/ or http://127.0.0.1:8080/somevirtual/
/// Note: the trailing slash is required! For more info see the
/// HttpListener.Prefixes property on MSDN.</param>
/// <exception cref="System.ArgumentNullException">urlBase</exception>
public override void Start(string urlBase)
{
if (string.IsNullOrEmpty(urlBase))
{
throw new ArgumentNullException("urlBase");
}
// *** Already running - just leave it in place
if (IsStarted)
{
return;
}
if (Listener == null)
{
_logger.Info("Creating HttpListner");
Listener = new HttpListener();
}
EndpointHost.Config.ServiceStackHandlerFactoryPath = HttpListenerRequestWrapper.GetHandlerPathIfAny(urlBase);
UrlPrefix = urlBase;
_logger.Info("Adding HttpListener Prefixes");
Listener.Prefixes.Add(urlBase);
IsStarted = true;
_logger.Info("Starting HttpListner");
Listener.Start();
_logger.Info("Creating HttpListner observable stream");
HttpListener = CreateObservableStream().Subscribe(ProcessHttpRequestAsync);
}
/// <summary>
/// Creates the observable stream.
/// </summary>
/// <returns>IObservable{HttpListenerContext}.</returns>
private IObservable<HttpListenerContext> CreateObservableStream()
{
return Observable.Create<HttpListenerContext>(obs =>
Observable.FromAsync(() => Listener.GetContextAsync())
.Subscribe(obs))
.Repeat()
.Retry()
.Publish()
.RefCount();
}
/// <summary>
/// Processes incoming http requests by routing them to the appropiate handler
/// </summary>
/// <param name="context">The CTX.</param>
private async void ProcessHttpRequestAsync(HttpListenerContext context)
{
var date = DateTime.Now;
LogHttpRequest(context);
if (context.Request.IsWebSocketRequest)
{
await ProcessWebSocketRequest(context).ConfigureAwait(false);
return;
}
var localPath = context.Request.Url.LocalPath;
if (string.Equals(localPath, "/mediabrowser/", StringComparison.OrdinalIgnoreCase))
{
context.Response.Redirect(DefaultRedirectPath);
context.Response.Close();
return;
}
if (string.Equals(localPath, "/mediabrowser", StringComparison.OrdinalIgnoreCase))
{
context.Response.Redirect("mediabrowser/" + DefaultRedirectPath);
context.Response.Close();
return;
}
if (string.Equals(localPath, "/", StringComparison.OrdinalIgnoreCase))
{
context.Response.Redirect("mediabrowser/" + DefaultRedirectPath);
context.Response.Close();
return;
}
if (string.IsNullOrEmpty(localPath))
{
context.Response.Redirect("/mediabrowser/" + DefaultRedirectPath);
context.Response.Close();
return;
}
RaiseReceiveWebRequest(context);
await Task.Factory.StartNew(() =>
{
try
{
var url = context.Request.Url.ToString();
var endPoint = context.Request.RemoteEndPoint;
ProcessRequest(context);
var duration = DateTime.Now - date;
LogResponse(context, url, endPoint, duration);
}
catch (Exception ex)
{
_logger.ErrorException("ProcessRequest failure", ex);
}
}).ConfigureAwait(false);
}
/// <summary>
/// Processes the web socket request.
/// </summary>
/// <param name="ctx">The CTX.</param>
/// <returns>Task.</returns>
private async Task ProcessWebSocketRequest(HttpListenerContext ctx)
{
#if __MonoCS__
#else
try
{
var webSocketContext = await ctx.AcceptWebSocketAsync(null).ConfigureAwait(false);
if (WebSocketConnected != null)
{
WebSocketConnected(this, new WebSocketConnectEventArgs { WebSocket = new NativeWebSocket(webSocketContext.WebSocket, _logger), Endpoint = ctx.Request.RemoteEndPoint.ToString() });
}
}
catch (Exception ex)
{
_logger.ErrorException("AcceptWebSocketAsync error", ex);
ctx.Response.StatusCode = 500;
ctx.Response.Close();
}
#endif
}
/// <summary>
/// Logs the HTTP request.
/// </summary>
/// <param name="ctx">The CTX.</param>
private void LogHttpRequest(HttpListenerContext ctx)
{
var endpoint = ctx.Request.LocalEndPoint;
if (endpoint != null)
{
var address = endpoint.ToString();
_localEndPoints.GetOrAdd(address, address);
}
if (EnableHttpRequestLogging)
{
var log = new StringBuilder();
log.AppendLine("Url: " + ctx.Request.Url);
log.AppendLine("Headers: " + string.Join(",", ctx.Request.Headers.AllKeys.Select(k => k + "=" + ctx.Request.Headers[k])));
var type = ctx.Request.IsWebSocketRequest ? "Web Socket" : "HTTP " + ctx.Request.HttpMethod;
_logger.LogMultiline(type + " request received from " + ctx.Request.RemoteEndPoint, LogSeverity.Debug, log);
}
}
/// <summary>
/// Overridable method that can be used to implement a custom hnandler
/// </summary>
/// <param name="context">The context.</param>
/// <exception cref="System.NotImplementedException">Cannot execute handler: + handler + at PathInfo: + httpReq.PathInfo</exception>
protected override void ProcessRequest(HttpListenerContext context)
{
if (string.IsNullOrEmpty(context.Request.RawUrl)) return;
var operationName = context.Request.GetOperationName();
var httpReq = new HttpListenerRequestWrapper(operationName, context.Request);
var httpRes = new HttpListenerResponseWrapper(context.Response);
var handler = ServiceStackHttpHandlerFactory.GetHandler(httpReq);
var serviceStackHandler = handler as IServiceStackHttpHandler;
if (serviceStackHandler != null)
{
var restHandler = serviceStackHandler as RestHandler;
if (restHandler != null)
{
httpReq.OperationName = operationName = restHandler.RestPath.RequestType.Name;
}
serviceStackHandler.ProcessRequest(httpReq, httpRes, operationName);
return;
}
throw new NotImplementedException("Cannot execute handler: " + handler + " at PathInfo: " + httpReq.PathInfo);
}
/// <summary>
/// Logs the response.
/// </summary>
/// <param name="ctx">The CTX.</param>
/// <param name="url">The URL.</param>
/// <param name="endPoint">The end point.</param>
/// <param name="duration">The duration.</param>
private void LogResponse(HttpListenerContext ctx, string url, IPEndPoint endPoint, TimeSpan duration)
{
if (!EnableHttpRequestLogging)
{
return;
}
var statusCode = ctx.Response.StatusCode;
var log = new StringBuilder();
log.AppendLine(string.Format("Url: {0}", url));
log.AppendLine("Headers: " + string.Join(",", ctx.Response.Headers.AllKeys.Select(k => k + "=" + ctx.Response.Headers[k])));
var responseTime = string.Format(". Response time: {0} ms", duration.TotalMilliseconds);
var msg = "Response code " + statusCode + " sent to " + endPoint + responseTime;
_logger.LogMultiline(msg, LogSeverity.Debug, log);
}
/// <summary>
/// Creates the service manager.
/// </summary>
/// <param name="assembliesWithServices">The assemblies with services.</param>
/// <returns>ServiceManager.</returns>
protected override ServiceManager CreateServiceManager(params Assembly[] assembliesWithServices)
{
var types = _restServices.Select(r => r.GetType()).ToArray();
return new ServiceManager(new Container(), new ServiceController(() => types));
}
/// <summary>
/// Shut down the Web Service
/// </summary>
public override void Stop()
{
if (HttpListener != null)
{
HttpListener.Dispose();
HttpListener = null;
}
if (Listener != null)
{
Listener.Prefixes.Remove(UrlPrefix);
}
base.Stop();
}
/// <summary>
/// The _supports native web socket
/// </summary>
private bool? _supportsNativeWebSocket;
/// <summary>
/// Gets a value indicating whether [supports web sockets].
/// </summary>
/// <value><c>true</c> if [supports web sockets]; otherwise, <c>false</c>.</value>
public bool SupportsWebSockets
{
get
{
#if __MonoCS__
return false;
#else
#endif
if (!_supportsNativeWebSocket.HasValue)
{
try
{
new ClientWebSocket();
_supportsNativeWebSocket = true;
}
catch (PlatformNotSupportedException)
{
_supportsNativeWebSocket = false;
}
}
return _supportsNativeWebSocket.Value;
}
}
/// <summary>
/// Gets or sets a value indicating whether [enable HTTP request logging].
/// </summary>
/// <value><c>true</c> if [enable HTTP request logging]; otherwise, <c>false</c>.</value>
public bool EnableHttpRequestLogging { get; set; }
/// <summary>
/// Adds the rest handlers.
/// </summary>
/// <param name="services">The services.</param>
public void Init(IEnumerable<IRestfulService> services)
{
_restServices.AddRange(services);
_logger.Info("Calling EndpointHost.ConfigureHost");
EndpointHost.ConfigureHost(this, ServerName, CreateServiceManager());
_logger.Info("Calling ServiceStack AppHost.Init");
Init();
}
/// <summary>
/// Releases the specified instance.
/// </summary>
/// <param name="instance">The instance.</param>
public override void Release(object instance)
{
// Leave this empty so SS doesn't try to dispose our objects
}
}
/// <summary>
/// Class ContainerAdapter
/// </summary>
class ContainerAdapter : IContainerAdapter, IRelease
{
/// <summary>
/// The _app host
/// </summary>
private readonly IApplicationHost _appHost;
/// <summary>
/// Initializes a new instance of the <see cref="ContainerAdapter" /> class.
/// </summary>
/// <param name="appHost">The app host.</param>
public ContainerAdapter(IApplicationHost appHost)
{
_appHost = appHost;
}
/// <summary>
/// Resolves this instance.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns>``0.</returns>
public T Resolve<T>()
{
return _appHost.Resolve<T>();
}
/// <summary>
/// Tries the resolve.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns>``0.</returns>
public T TryResolve<T>()
{
return _appHost.TryResolve<T>();
}
/// <summary>
/// Releases the specified instance.
/// </summary>
/// <param name="instance">The instance.</param>
public void Release(object instance)
{
// Leave this empty so SS doesn't try to dispose our objects
}
}
}

@ -0,0 +1,48 @@
using MediaBrowser.Model.Logging;
using System;
using System.Linq;
using System.Net;
using System.Text;
namespace MediaBrowser.Server.Implementations.HttpServer
{
public static class LoggerUtils
{
public static void LogRequest(ILogger logger, HttpListenerContext ctx, int workerIndex)
{
var log = new StringBuilder();
log.AppendLine("Url: " + ctx.Request.Url);
log.AppendLine("Headers: " + string.Join(",", ctx.Request.Headers.AllKeys.Select(k => k + "=" + ctx.Request.Headers[k])));
var type = ctx.Request.IsWebSocketRequest ? "Web Socket" : "HTTP " + ctx.Request.HttpMethod;
logger.LogMultiline(type + " request received on worker " + workerIndex + " from " + ctx.Request.RemoteEndPoint, LogSeverity.Debug, log);
}
/// <summary>
/// Logs the response.
/// </summary>
/// <param name="logger">The logger.</param>
/// <param name="ctx">The CTX.</param>
/// <param name="url">The URL.</param>
/// <param name="endPoint">The end point.</param>
/// <param name="duration">The duration.</param>
public static void LogResponse(ILogger logger, HttpListenerContext ctx, string url, IPEndPoint endPoint, TimeSpan duration)
{
var statusCode = ctx.Response.StatusCode;
var log = new StringBuilder();
log.AppendLine(string.Format("Url: {0}", url));
log.AppendLine("Headers: " + string.Join(",", ctx.Response.Headers.AllKeys.Select(k => k + "=" + ctx.Response.Headers[k])));
var responseTime = string.Format(". Response time: {0} ms", duration.TotalMilliseconds);
var msg = "Response code " + statusCode + " sent to " + endPoint + responseTime;
logger.LogMultiline(msg, LogSeverity.Debug, log);
}
}
}

@ -184,5 +184,41 @@ namespace MediaBrowser.Server.Implementations.HttpServer
/// </summary>
/// <value>The on receive.</value>
public Action<string> OnReceive { get; set; }
/// <summary>
/// The _supports native web socket
/// </summary>
private static bool? _supportsNativeWebSocket;
/// <summary>
/// Gets a value indicating whether [supports web sockets].
/// </summary>
/// <value><c>true</c> if [supports web sockets]; otherwise, <c>false</c>.</value>
public static bool IsSupported
{
get
{
#if __MonoCS__
return false;
#else
#endif
if (!_supportsNativeWebSocket.HasValue)
{
try
{
new ClientWebSocket();
_supportsNativeWebSocket = true;
}
catch (PlatformNotSupportedException)
{
_supportsNativeWebSocket = false;
}
}
return _supportsNativeWebSocket.Value;
}
}
}
}

@ -1,5 +1,4 @@
using ServiceStack.Service;
using ServiceStack.ServiceHost;
using ServiceStack.Web;
using System;
using System.Collections.Generic;
using System.Globalization;
@ -197,7 +196,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
public string ContentType { get; set; }
public IRequestContext RequestContext { get; set; }
public IRequest RequestContext { get; set; }
public object Response { get; set; }

@ -0,0 +1,102 @@
using MediaBrowser.Model.Logging;
using ServiceStack;
using ServiceStack.Web;
using System;
using System.Globalization;
using System.Net;
using System.Text;
namespace MediaBrowser.Server.Implementations.HttpServer
{
public class ResponseFilter
{
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
private readonly ILogger _logger;
public ResponseFilter(ILogger logger)
{
_logger = logger;
}
/// <summary>
/// Filters the response.
/// </summary>
/// <param name="req">The req.</param>
/// <param name="res">The res.</param>
/// <param name="dto">The dto.</param>
public void FilterResponse(IRequest req, IResponse res, object dto)
{
// Try to prevent compatibility view
res.AddHeader("X-UA-Compatible", "IE=Edge");
var exception = dto as Exception;
if (exception != null)
{
_logger.ErrorException("Error processing request for {0}", exception, req.RawUrl);
if (!string.IsNullOrEmpty(exception.Message))
{
var error = exception.Message.Replace(Environment.NewLine, " ");
error = RemoveControlCharacters(error);
res.AddHeader("X-Application-Error-Code", error);
}
}
if (dto is CompressedResult)
{
// Per Google PageSpeed
// This instructs the proxies to cache two versions of the resource: one compressed, and one uncompressed.
// The correct version of the resource is delivered based on the client request header.
// This is a good choice for applications that are singly homed and depend on public proxies for user locality.
res.AddHeader("Vary", "Accept-Encoding");
}
var hasOptions = dto as IHasOptions;
if (hasOptions != null)
{
// Content length has to be explicitly set on on HttpListenerResponse or it won't be happy
string contentLength;
if (hasOptions.Options.TryGetValue("Content-Length", out contentLength) && !string.IsNullOrEmpty(contentLength))
{
var length = long.Parse(contentLength, UsCulture);
if (length > 0)
{
var response = (HttpListenerResponse)res.OriginalResponse;
response.ContentLength64 = length;
// Disable chunked encoding. Technically this is only needed when using Content-Range, but
// anytime we know the content length there's no need for it
response.SendChunked = false;
}
}
}
}
/// <summary>
/// Removes the control characters.
/// </summary>
/// <param name="inString">The in string.</param>
/// <returns>System.String.</returns>
private static string RemoveControlCharacters(string inString)
{
if (inString == null) return null;
var newString = new StringBuilder();
foreach (var ch in inString)
{
if (!char.IsControl(ch))
{
newString.Append(ch);
}
}
return newString.ToString();
}
}
}

@ -1,5 +1,5 @@
using MediaBrowser.Common;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Logging;
namespace MediaBrowser.Server.Implementations.HttpServer
@ -15,11 +15,12 @@ namespace MediaBrowser.Server.Implementations.HttpServer
/// <param name="applicationHost">The application host.</param>
/// <param name="logManager">The log manager.</param>
/// <param name="serverName">Name of the server.</param>
/// <param name="handlerPath">The handler path.</param>
/// <param name="defaultRedirectpath">The default redirectpath.</param>
/// <returns>IHttpServer.</returns>
public static IHttpServer CreateServer(IApplicationHost applicationHost, ILogManager logManager, string serverName, string defaultRedirectpath)
public static IHttpServer CreateServer(IApplicationHost applicationHost, ILogManager logManager, string serverName, string handlerPath, string defaultRedirectpath)
{
return new HttpServer(applicationHost, logManager, serverName, defaultRedirectpath);
return new HttpListenerHost(applicationHost, logManager, serverName, handlerPath, defaultRedirectpath);
}
}
}

@ -1,6 +1,5 @@
using MediaBrowser.Model.Logging;
using ServiceStack.Service;
using ServiceStack.ServiceHost;
using ServiceStack.Web;
using System;
using System.Collections.Generic;
using System.IO;

@ -1,6 +1,7 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Net;
using ServiceStack.ServiceHost;
using MediaBrowser.Controller.Net;
using ServiceStack;
using ServiceStack.Web;
using System.IO;
namespace MediaBrowser.Server.Implementations.HttpServer
@ -40,7 +41,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
var requestedFile = Path.Combine(swaggerDirectory, request.ResourceName.Replace('/', Path.DirectorySeparatorChar));
return ResultFactory.GetStaticFileResult(RequestContext, requestedFile);
return ResultFactory.GetStaticFileResult(Request, requestedFile);
}
/// <summary>
@ -53,6 +54,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer
/// Gets or sets the request context.
/// </summary>
/// <value>The request context.</value>
public IRequestContext RequestContext { get; set; }
public IRequest Request { get; set; }
}
}

@ -37,24 +37,28 @@
<Reference Include="Alchemy">
<HintPath>..\packages\Alchemy.2.2.1\lib\net40\Alchemy.dll</HintPath>
</Reference>
<Reference Include="Mono.Data.Sqlite">
<HintPath>..\packages\ServiceStack.OrmLite.Sqlite.Mono.3.9.70\lib\net35\Mono.Data.Sqlite.dll</HintPath>
<Reference Include="ServiceStack, Version=3.9.70.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.OrmLite.Sqlite">
<HintPath>..\packages\ServiceStack.OrmLite.Sqlite.Mono.3.9.70\lib\net35\ServiceStack.OrmLite.Sqlite.dll</HintPath>
<Reference Include="ServiceStack.Client">
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Client.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Reactive.Core">
<HintPath>..\packages\Rx-Core.2.1.30214.0\lib\Net45\System.Reactive.Core.dll</HintPath>
<Reference Include="ServiceStack.Common, Version=3.9.70.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Common.dll</HintPath>
</Reference>
<Reference Include="System.Reactive.Interfaces">
<HintPath>..\packages\Rx-Interfaces.2.1.30214.0\lib\Net45\System.Reactive.Interfaces.dll</HintPath>
<Reference Include="ServiceStack.Interfaces, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll</HintPath>
</Reference>
<Reference Include="System.Reactive.Linq">
<HintPath>..\packages\Rx-Linq.2.1.30214.0\lib\Net45\System.Reactive.Linq.dll</HintPath>
<Reference Include="ServiceStack.Text, Version=3.9.70.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Text.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
@ -63,36 +67,9 @@
<Reference Include="MoreLinq">
<HintPath>..\packages\morelinq.1.0.16006\lib\net35\MoreLinq.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.OrmLite.SqlServer">
<HintPath>..\packages\ServiceStack.OrmLite.SqlServer.3.9.43\lib\ServiceStack.OrmLite.SqlServer.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.Redis">
<HintPath>..\packages\ServiceStack.Redis.3.9.43\lib\net35\ServiceStack.Redis.dll</HintPath>
</Reference>
<Reference Include="BDInfo">
<HintPath>..\packages\MediaBrowser.BdInfo.1.0.0.5\lib\net20\BDInfo.dll</HintPath>
</Reference>
<Reference Include="ServiceStack">
<HintPath>..\packages\ServiceStack.3.9.70\lib\net35\ServiceStack.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.Api.Swagger">
<HintPath>..\packages\ServiceStack.Api.Swagger.3.9.70\lib\net35\ServiceStack.Api.Swagger.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.Common">
<HintPath>..\packages\ServiceStack.Common.3.9.70\lib\net35\ServiceStack.Common.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.Interfaces">
<HintPath>..\packages\ServiceStack.Common.3.9.70\lib\net35\ServiceStack.Interfaces.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.OrmLite">
<HintPath>..\packages\ServiceStack.OrmLite.Sqlite.Mono.3.9.70\lib\net35\ServiceStack.OrmLite.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.ServiceInterface">
<HintPath>..\packages\ServiceStack.3.9.70\lib\net35\ServiceStack.ServiceInterface.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.Text">
<HintPath>..\packages\ServiceStack.Text.3.9.70\lib\net35\ServiceStack.Text.dll</HintPath>
</Reference>
<Reference Include="System.Data.SQLite">
<HintPath>..\packages\System.Data.SQLite.x86.1.0.89.0\lib\net45\System.Data.SQLite.dll</HintPath>
</Reference>
@ -119,10 +96,13 @@
<Compile Include="EntryPoints\UdpServerEntryPoint.cs" />
<Compile Include="EntryPoints\ServerEventNotifier.cs" />
<Compile Include="EntryPoints\UserDataChangeNotifier.cs" />
<Compile Include="HttpServer\ContainerAdapter.cs" />
<Compile Include="HttpServer\HttpListenerHost.cs" />
<Compile Include="HttpServer\HttpResultFactory.cs" />
<Compile Include="HttpServer\HttpServer.cs" />
<Compile Include="HttpServer\LoggerUtils.cs" />
<Compile Include="HttpServer\NativeWebSocket.cs" />
<Compile Include="HttpServer\RangeRequestWriter.cs" />
<Compile Include="HttpServer\ResponseFilter.cs" />
<Compile Include="HttpServer\ServerFactory.cs" />
<Compile Include="HttpServer\ServerLogger.cs" />
<Compile Include="HttpServer\StreamWriter.cs" />
@ -264,58 +244,6 @@
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Content Include="sqlite3.dll" />
<Content Include="swagger-ui\css\hightlight.default.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="swagger-ui\css\screen.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="swagger-ui\images\logo_small.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="swagger-ui\images\pet_store_api.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="swagger-ui\images\throbber.gif">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="swagger-ui\images\wordnik_api.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="swagger-ui\lib\backbone-min.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="swagger-ui\lib\handlebars-1.0.rc.1.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="swagger-ui\lib\highlight.7.3.pack.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="swagger-ui\lib\jquery-1.8.0.min.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="swagger-ui\lib\jquery.ba-bbq.min.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="swagger-ui\lib\jquery.slideto.min.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="swagger-ui\lib\jquery.wiggle.min.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="swagger-ui\lib\swagger.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="swagger-ui\lib\underscore-min.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="swagger-ui\swagger-ui.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="swagger-ui\swagger-ui.min.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<EmbeddedResource Include="Localization\Ratings\ca.txt" />
<Content Include="swagger-ui\index.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>

@ -1,6 +1,7 @@
using MediaBrowser.Common.Net;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Net;
using MediaBrowser.Model.Serialization;
@ -168,7 +169,7 @@ namespace MediaBrowser.Server.Implementations.ServerManager
{
HttpServer = _applicationHost.Resolve<IHttpServer>();
HttpServer.EnableHttpRequestLogging = enableHttpLogging;
HttpServer.Start(urlPrefix);
HttpServer.StartServer(urlPrefix);
}
catch (SocketException ex)
{

@ -1,11 +1,12 @@
using MediaBrowser.Common.Net;
using System.Threading;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Logging;
using System;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Reactive.Linq;
using System.Text;
using System.Threading.Tasks;
@ -35,6 +36,8 @@ namespace MediaBrowser.Server.Implementations.Udp
/// </summary>
private readonly IServerConfigurationManager _serverConfigurationManager;
private bool _isDisposed;
/// <summary>
/// Initializes a new instance of the <see cref="UdpServer" /> class.
/// </summary>
@ -115,38 +118,41 @@ namespace MediaBrowser.Server.Implementations.Udp
_udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
CreateObservable().Subscribe(OnMessageReceived);
Task.Run(() => StartListening());
}
/// <summary>
/// Creates the observable.
/// </summary>
/// <returns>IObservable{UdpReceiveResult}.</returns>
private IObservable<UdpReceiveResult> CreateObservable()
private async void StartListening()
{
while (!_isDisposed)
{
try
{
var result = await GetResult().ConfigureAwait(false);
OnMessageReceived(result);
}
catch (ObjectDisposedException)
{
break;
}
}
}
private Task<UdpReceiveResult> GetResult()
{
return Observable.Create<UdpReceiveResult>(obs =>
Observable.FromAsync(() =>
{
try
{
return _udpClient.ReceiveAsync();
}
catch (ObjectDisposedException)
{
return Task.FromResult(new UdpReceiveResult(new byte[]{}, new IPEndPoint(IPAddress.Any, 0)));
}
catch (Exception ex)
{
_logger.ErrorException("Error receiving udp message", ex);
return Task.FromResult(new UdpReceiveResult(new byte[] { }, new IPEndPoint(IPAddress.Any, 0)));
}
})
.Subscribe(obs))
.Repeat()
.Retry()
.Publish()
.RefCount();
try
{
return _udpClient.ReceiveAsync();
}
catch (ObjectDisposedException)
{
return Task.FromResult(new UdpReceiveResult(new byte[] { }, new IPEndPoint(IPAddress.Any, 0)));
}
catch (Exception ex)
{
_logger.ErrorException("Error receiving udp message", ex);
return Task.FromResult(new UdpReceiveResult(new byte[] { }, new IPEndPoint(IPAddress.Any, 0)));
}
}
/// <summary>
@ -182,6 +188,8 @@ namespace MediaBrowser.Server.Implementations.Udp
/// </summary>
public void Stop()
{
_isDisposed = true;
if (_udpClient != null)
{
_udpClient.Close();

@ -3,15 +3,5 @@
<package id="Alchemy" version="2.2.1" targetFramework="net45" />
<package id="MediaBrowser.BdInfo" version="1.0.0.5" targetFramework="net45" />
<package id="morelinq" version="1.0.16006" targetFramework="net45" />
<package id="Rx-Core" version="2.1.30214.0" targetFramework="net45" />
<package id="Rx-Interfaces" version="2.1.30214.0" targetFramework="net45" />
<package id="Rx-Linq" version="2.1.30214.0" targetFramework="net45" />
<package id="ServiceStack" version="3.9.70" targetFramework="net45" />
<package id="ServiceStack.Api.Swagger" version="3.9.70" targetFramework="net45" />
<package id="ServiceStack.Common" version="3.9.70" targetFramework="net45" />
<package id="ServiceStack.OrmLite.Sqlite.Mono" version="3.9.70" targetFramework="net45" />
<package id="ServiceStack.OrmLite.SqlServer" version="3.9.43" targetFramework="net45" />
<package id="ServiceStack.Redis" version="3.9.43" targetFramework="net45" />
<package id="ServiceStack.Text" version="3.9.70" targetFramework="net45" />
<package id="System.Data.SQLite.x86" version="1.0.89.0" targetFramework="net45" />
</packages>

@ -1,135 +0,0 @@
/*
Original style from softwaremaniacs.org (c) Ivan Sagalaev <Maniac@SoftwareManiacs.Org>
*/
pre code {
display: block; padding: 0.5em;
background: #F0F0F0;
}
pre code,
pre .subst,
pre .tag .title,
pre .lisp .title,
pre .clojure .built_in,
pre .nginx .title {
color: black;
}
pre .string,
pre .title,
pre .constant,
pre .parent,
pre .tag .value,
pre .rules .value,
pre .rules .value .number,
pre .preprocessor,
pre .ruby .symbol,
pre .ruby .symbol .string,
pre .aggregate,
pre .template_tag,
pre .django .variable,
pre .smalltalk .class,
pre .addition,
pre .flow,
pre .stream,
pre .bash .variable,
pre .apache .tag,
pre .apache .cbracket,
pre .tex .command,
pre .tex .special,
pre .erlang_repl .function_or_atom,
pre .markdown .header {
color: #800;
}
pre .comment,
pre .annotation,
pre .template_comment,
pre .diff .header,
pre .chunk,
pre .markdown .blockquote {
color: #888;
}
pre .number,
pre .date,
pre .regexp,
pre .literal,
pre .smalltalk .symbol,
pre .smalltalk .char,
pre .go .constant,
pre .change,
pre .markdown .bullet,
pre .markdown .link_url {
color: #080;
}
pre .label,
pre .javadoc,
pre .ruby .string,
pre .decorator,
pre .filter .argument,
pre .localvars,
pre .array,
pre .attr_selector,
pre .important,
pre .pseudo,
pre .pi,
pre .doctype,
pre .deletion,
pre .envvar,
pre .shebang,
pre .apache .sqbracket,
pre .nginx .built_in,
pre .tex .formula,
pre .erlang_repl .reserved,
pre .prompt,
pre .markdown .link_label,
pre .vhdl .attribute,
pre .clojure .attribute,
pre .coffeescript .property {
color: #88F
}
pre .keyword,
pre .id,
pre .phpdoc,
pre .title,
pre .built_in,
pre .aggregate,
pre .css .tag,
pre .javadoctag,
pre .phpdoc,
pre .yardoctag,
pre .smalltalk .class,
pre .winutils,
pre .bash .variable,
pre .apache .tag,
pre .go .typename,
pre .tex .command,
pre .markdown .strong,
pre .request,
pre .status {
font-weight: bold;
}
pre .markdown .emphasis {
font-style: italic;
}
pre .nginx .built_in {
font-weight: normal;
}
pre .coffeescript .javascript,
pre .javascript .xml,
pre .tex .formula,
pre .xml .javascript,
pre .xml .vbscript,
pre .xml .css,
pre .xml .cdata {
opacity: 0.5;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 770 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 824 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 980 B

@ -1,38 +0,0 @@
// Backbone.js 0.9.2
// (c) 2010-2012 Jeremy Ashkenas, DocumentCloud Inc.
// Backbone may be freely distributed under the MIT license.
// For all details and documentation:
// http://backbonejs.org
(function(){var l=this,y=l.Backbone,z=Array.prototype.slice,A=Array.prototype.splice,g;g="undefined"!==typeof exports?exports:l.Backbone={};g.VERSION="0.9.2";var f=l._;!f&&"undefined"!==typeof require&&(f=require("underscore"));var i=l.jQuery||l.Zepto||l.ender;g.setDomLibrary=function(a){i=a};g.noConflict=function(){l.Backbone=y;return this};g.emulateHTTP=!1;g.emulateJSON=!1;var p=/\s+/,k=g.Events={on:function(a,b,c){var d,e,f,g,j;if(!b)return this;a=a.split(p);for(d=this._callbacks||(this._callbacks=
{});e=a.shift();)f=(j=d[e])?j.tail:{},f.next=g={},f.context=c,f.callback=b,d[e]={tail:g,next:j?j.next:f};return this},off:function(a,b,c){var d,e,h,g,j,q;if(e=this._callbacks){if(!a&&!b&&!c)return delete this._callbacks,this;for(a=a?a.split(p):f.keys(e);d=a.shift();)if(h=e[d],delete e[d],h&&(b||c))for(g=h.tail;(h=h.next)!==g;)if(j=h.callback,q=h.context,b&&j!==b||c&&q!==c)this.on(d,j,q);return this}},trigger:function(a){var b,c,d,e,f,g;if(!(d=this._callbacks))return this;f=d.all;a=a.split(p);for(g=
z.call(arguments,1);b=a.shift();){if(c=d[b])for(e=c.tail;(c=c.next)!==e;)c.callback.apply(c.context||this,g);if(c=f){e=c.tail;for(b=[b].concat(g);(c=c.next)!==e;)c.callback.apply(c.context||this,b)}}return this}};k.bind=k.on;k.unbind=k.off;var o=g.Model=function(a,b){var c;a||(a={});b&&b.parse&&(a=this.parse(a));if(c=n(this,"defaults"))a=f.extend({},c,a);b&&b.collection&&(this.collection=b.collection);this.attributes={};this._escapedAttributes={};this.cid=f.uniqueId("c");this.changed={};this._silent=
{};this._pending={};this.set(a,{silent:!0});this.changed={};this._silent={};this._pending={};this._previousAttributes=f.clone(this.attributes);this.initialize.apply(this,arguments)};f.extend(o.prototype,k,{changed:null,_silent:null,_pending:null,idAttribute:"id",initialize:function(){},toJSON:function(){return f.clone(this.attributes)},get:function(a){return this.attributes[a]},escape:function(a){var b;if(b=this._escapedAttributes[a])return b;b=this.get(a);return this._escapedAttributes[a]=f.escape(null==
b?"":""+b)},has:function(a){return null!=this.get(a)},set:function(a,b,c){var d,e;f.isObject(a)||null==a?(d=a,c=b):(d={},d[a]=b);c||(c={});if(!d)return this;d instanceof o&&(d=d.attributes);if(c.unset)for(e in d)d[e]=void 0;if(!this._validate(d,c))return!1;this.idAttribute in d&&(this.id=d[this.idAttribute]);var b=c.changes={},h=this.attributes,g=this._escapedAttributes,j=this._previousAttributes||{};for(e in d){a=d[e];if(!f.isEqual(h[e],a)||c.unset&&f.has(h,e))delete g[e],(c.silent?this._silent:
b)[e]=!0;c.unset?delete h[e]:h[e]=a;!f.isEqual(j[e],a)||f.has(h,e)!=f.has(j,e)?(this.changed[e]=a,c.silent||(this._pending[e]=!0)):(delete this.changed[e],delete this._pending[e])}c.silent||this.change(c);return this},unset:function(a,b){(b||(b={})).unset=!0;return this.set(a,null,b)},clear:function(a){(a||(a={})).unset=!0;return this.set(f.clone(this.attributes),a)},fetch:function(a){var a=a?f.clone(a):{},b=this,c=a.success;a.success=function(d,e,f){if(!b.set(b.parse(d,f),a))return!1;c&&c(b,d)};
a.error=g.wrapError(a.error,b,a);return(this.sync||g.sync).call(this,"read",this,a)},save:function(a,b,c){var d,e;f.isObject(a)||null==a?(d=a,c=b):(d={},d[a]=b);c=c?f.clone(c):{};if(c.wait){if(!this._validate(d,c))return!1;e=f.clone(this.attributes)}a=f.extend({},c,{silent:!0});if(d&&!this.set(d,c.wait?a:c))return!1;var h=this,i=c.success;c.success=function(a,b,e){b=h.parse(a,e);if(c.wait){delete c.wait;b=f.extend(d||{},b)}if(!h.set(b,c))return false;i?i(h,a):h.trigger("sync",h,a,c)};c.error=g.wrapError(c.error,
h,c);b=this.isNew()?"create":"update";b=(this.sync||g.sync).call(this,b,this,c);c.wait&&this.set(e,a);return b},destroy:function(a){var a=a?f.clone(a):{},b=this,c=a.success,d=function(){b.trigger("destroy",b,b.collection,a)};if(this.isNew())return d(),!1;a.success=function(e){a.wait&&d();c?c(b,e):b.trigger("sync",b,e,a)};a.error=g.wrapError(a.error,b,a);var e=(this.sync||g.sync).call(this,"delete",this,a);a.wait||d();return e},url:function(){var a=n(this,"urlRoot")||n(this.collection,"url")||t();
return this.isNew()?a:a+("/"==a.charAt(a.length-1)?"":"/")+encodeURIComponent(this.id)},parse:function(a){return a},clone:function(){return new this.constructor(this.attributes)},isNew:function(){return null==this.id},change:function(a){a||(a={});var b=this._changing;this._changing=!0;for(var c in this._silent)this._pending[c]=!0;var d=f.extend({},a.changes,this._silent);this._silent={};for(c in d)this.trigger("change:"+c,this,this.get(c),a);if(b)return this;for(;!f.isEmpty(this._pending);){this._pending=
{};this.trigger("change",this,a);for(c in this.changed)!this._pending[c]&&!this._silent[c]&&delete this.changed[c];this._previousAttributes=f.clone(this.attributes)}this._changing=!1;return this},hasChanged:function(a){return!arguments.length?!f.isEmpty(this.changed):f.has(this.changed,a)},changedAttributes:function(a){if(!a)return this.hasChanged()?f.clone(this.changed):!1;var b,c=!1,d=this._previousAttributes,e;for(e in a)if(!f.isEqual(d[e],b=a[e]))(c||(c={}))[e]=b;return c},previous:function(a){return!arguments.length||
!this._previousAttributes?null:this._previousAttributes[a]},previousAttributes:function(){return f.clone(this._previousAttributes)},isValid:function(){return!this.validate(this.attributes)},_validate:function(a,b){if(b.silent||!this.validate)return!0;var a=f.extend({},this.attributes,a),c=this.validate(a,b);if(!c)return!0;b&&b.error?b.error(this,c,b):this.trigger("error",this,c,b);return!1}});var r=g.Collection=function(a,b){b||(b={});b.model&&(this.model=b.model);b.comparator&&(this.comparator=b.comparator);
this._reset();this.initialize.apply(this,arguments);a&&this.reset(a,{silent:!0,parse:b.parse})};f.extend(r.prototype,k,{model:o,initialize:function(){},toJSON:function(a){return this.map(function(b){return b.toJSON(a)})},add:function(a,b){var c,d,e,g,i,j={},k={},l=[];b||(b={});a=f.isArray(a)?a.slice():[a];c=0;for(d=a.length;c<d;c++){if(!(e=a[c]=this._prepareModel(a[c],b)))throw Error("Can't add an invalid model to a collection");g=e.cid;i=e.id;j[g]||this._byCid[g]||null!=i&&(k[i]||this._byId[i])?
l.push(c):j[g]=k[i]=e}for(c=l.length;c--;)a.splice(l[c],1);c=0;for(d=a.length;c<d;c++)(e=a[c]).on("all",this._onModelEvent,this),this._byCid[e.cid]=e,null!=e.id&&(this._byId[e.id]=e);this.length+=d;A.apply(this.models,[null!=b.at?b.at:this.models.length,0].concat(a));this.comparator&&this.sort({silent:!0});if(b.silent)return this;c=0;for(d=this.models.length;c<d;c++)if(j[(e=this.models[c]).cid])b.index=c,e.trigger("add",e,this,b);return this},remove:function(a,b){var c,d,e,g;b||(b={});a=f.isArray(a)?
a.slice():[a];c=0;for(d=a.length;c<d;c++)if(g=this.getByCid(a[c])||this.get(a[c]))delete this._byId[g.id],delete this._byCid[g.cid],e=this.indexOf(g),this.models.splice(e,1),this.length--,b.silent||(b.index=e,g.trigger("remove",g,this,b)),this._removeReference(g);return this},push:function(a,b){a=this._prepareModel(a,b);this.add(a,b);return a},pop:function(a){var b=this.at(this.length-1);this.remove(b,a);return b},unshift:function(a,b){a=this._prepareModel(a,b);this.add(a,f.extend({at:0},b));return a},
shift:function(a){var b=this.at(0);this.remove(b,a);return b},get:function(a){return null==a?void 0:this._byId[null!=a.id?a.id:a]},getByCid:function(a){return a&&this._byCid[a.cid||a]},at:function(a){return this.models[a]},where:function(a){return f.isEmpty(a)?[]:this.filter(function(b){for(var c in a)if(a[c]!==b.get(c))return!1;return!0})},sort:function(a){a||(a={});if(!this.comparator)throw Error("Cannot sort a set without a comparator");var b=f.bind(this.comparator,this);1==this.comparator.length?
this.models=this.sortBy(b):this.models.sort(b);a.silent||this.trigger("reset",this,a);return this},pluck:function(a){return f.map(this.models,function(b){return b.get(a)})},reset:function(a,b){a||(a=[]);b||(b={});for(var c=0,d=this.models.length;c<d;c++)this._removeReference(this.models[c]);this._reset();this.add(a,f.extend({silent:!0},b));b.silent||this.trigger("reset",this,b);return this},fetch:function(a){a=a?f.clone(a):{};void 0===a.parse&&(a.parse=!0);var b=this,c=a.success;a.success=function(d,
e,f){b[a.add?"add":"reset"](b.parse(d,f),a);c&&c(b,d)};a.error=g.wrapError(a.error,b,a);return(this.sync||g.sync).call(this,"read",this,a)},create:function(a,b){var c=this,b=b?f.clone(b):{},a=this._prepareModel(a,b);if(!a)return!1;b.wait||c.add(a,b);var d=b.success;b.success=function(e,f){b.wait&&c.add(e,b);d?d(e,f):e.trigger("sync",a,f,b)};a.save(null,b);return a},parse:function(a){return a},chain:function(){return f(this.models).chain()},_reset:function(){this.length=0;this.models=[];this._byId=
{};this._byCid={}},_prepareModel:function(a,b){b||(b={});a instanceof o?a.collection||(a.collection=this):(b.collection=this,a=new this.model(a,b),a._validate(a.attributes,b)||(a=!1));return a},_removeReference:function(a){this==a.collection&&delete a.collection;a.off("all",this._onModelEvent,this)},_onModelEvent:function(a,b,c,d){("add"==a||"remove"==a)&&c!=this||("destroy"==a&&this.remove(b,d),b&&a==="change:"+b.idAttribute&&(delete this._byId[b.previous(b.idAttribute)],this._byId[b.id]=b),this.trigger.apply(this,
arguments))}});f.each("forEach,each,map,reduce,reduceRight,find,detect,filter,select,reject,every,all,some,any,include,contains,invoke,max,min,sortBy,sortedIndex,toArray,size,first,initial,rest,last,without,indexOf,shuffle,lastIndexOf,isEmpty,groupBy".split(","),function(a){r.prototype[a]=function(){return f[a].apply(f,[this.models].concat(f.toArray(arguments)))}});var u=g.Router=function(a){a||(a={});a.routes&&(this.routes=a.routes);this._bindRoutes();this.initialize.apply(this,arguments)},B=/:\w+/g,
C=/\*\w+/g,D=/[-[\]{}()+?.,\\^$|#\s]/g;f.extend(u.prototype,k,{initialize:function(){},route:function(a,b,c){g.history||(g.history=new m);f.isRegExp(a)||(a=this._routeToRegExp(a));c||(c=this[b]);g.history.route(a,f.bind(function(d){d=this._extractParameters(a,d);c&&c.apply(this,d);this.trigger.apply(this,["route:"+b].concat(d));g.history.trigger("route",this,b,d)},this));return this},navigate:function(a,b){g.history.navigate(a,b)},_bindRoutes:function(){if(this.routes){var a=[],b;for(b in this.routes)a.unshift([b,
this.routes[b]]);b=0;for(var c=a.length;b<c;b++)this.route(a[b][0],a[b][1],this[a[b][1]])}},_routeToRegExp:function(a){a=a.replace(D,"\\$&").replace(B,"([^/]+)").replace(C,"(.*?)");return RegExp("^"+a+"$")},_extractParameters:function(a,b){return a.exec(b).slice(1)}});var m=g.History=function(){this.handlers=[];f.bindAll(this,"checkUrl")},s=/^[#\/]/,E=/msie [\w.]+/;m.started=!1;f.extend(m.prototype,k,{interval:50,getHash:function(a){return(a=(a?a.location:window.location).href.match(/#(.*)$/))?a[1]:
""},getFragment:function(a,b){if(null==a)if(this._hasPushState||b){var a=window.location.pathname,c=window.location.search;c&&(a+=c)}else a=this.getHash();a.indexOf(this.options.root)||(a=a.substr(this.options.root.length));return a.replace(s,"")},start:function(a){if(m.started)throw Error("Backbone.history has already been started");m.started=!0;this.options=f.extend({},{root:"/"},this.options,a);this._wantsHashChange=!1!==this.options.hashChange;this._wantsPushState=!!this.options.pushState;this._hasPushState=
!(!this.options.pushState||!window.history||!window.history.pushState);var a=this.getFragment(),b=document.documentMode;if(b=E.exec(navigator.userAgent.toLowerCase())&&(!b||7>=b))this.iframe=i('<iframe src="javascript:0" tabindex="-1" />').hide().appendTo("body")[0].contentWindow,this.navigate(a);this._hasPushState?i(window).bind("popstate",this.checkUrl):this._wantsHashChange&&"onhashchange"in window&&!b?i(window).bind("hashchange",this.checkUrl):this._wantsHashChange&&(this._checkUrlInterval=setInterval(this.checkUrl,
this.interval));this.fragment=a;a=window.location;b=a.pathname==this.options.root;if(this._wantsHashChange&&this._wantsPushState&&!this._hasPushState&&!b)return this.fragment=this.getFragment(null,!0),window.location.replace(this.options.root+"#"+this.fragment),!0;this._wantsPushState&&this._hasPushState&&b&&a.hash&&(this.fragment=this.getHash().replace(s,""),window.history.replaceState({},document.title,a.protocol+"//"+a.host+this.options.root+this.fragment));if(!this.options.silent)return this.loadUrl()},
stop:function(){i(window).unbind("popstate",this.checkUrl).unbind("hashchange",this.checkUrl);clearInterval(this._checkUrlInterval);m.started=!1},route:function(a,b){this.handlers.unshift({route:a,callback:b})},checkUrl:function(){var a=this.getFragment();a==this.fragment&&this.iframe&&(a=this.getFragment(this.getHash(this.iframe)));if(a==this.fragment)return!1;this.iframe&&this.navigate(a);this.loadUrl()||this.loadUrl(this.getHash())},loadUrl:function(a){var b=this.fragment=this.getFragment(a);return f.any(this.handlers,
function(a){if(a.route.test(b))return a.callback(b),!0})},navigate:function(a,b){if(!m.started)return!1;if(!b||!0===b)b={trigger:b};var c=(a||"").replace(s,"");this.fragment!=c&&(this._hasPushState?(0!=c.indexOf(this.options.root)&&(c=this.options.root+c),this.fragment=c,window.history[b.replace?"replaceState":"pushState"]({},document.title,c)):this._wantsHashChange?(this.fragment=c,this._updateHash(window.location,c,b.replace),this.iframe&&c!=this.getFragment(this.getHash(this.iframe))&&(b.replace||
this.iframe.document.open().close(),this._updateHash(this.iframe.location,c,b.replace))):window.location.assign(this.options.root+a),b.trigger&&this.loadUrl(a))},_updateHash:function(a,b,c){c?a.replace(a.toString().replace(/(javascript:|#).*$/,"")+"#"+b):a.hash=b}});var v=g.View=function(a){this.cid=f.uniqueId("view");this._configure(a||{});this._ensureElement();this.initialize.apply(this,arguments);this.delegateEvents()},F=/^(\S+)\s*(.*)$/,w="model,collection,el,id,attributes,className,tagName".split(",");
f.extend(v.prototype,k,{tagName:"div",$:function(a){return this.$el.find(a)},initialize:function(){},render:function(){return this},remove:function(){this.$el.remove();return this},make:function(a,b,c){a=document.createElement(a);b&&i(a).attr(b);c&&i(a).html(c);return a},setElement:function(a,b){this.$el&&this.undelegateEvents();this.$el=a instanceof i?a:i(a);this.el=this.$el[0];!1!==b&&this.delegateEvents();return this},delegateEvents:function(a){if(a||(a=n(this,"events"))){this.undelegateEvents();
for(var b in a){var c=a[b];f.isFunction(c)||(c=this[a[b]]);if(!c)throw Error('Method "'+a[b]+'" does not exist');var d=b.match(F),e=d[1],d=d[2],c=f.bind(c,this),e=e+(".delegateEvents"+this.cid);""===d?this.$el.bind(e,c):this.$el.delegate(d,e,c)}}},undelegateEvents:function(){this.$el.unbind(".delegateEvents"+this.cid)},_configure:function(a){this.options&&(a=f.extend({},this.options,a));for(var b=0,c=w.length;b<c;b++){var d=w[b];a[d]&&(this[d]=a[d])}this.options=a},_ensureElement:function(){if(this.el)this.setElement(this.el,
!1);else{var a=n(this,"attributes")||{};this.id&&(a.id=this.id);this.className&&(a["class"]=this.className);this.setElement(this.make(this.tagName,a),!1)}}});o.extend=r.extend=u.extend=v.extend=function(a,b){var c=G(this,a,b);c.extend=this.extend;return c};var H={create:"POST",update:"PUT","delete":"DELETE",read:"GET"};g.sync=function(a,b,c){var d=H[a];c||(c={});var e={type:d,dataType:"json"};c.url||(e.url=n(b,"url")||t());if(!c.data&&b&&("create"==a||"update"==a))e.contentType="application/json",
e.data=JSON.stringify(b.toJSON());g.emulateJSON&&(e.contentType="application/x-www-form-urlencoded",e.data=e.data?{model:e.data}:{});if(g.emulateHTTP&&("PUT"===d||"DELETE"===d))g.emulateJSON&&(e.data._method=d),e.type="POST",e.beforeSend=function(a){a.setRequestHeader("X-HTTP-Method-Override",d)};"GET"!==e.type&&!g.emulateJSON&&(e.processData=!1);return i.ajax(f.extend(e,c))};g.wrapError=function(a,b,c){return function(d,e){e=d===b?e:d;a?a(b,e,c):b.trigger("error",b,e,c)}};var x=function(){},G=function(a,
b,c){var d;d=b&&b.hasOwnProperty("constructor")?b.constructor:function(){a.apply(this,arguments)};f.extend(d,a);x.prototype=a.prototype;d.prototype=new x;b&&f.extend(d.prototype,b);c&&f.extend(d,c);d.prototype.constructor=d;d.__super__=a.prototype;return d},n=function(a,b){return!a||!a[b]?null:f.isFunction(a[b])?a[b]():a[b]},t=function(){throw Error('A "url" property or function must be specified');}}).call(this);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1,18 +0,0 @@
/*
* jQuery BBQ: Back Button & Query Library - v1.2.1 - 2/17/2010
* http://benalman.com/projects/jquery-bbq-plugin/
*
* Copyright (c) 2010 "Cowboy" Ben Alman
* Dual licensed under the MIT and GPL licenses.
* http://benalman.com/about/license/
*/
(function($,p){var i,m=Array.prototype.slice,r=decodeURIComponent,a=$.param,c,l,v,b=$.bbq=$.bbq||{},q,u,j,e=$.event.special,d="hashchange",A="querystring",D="fragment",y="elemUrlAttr",g="location",k="href",t="src",x=/^.*\?|#.*$/g,w=/^.*\#/,h,C={};function E(F){return typeof F==="string"}function B(G){var F=m.call(arguments,1);return function(){return G.apply(this,F.concat(m.call(arguments)))}}function n(F){return F.replace(/^[^#]*#?(.*)$/,"$1")}function o(F){return F.replace(/(?:^[^?#]*\?([^#]*).*$)?.*/,"$1")}function f(H,M,F,I,G){var O,L,K,N,J;if(I!==i){K=F.match(H?/^([^#]*)\#?(.*)$/:/^([^#?]*)\??([^#]*)(#?.*)/);J=K[3]||"";if(G===2&&E(I)){L=I.replace(H?w:x,"")}else{N=l(K[2]);I=E(I)?l[H?D:A](I):I;L=G===2?I:G===1?$.extend({},I,N):$.extend({},N,I);L=a(L);if(H){L=L.replace(h,r)}}O=K[1]+(H?"#":L||!K[1]?"?":"")+L+J}else{O=M(F!==i?F:p[g][k])}return O}a[A]=B(f,0,o);a[D]=c=B(f,1,n);c.noEscape=function(G){G=G||"";var F=$.map(G.split(""),encodeURIComponent);h=new RegExp(F.join("|"),"g")};c.noEscape(",/");$.deparam=l=function(I,F){var H={},G={"true":!0,"false":!1,"null":null};$.each(I.replace(/\+/g," ").split("&"),function(L,Q){var K=Q.split("="),P=r(K[0]),J,O=H,M=0,R=P.split("]["),N=R.length-1;if(/\[/.test(R[0])&&/\]$/.test(R[N])){R[N]=R[N].replace(/\]$/,"");R=R.shift().split("[").concat(R);N=R.length-1}else{N=0}if(K.length===2){J=r(K[1]);if(F){J=J&&!isNaN(J)?+J:J==="undefined"?i:G[J]!==i?G[J]:J}if(N){for(;M<=N;M++){P=R[M]===""?O.length:R[M];O=O[P]=M<N?O[P]||(R[M+1]&&isNaN(R[M+1])?{}:[]):J}}else{if($.isArray(H[P])){H[P].push(J)}else{if(H[P]!==i){H[P]=[H[P],J]}else{H[P]=J}}}}else{if(P){H[P]=F?i:""}}});return H};function z(H,F,G){if(F===i||typeof F==="boolean"){G=F;F=a[H?D:A]()}else{F=E(F)?F.replace(H?w:x,""):F}return l(F,G)}l[A]=B(z,0);l[D]=v=B(z,1);$[y]||($[y]=function(F){return $.extend(C,F)})({a:k,base:k,iframe:t,img:t,input:t,form:"action",link:k,script:t});j=$[y];function s(I,G,H,F){if(!E(H)&&typeof H!=="object"){F=H;H=G;G=i}return this.each(function(){var L=$(this),J=G||j()[(this.nodeName||"").toLowerCase()]||"",K=J&&L.attr(J)||"";L.attr(J,a[I](K,H,F))})}$.fn[A]=B(s,A);$.fn[D]=B(s,D);b.pushState=q=function(I,F){if(E(I)&&/^#/.test(I)&&F===i){F=2}var H=I!==i,G=c(p[g][k],H?I:{},H?F:2);p[g][k]=G+(/#/.test(G)?"":"#")};b.getState=u=function(F,G){return F===i||typeof F==="boolean"?v(F):v(G)[F]};b.removeState=function(F){var G={};if(F!==i){G=u();$.each($.isArray(F)?F:arguments,function(I,H){delete G[H]})}q(G,2)};e[d]=$.extend(e[d],{add:function(F){var H;function G(J){var I=J[D]=c();J.getState=function(K,L){return K===i||typeof K==="boolean"?l(I,K):l(I,L)[K]};H.apply(this,arguments)}if($.isFunction(F)){H=F;return G}else{H=F.handler;F.handler=G}}})})(jQuery,this);
/*
* jQuery hashchange event - v1.2 - 2/11/2010
* http://benalman.com/projects/jquery-hashchange-plugin/
*
* Copyright (c) 2010 "Cowboy" Ben Alman
* Dual licensed under the MIT and GPL licenses.
* http://benalman.com/about/license/
*/
(function($,i,b){var j,k=$.event.special,c="location",d="hashchange",l="href",f=$.browser,g=document.documentMode,h=f.msie&&(g===b||g<8),e="on"+d in i&&!h;function a(m){m=m||i[c][l];return m.replace(/^[^#]*#?(.*)$/,"$1")}$[d+"Delay"]=100;k[d]=$.extend(k[d],{setup:function(){if(e){return false}$(j.start)},teardown:function(){if(e){return false}$(j.stop)}});j=(function(){var m={},r,n,o,q;function p(){o=q=function(s){return s};if(h){n=$('<iframe src="javascript:0"/>').hide().insertAfter("body")[0].contentWindow;q=function(){return a(n.document[c][l])};o=function(u,s){if(u!==s){var t=n.document;t.open().close();t[c].hash="#"+u}};o(a())}}m.start=function(){if(r){return}var t=a();o||p();(function s(){var v=a(),u=q(t);if(v!==t){o(t=v,u);$(i).trigger(d)}else{if(u!==t){i[c][l]=i[c][l].replace(/#.*/,"")+"#"+u}}r=setTimeout(s,$[d+"Delay"])})()};m.stop=function(){if(!n){r&&clearTimeout(r);r=0}};return m})()})(jQuery,this);

@ -1 +0,0 @@
(function(b){b.fn.slideto=function(a){a=b.extend({slide_duration:"slow",highlight_duration:3E3,highlight:true,highlight_color:"#FFFF99"},a);return this.each(function(){obj=b(this);b("body").animate({scrollTop:obj.offset().top},a.slide_duration,function(){a.highlight&&b.ui.version&&obj.effect("highlight",{color:a.highlight_color},a.highlight_duration)})})}})(jQuery);

@ -1,8 +0,0 @@
/*
jQuery Wiggle
Author: WonderGroup, Jordan Thomas
URL: http://labs.wondergroup.com/demos/mini-ui/index.html
License: MIT (http://en.wikipedia.org/wiki/MIT_License)
*/
jQuery.fn.wiggle=function(o){var d={speed:50,wiggles:3,travel:5,callback:null};var o=jQuery.extend(d,o);return this.each(function(){var cache=this;var wrap=jQuery(this).wrap('<div class="wiggle-wrap"></div>').css("position","relative");var calls=0;for(i=1;i<=o.wiggles;i++){jQuery(this).animate({left:"-="+o.travel},o.speed).animate({left:"+="+o.travel*2},o.speed*2).animate({left:"-="+o.travel},o.speed,function(){calls++;if(jQuery(cache).parent().hasClass('wiggle-wrap')){jQuery(cache).parent().replaceWith(cache);}
if(calls==o.wiggles&&jQuery.isFunction(o.callback)){o.callback();}});}});};

@ -1,772 +0,0 @@
// Generated by CoffeeScript 1.4.0
(function() {
var SwaggerApi, SwaggerModel, SwaggerModelProperty, SwaggerOperation, SwaggerRequest, SwaggerResource,
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
SwaggerApi = (function() {
SwaggerApi.prototype.discoveryUrl = "http://api.wordnik.com/v4/resources.json";
SwaggerApi.prototype.debug = false;
SwaggerApi.prototype.api_key = null;
SwaggerApi.prototype.basePath = null;
function SwaggerApi(options) {
if (options == null) {
options = {};
}
if (options.discoveryUrl != null) {
this.discoveryUrl = options.discoveryUrl;
}
if (options.debug != null) {
this.debug = options.debug;
}
this.apiKeyName = options.apiKeyName != null ? options.apiKeyName : 'api_key';
if (options.apiKey != null) {
this.api_key = options.apiKey;
}
if (options.api_key != null) {
this.api_key = options.api_key;
}
if (options.verbose != null) {
this.verbose = options.verbose;
}
this.supportHeaderParams = options.supportHeaderParams != null ? options.supportHeaderParams : false;
this.supportedSubmitMethods = options.supportedSubmitMethods != null ? options.supportedSubmitMethods : ['get'];
if (options.success != null) {
this.success = options.success;
}
this.failure = options.failure != null ? options.failure : function() {};
this.progress = options.progress != null ? options.progress : function() {};
this.headers = options.headers != null ? options.headers : {};
this.booleanValues = options.booleanValues != null ? options.booleanValues : new Array('true', 'false');
this.discoveryUrl = this.suffixApiKey(this.discoveryUrl);
if (options.success != null) {
this.build();
}
}
SwaggerApi.prototype.build = function() {
var _this = this;
this.progress('fetching resource list: ' + this.discoveryUrl);
return jQuery.getJSON(this.discoveryUrl, function(response) {
var res, resource, _i, _j, _len, _len1, _ref, _ref1;
if (response.apiVersion != null) {
_this.apiVersion = response.apiVersion;
}
if ((response.basePath != null) && jQuery.trim(response.basePath).length > 0) {
_this.basePath = response.basePath;
if (_this.basePath.match(/^HTTP/i) == null) {
_this.fail("discoveryUrl basePath must be a URL.");
}
_this.basePath = _this.basePath.replace(/\/$/, '');
} else {
_this.basePath = _this.discoveryUrl.substring(0, _this.discoveryUrl.lastIndexOf('/'));
log('derived basepath from discoveryUrl as ' + _this.basePath);
}
_this.apis = {};
_this.apisArray = [];
if (response.resourcePath != null) {
_this.resourcePath = response.resourcePath;
res = null;
_ref = response.apis;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
resource = _ref[_i];
if (res === null) {
res = new SwaggerResource(resource, _this);
} else {
res.addOperations(resource.path, resource.operations);
}
}
if (res != null) {
_this.apis[res.name] = res;
_this.apisArray.push(res);
res.ready = true;
_this.selfReflect();
}
} else {
_ref1 = response.apis;
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
resource = _ref1[_j];
res = new SwaggerResource(resource, _this);
_this.apis[res.name] = res;
_this.apisArray.push(res);
}
}
return _this;
}).error(function(error) {
if (_this.discoveryUrl.substring(0, 4) !== 'http') {
return _this.fail('Please specify the protocol for ' + _this.discoveryUrl);
} else if (error.status === 0) {
return _this.fail('Can\'t read from server. It may not have the appropriate access-control-origin settings.');
} else if (error.status === 404) {
return _this.fail('Can\'t read swagger JSON from ' + _this.discoveryUrl);
} else {
return _this.fail(error.status + ' : ' + error.statusText + ' ' + _this.discoveryUrl);
}
});
};
SwaggerApi.prototype.selfReflect = function() {
var resource, resource_name, _ref;
if (this.apis == null) {
return false;
}
_ref = this.apis;
for (resource_name in _ref) {
resource = _ref[resource_name];
if (resource.ready == null) {
return false;
}
}
this.setConsolidatedModels();
this.ready = true;
if (this.success != null) {
return this.success();
}
};
SwaggerApi.prototype.fail = function(message) {
this.failure(message);
throw message;
};
SwaggerApi.prototype.setConsolidatedModels = function() {
var model, modelName, resource, resource_name, _i, _len, _ref, _ref1, _results;
this.modelsArray = [];
this.models = {};
_ref = this.apis;
for (resource_name in _ref) {
resource = _ref[resource_name];
for (modelName in resource.models) {
if (!(this.models[modelName] != null)) {
this.models[modelName] = resource.models[modelName];
this.modelsArray.push(resource.models[modelName]);
}
}
}
_ref1 = this.modelsArray;
_results = [];
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
model = _ref1[_i];
_results.push(model.setReferencedModels(this.models));
}
return _results;
};
SwaggerApi.prototype.suffixApiKey = function(url) {
var sep;
if ((this.api_key != null) && jQuery.trim(this.api_key).length > 0 && (url != null)) {
sep = url.indexOf('?') > 0 ? '&' : '?';
return url + sep + this.apiKeyName + '=' + this.api_key;
} else {
return url;
}
};
SwaggerApi.prototype.help = function() {
var operation, operation_name, parameter, resource, resource_name, _i, _len, _ref, _ref1, _ref2;
_ref = this.apis;
for (resource_name in _ref) {
resource = _ref[resource_name];
console.log(resource_name);
_ref1 = resource.operations;
for (operation_name in _ref1) {
operation = _ref1[operation_name];
console.log(" " + operation.nickname);
_ref2 = operation.parameters;
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
parameter = _ref2[_i];
console.log(" " + parameter.name + (parameter.required ? ' (required)' : '') + " - " + parameter.description);
}
}
}
return this;
};
return SwaggerApi;
})();
SwaggerResource = (function() {
function SwaggerResource(resourceObj, api) {
var parts,
_this = this;
this.api = api;
this.path = this.api.resourcePath != null ? this.api.resourcePath : resourceObj.path;
this.description = resourceObj.description;
parts = this.path.split("/");
this.name = parts[parts.length - 1].replace('.{format}', '');
this.basePath = this.api.basePath;
this.operations = {};
this.operationsArray = [];
this.modelsArray = [];
this.models = {};
if ((resourceObj.operations != null) && (this.api.resourcePath != null)) {
this.api.progress('reading resource ' + this.name + ' models and operations');
this.addModels(resourceObj.models);
this.addOperations(resourceObj.path, resourceObj.operations);
this.api[this.name] = this;
} else {
if (this.path == null) {
this.api.fail("SwaggerResources must have a path.");
}
this.url = this.api.suffixApiKey(this.api.basePath + this.path.replace('{format}', 'json'));
this.api.progress('fetching resource ' + this.name + ': ' + this.url);
jQuery.getJSON(this.url, function(response) {
var endpoint, _i, _len, _ref;
if ((response.basePath != null) && jQuery.trim(response.basePath).length > 0) {
_this.basePath = response.basePath;
_this.basePath = _this.basePath.replace(/\/$/, '');
}
_this.addModels(response.models);
if (response.apis) {
_ref = response.apis;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
endpoint = _ref[_i];
_this.addOperations(endpoint.path, endpoint.operations);
}
}
_this.api[_this.name] = _this;
_this.ready = true;
return _this.api.selfReflect();
}).error(function(error) {
return _this.api.fail("Unable to read api '" + _this.name + "' from path " + _this.url + " (server returned " + error.statusText + ")");
});
}
}
SwaggerResource.prototype.addModels = function(models) {
var model, modelName, swaggerModel, _i, _len, _ref, _results;
if (models != null) {
for (modelName in models) {
if (!(this.models[modelName] != null)) {
swaggerModel = new SwaggerModel(modelName, models[modelName]);
this.modelsArray.push(swaggerModel);
this.models[modelName] = swaggerModel;
}
}
_ref = this.modelsArray;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
model = _ref[_i];
_results.push(model.setReferencedModels(this.models));
}
return _results;
}
};
SwaggerResource.prototype.addOperations = function(resource_path, ops) {
var consumes, o, op, _i, _len, _results;
if (ops) {
_results = [];
for (_i = 0, _len = ops.length; _i < _len; _i++) {
o = ops[_i];
consumes = o.consumes;
if (o.supportedContentTypes) {
consumes = o.supportedContentTypes;
}
op = new SwaggerOperation(o.nickname, resource_path, o.httpMethod, o.parameters, o.summary, o.notes, o.responseClass, o.errorResponses, this, o.consumes, o.produces);
this.operations[op.nickname] = op;
_results.push(this.operationsArray.push(op));
}
return _results;
}
};
SwaggerResource.prototype.help = function() {
var operation, operation_name, parameter, _i, _len, _ref, _ref1;
_ref = this.operations;
for (operation_name in _ref) {
operation = _ref[operation_name];
console.log(" " + operation.nickname);
_ref1 = operation.parameters;
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
parameter = _ref1[_i];
console.log(" " + parameter.name + (parameter.required ? ' (required)' : '') + " - " + parameter.description);
}
}
return this;
};
return SwaggerResource;
})();
SwaggerModel = (function() {
function SwaggerModel(modelName, obj) {
var propertyName;
this.name = obj.id != null ? obj.id : modelName;
this.properties = [];
for (propertyName in obj.properties) {
this.properties.push(new SwaggerModelProperty(propertyName, obj.properties[propertyName]));
}
}
SwaggerModel.prototype.setReferencedModels = function(allModels) {
var prop, _i, _len, _ref, _results;
_ref = this.properties;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
prop = _ref[_i];
if (allModels[prop.dataType] != null) {
_results.push(prop.refModel = allModels[prop.dataType]);
} else if ((prop.refDataType != null) && (allModels[prop.refDataType] != null)) {
_results.push(prop.refModel = allModels[prop.refDataType]);
} else {
_results.push(void 0);
}
}
return _results;
};
SwaggerModel.prototype.getMockSignature = function(modelsToIgnore) {
var classClose, classOpen, prop, propertiesStr, returnVal, strong, strongClose, stronger, _i, _j, _len, _len1, _ref, _ref1;
propertiesStr = [];
_ref = this.properties;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
prop = _ref[_i];
propertiesStr.push(prop.toString());
}
strong = '<span class="strong">';
stronger = '<span class="stronger">';
strongClose = '</span>';
classOpen = strong + this.name + ' {' + strongClose;
classClose = strong + '}' + strongClose;
returnVal = classOpen + '<div>' + propertiesStr.join(',</div><div>') + '</div>' + classClose;
if (!modelsToIgnore) {
modelsToIgnore = [];
}
modelsToIgnore.push(this);
_ref1 = this.properties;
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
prop = _ref1[_j];
if ((prop.refModel != null) && (modelsToIgnore.indexOf(prop.refModel)) === -1) {
returnVal = returnVal + ('<br>' + prop.refModel.getMockSignature(modelsToIgnore));
}
}
return returnVal;
};
SwaggerModel.prototype.createJSONSample = function(modelsToIgnore) {
var prop, result, _i, _len, _ref;
result = {};
modelsToIgnore = modelsToIgnore || [];
modelsToIgnore.push(this.name);
_ref = this.properties;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
prop = _ref[_i];
result[prop.name] = prop.getSampleValue(modelsToIgnore);
}
return result;
};
return SwaggerModel;
})();
SwaggerModelProperty = (function() {
function SwaggerModelProperty(name, obj) {
this.name = name;
this.dataType = obj.type;
this.isCollection = this.dataType && (this.dataType.toLowerCase() === 'array' || this.dataType.toLowerCase() === 'list' || this.dataType.toLowerCase() === 'set');
this.descr = obj.description;
this.required = obj.required;
if (obj.items != null) {
if (obj.items.type != null) {
this.refDataType = obj.items.type;
}
if (obj.items.$ref != null) {
this.refDataType = obj.items.$ref;
}
}
this.dataTypeWithRef = this.refDataType != null ? this.dataType + '[' + this.refDataType + ']' : this.dataType;
if (obj.allowableValues != null) {
this.valueType = obj.allowableValues.valueType;
this.values = obj.allowableValues.values;
if (this.values != null) {
this.valuesString = "'" + this.values.join("' or '") + "'";
}
}
}
SwaggerModelProperty.prototype.getSampleValue = function(modelsToIgnore) {
var result;
if ((this.refModel != null) && (modelsToIgnore.indexOf(this.refModel.name) === -1)) {
result = this.refModel.createJSONSample(modelsToIgnore);
} else {
if (this.isCollection) {
result = this.refDataType;
} else {
result = this.dataType;
}
}
if (this.isCollection) {
return [result];
} else {
return result;
}
};
SwaggerModelProperty.prototype.toString = function() {
var req, str;
req = this.required ? 'propReq' : 'propOpt';
str = '<span class="propName ' + req + '">' + this.name + '</span> (<span class="propType">' + this.dataTypeWithRef + '</span>';
if (!this.required) {
str += ', <span class="propOptKey">optional</span>';
}
str += ')';
if (this.values != null) {
str += " = <span class='propVals'>['" + this.values.join("' or '") + "']</span>";
}
if (this.descr != null) {
str += ': <span class="propDesc">' + this.descr + '</span>';
}
return str;
};
return SwaggerModelProperty;
})();
SwaggerOperation = (function() {
function SwaggerOperation(nickname, path, httpMethod, parameters, summary, notes, responseClass, errorResponses, resource, consumes, produces) {
var parameter, v, _i, _j, _len, _len1, _ref, _ref1, _ref2,
_this = this;
this.nickname = nickname;
this.path = path;
this.httpMethod = httpMethod;
this.parameters = parameters != null ? parameters : [];
this.summary = summary;
this.notes = notes;
this.responseClass = responseClass;
this.errorResponses = errorResponses;
this.resource = resource;
this.consumes = consumes;
this.produces = produces;
this["do"] = __bind(this["do"], this);
if (this.nickname == null) {
this.resource.api.fail("SwaggerOperations must have a nickname.");
}
if (this.path == null) {
this.resource.api.fail("SwaggerOperation " + nickname + " is missing path.");
}
if (this.httpMethod == null) {
this.resource.api.fail("SwaggerOperation " + nickname + " is missing httpMethod.");
}
this.path = this.path.replace('{format}', 'json');
this.httpMethod = this.httpMethod.toLowerCase();
this.isGetMethod = this.httpMethod === "get";
this.resourceName = this.resource.name;
if (((_ref = this.responseClass) != null ? _ref.toLowerCase() : void 0) === 'void') {
this.responseClass = void 0;
}
if (this.responseClass != null) {
this.responseClassSignature = this.getSignature(this.responseClass, this.resource.models);
this.responseSampleJSON = this.getSampleJSON(this.responseClass, this.resource.models);
}
this.errorResponses = this.errorResponses || [];
_ref1 = this.parameters;
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
parameter = _ref1[_i];
parameter.name = parameter.name || parameter.dataType;
if (parameter.dataType.toLowerCase() === 'boolean') {
parameter.allowableValues = {};
parameter.allowableValues.values = this.resource.api.booleanValues;
}
parameter.signature = this.getSignature(parameter.dataType, this.resource.models);
parameter.sampleJSON = this.getSampleJSON(parameter.dataType, this.resource.models);
if (parameter.allowableValues != null) {
if (parameter.allowableValues.valueType === "RANGE") {
parameter.isRange = true;
} else {
parameter.isList = true;
}
if (parameter.allowableValues.values != null) {
parameter.allowableValues.descriptiveValues = [];
_ref2 = parameter.allowableValues.values;
for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
v = _ref2[_j];
if ((parameter.defaultValue != null) && parameter.defaultValue === v) {
parameter.allowableValues.descriptiveValues.push({
value: v,
isDefault: true
});
} else {
parameter.allowableValues.descriptiveValues.push({
value: v,
isDefault: false
});
}
}
}
}
}
this.resource[this.nickname] = function(args, callback, error) {
return _this["do"](args, callback, error);
};
}
SwaggerOperation.prototype.isListType = function(dataType) {
if (dataType.indexOf('[') >= 0) {
return dataType.substring(dataType.indexOf('[') + 1, dataType.indexOf(']'));
} else {
return void 0;
}
};
SwaggerOperation.prototype.getSignature = function(dataType, models) {
var isPrimitive, listType;
listType = this.isListType(dataType);
isPrimitive = ((listType != null) && models[listType]) || (models[dataType] != null) ? false : true;
if (isPrimitive) {
return dataType;
} else {
if (listType != null) {
return models[listType].getMockSignature();
} else {
return models[dataType].getMockSignature();
}
}
};
SwaggerOperation.prototype.getSampleJSON = function(dataType, models) {
var isPrimitive, listType, val;
listType = this.isListType(dataType);
isPrimitive = ((listType != null) && models[listType]) || (models[dataType] != null) ? false : true;
val = isPrimitive ? void 0 : (listType != null ? models[listType].createJSONSample() : models[dataType].createJSONSample());
if (val) {
val = listType ? [val] : val;
return JSON.stringify(val, null, 2);
}
};
SwaggerOperation.prototype["do"] = function(args, callback, error) {
var body, headers;
if (args == null) {
args = {};
}
if ((typeof args) === "function") {
error = callback;
callback = args;
args = {};
}
if (error == null) {
error = function(xhr, textStatus, error) {
return console.log(xhr, textStatus, error);
};
}
if (callback == null) {
callback = function(data) {
return console.log(data);
};
}
if (args.headers != null) {
headers = args.headers;
delete args.headers;
}
if (args.body != null) {
body = args.body;
delete args.body;
}
return new SwaggerRequest(this.httpMethod, this.urlify(args), headers, body, callback, error, this);
};
SwaggerOperation.prototype.pathJson = function() {
return this.path.replace("{format}", "json");
};
SwaggerOperation.prototype.pathXml = function() {
return this.path.replace("{format}", "xml");
};
SwaggerOperation.prototype.urlify = function(args, includeApiKey) {
var param, queryParams, reg, url, _i, _len, _ref;
if (includeApiKey == null) {
includeApiKey = true;
}
url = this.resource.basePath + this.pathJson();
_ref = this.parameters;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
param = _ref[_i];
if (param.paramType === 'path') {
if (args[param.name]) {
reg = new RegExp('\{' + param.name + '[^\}]*\}', 'gi');
url = url.replace(reg, encodeURIComponent(args[param.name]));
delete args[param.name];
} else {
throw "" + param.name + " is a required path param.";
}
}
}
if (includeApiKey && (this.resource.api.api_key != null) && this.resource.api.api_key.length > 0) {
args[this.apiKeyName] = this.resource.api.api_key;
}
if (this.supportHeaderParams()) {
queryParams = jQuery.param(this.getQueryParams(args, includeApiKey));
} else {
queryParams = jQuery.param(this.getQueryAndHeaderParams(args, includeApiKey));
}
if ((queryParams != null) && queryParams.length > 0) {
url += "?" + queryParams;
}
return url;
};
SwaggerOperation.prototype.supportHeaderParams = function() {
return this.resource.api.supportHeaderParams;
};
SwaggerOperation.prototype.supportedSubmitMethods = function() {
return this.resource.api.supportedSubmitMethods;
};
SwaggerOperation.prototype.getQueryAndHeaderParams = function(args, includeApiKey) {
if (includeApiKey == null) {
includeApiKey = true;
}
return this.getMatchingParams(['query', 'header'], args, includeApiKey);
};
SwaggerOperation.prototype.getQueryParams = function(args, includeApiKey) {
if (includeApiKey == null) {
includeApiKey = true;
}
return this.getMatchingParams(['query'], args, includeApiKey);
};
SwaggerOperation.prototype.getHeaderParams = function(args, includeApiKey) {
if (includeApiKey == null) {
includeApiKey = true;
}
return this.getMatchingParams(['header'], args, includeApiKey);
};
SwaggerOperation.prototype.getMatchingParams = function(paramTypes, args, includeApiKey) {
var matchingParams, name, param, value, _i, _len, _ref, _ref1;
matchingParams = {};
_ref = this.parameters;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
param = _ref[_i];
if ((jQuery.inArray(param.paramType, paramTypes) >= 0) && args[param.name]) {
matchingParams[param.name] = args[param.name];
}
}
if (includeApiKey && (this.resource.api.api_key != null) && this.resource.api.api_key.length > 0) {
matchingParams[this.resource.api.apiKeyName] = this.resource.api.api_key;
}
if (jQuery.inArray('header', paramTypes) >= 0) {
_ref1 = this.resource.api.headers;
for (name in _ref1) {
value = _ref1[name];
matchingParams[name] = value;
}
}
return matchingParams;
};
SwaggerOperation.prototype.help = function() {
var parameter, _i, _len, _ref;
_ref = this.parameters;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
parameter = _ref[_i];
console.log(" " + parameter.name + (parameter.required ? ' (required)' : '') + " - " + parameter.description);
}
return this;
};
return SwaggerOperation;
})();
SwaggerRequest = (function() {
function SwaggerRequest(type, url, headers, body, successCallback, errorCallback, operation) {
var obj,
_this = this;
this.type = type;
this.url = url;
this.headers = headers;
this.body = body;
this.successCallback = successCallback;
this.errorCallback = errorCallback;
this.operation = operation;
if (this.type == null) {
throw "SwaggerRequest type is required (get/post/put/delete).";
}
if (this.url == null) {
throw "SwaggerRequest url is required.";
}
if (this.successCallback == null) {
throw "SwaggerRequest successCallback is required.";
}
if (this.errorCallback == null) {
throw "SwaggerRequest error callback is required.";
}
if (this.operation == null) {
throw "SwaggerRequest operation is required.";
}
if (this.operation.resource.api.verbose) {
console.log(this.asCurl());
}
this.headers || (this.headers = {});
if (this.operation.resource.api.api_key != null) {
this.headers[this.apiKeyName] = this.operation.resource.api.api_key;
}
if (this.headers.mock == null) {
obj = {
type: this.type,
url: this.url,
data: JSON.stringify(this.body),
dataType: 'json',
error: function(xhr, textStatus, error) {
return _this.errorCallback(xhr, textStatus, error);
},
success: function(data) {
return _this.successCallback(data);
}
};
if (obj.type.toLowerCase() === "post" || obj.type.toLowerCase() === "put") {
obj.contentType = "application/json";
}
jQuery.ajax(obj);
}
}
SwaggerRequest.prototype.asCurl = function() {
var header_args, k, v;
header_args = (function() {
var _ref, _results;
_ref = this.headers;
_results = [];
for (k in _ref) {
v = _ref[k];
_results.push("--header \"" + k + ": " + v + "\"");
}
return _results;
}).call(this);
return "curl " + (header_args.join(" ")) + " " + this.url;
};
return SwaggerRequest;
})();
window.SwaggerApi = SwaggerApi;
window.SwaggerResource = SwaggerResource;
window.SwaggerOperation = SwaggerOperation;
window.SwaggerRequest = SwaggerRequest;
window.SwaggerModelProperty = SwaggerModelProperty;
}).call(this);

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save