mirror of
https://github.com/mxpv/podsync.git
synced 2024-05-11 05:55:04 +00:00
Implement create feed backend API
This commit is contained in:
@@ -1,26 +1,41 @@
|
||||
using System.IO;
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Serialization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Podsync.Helpers;
|
||||
using Podsync.Services;
|
||||
using Podsync.Services.Builder;
|
||||
using Podsync.Services.Feed;
|
||||
using Podsync.Services.Links;
|
||||
using Podsync.Services.Resolver;
|
||||
using Podsync.Services.Storage;
|
||||
|
||||
namespace Podsync.Controllers
|
||||
{
|
||||
[Route("feed")]
|
||||
public class FeedController : Controller
|
||||
{
|
||||
private const int DefaultPageSize = 50;
|
||||
|
||||
private readonly XmlSerializer _serializer = new XmlSerializer(typeof(Rss));
|
||||
|
||||
private readonly IRssBuilder _rssBuilder;
|
||||
private readonly ILinkService _linkService;
|
||||
private readonly IStorageService _storageService;
|
||||
|
||||
public FeedController(IRssBuilder rssBuilder)
|
||||
public FeedController(IRssBuilder rssBuilder, ILinkService linkService, IStorageService storageService)
|
||||
{
|
||||
_rssBuilder = rssBuilder;
|
||||
_linkService = linkService;
|
||||
_storageService = storageService;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("{feedId}")]
|
||||
public async Task<IActionResult> Index(string feedId)
|
||||
[ValidateModelState]
|
||||
public async Task<IActionResult> Index([Required] string feedId)
|
||||
{
|
||||
var rss = await _rssBuilder.Query(feedId);
|
||||
|
||||
@@ -34,5 +49,24 @@ namespace Podsync.Controllers
|
||||
|
||||
return Content(body, "text/xml");
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("create")]
|
||||
[ValidateModelState]
|
||||
public Task<string> Create([FromBody] CreateFeedRequest request)
|
||||
{
|
||||
var linkInfo = _linkService.Parse(new Uri(request.Url));
|
||||
|
||||
var feed = new FeedMetadata
|
||||
{
|
||||
Provider = linkInfo.Provider,
|
||||
LinkType = linkInfo.LinkType,
|
||||
Id = linkInfo.Id,
|
||||
Quality = request.Quality ?? ResolveType.VideoHigh,
|
||||
PageSize = request.PageSize ?? DefaultPageSize
|
||||
};
|
||||
|
||||
return _storageService.Save(feed);
|
||||
}
|
||||
}
|
||||
}
|
28
src/Podsync/Helpers/ValidateModelStateAttribute.cs
Normal file
28
src/Podsync/Helpers/ValidateModelStateAttribute.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
|
||||
namespace Podsync.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// Validate the model state prior to action execution.
|
||||
/// See http://www.strathweb.com/2015/06/action-filters-service-filters-type-filters-asp-net-5-mvc-6/
|
||||
/// </summary>
|
||||
public class ValidateModelStateAttribute : ActionFilterAttribute
|
||||
{
|
||||
private readonly bool _validateNotNull;
|
||||
|
||||
public ValidateModelStateAttribute(bool validateNotNull = true)
|
||||
{
|
||||
_validateNotNull = validateNotNull;
|
||||
}
|
||||
|
||||
public override void OnActionExecuting(ActionExecutingContext context)
|
||||
{
|
||||
if (!context.ModelState.IsValid || _validateNotNull && context.ActionArguments.Any(p => p.Value == null))
|
||||
{
|
||||
context.Result = new BadRequestObjectResult(context.ModelState);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
17
src/Podsync/Services/CreateFeedRequest.cs
Normal file
17
src/Podsync/Services/CreateFeedRequest.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Podsync.Services.Resolver;
|
||||
|
||||
namespace Podsync.Services
|
||||
{
|
||||
public class CreateFeedRequest
|
||||
{
|
||||
[Required]
|
||||
[Url]
|
||||
public string Url { get; set; }
|
||||
|
||||
public ResolveType? Quality { get; set; }
|
||||
|
||||
[Range(50, 150)]
|
||||
public int? PageSize { get; set; }
|
||||
}
|
||||
}
|
@@ -2,7 +2,7 @@
|
||||
{
|
||||
public enum ResolveType
|
||||
{
|
||||
VideoHigh,
|
||||
VideoHigh = 0,
|
||||
VideoLow,
|
||||
AudioHigh,
|
||||
AudioLow
|
||||
|
@@ -59,10 +59,6 @@ namespace Podsync
|
||||
app.UseDeveloperExceptionPage();
|
||||
app.UseBrowserLink();
|
||||
}
|
||||
else
|
||||
{
|
||||
app.UseExceptionHandler("/Home/Error");
|
||||
}
|
||||
|
||||
app.UseStaticFiles();
|
||||
|
||||
|
55
test/Podsync.Tests/Controllers/FeedControllerTests.cs
Normal file
55
test/Podsync.Tests/Controllers/FeedControllerTests.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Podsync.Services;
|
||||
using Podsync.Services.Resolver;
|
||||
using Xunit;
|
||||
|
||||
namespace Podsync.Tests.Controllers
|
||||
{
|
||||
public class FeedControllerTests : TestServer<Startup>
|
||||
{
|
||||
[Fact]
|
||||
public async Task ValidateCreateNullTest()
|
||||
{
|
||||
var response = await Client.PostAsync("/feed/create", new StringContent("", Encoding.UTF8, "application/json"));
|
||||
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, null, null)]
|
||||
[InlineData("a", null, null)]
|
||||
[InlineData("http://youtube.com", null, 0)]
|
||||
[InlineData("http://youtube.com", null, 25)]
|
||||
[InlineData("http://youtube.com", null, 151)]
|
||||
public async Task ValidateCreateTest(string url, ResolveType? quality, int? pageSize)
|
||||
{
|
||||
var feed = new CreateFeedRequest
|
||||
{
|
||||
Url = url,
|
||||
Quality = quality,
|
||||
PageSize = pageSize
|
||||
};
|
||||
|
||||
var response = await Client.PostAsync("/feed/create", MakeHttpContent(feed));
|
||||
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CreateFeedTest()
|
||||
{
|
||||
var feed = new CreateFeedRequest
|
||||
{
|
||||
Url = "https://www.youtube.com/channel/UCKy1dAqELo0zrOtPkf0eTMw",
|
||||
Quality = ResolveType.AudioLow,
|
||||
};
|
||||
|
||||
var response = await Client.PostAsync("/feed/create", MakeHttpContent(feed));
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var id = await response.Content.ReadAsStringAsync();
|
||||
Assert.NotNull(id);
|
||||
}
|
||||
}
|
||||
}
|
17
test/Podsync.Tests/Controllers/StatusControllerTests.cs
Normal file
17
test/Podsync.Tests/Controllers/StatusControllerTests.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace Podsync.Tests.Controllers
|
||||
{
|
||||
public class StatusControllerTests : TestServer<Startup>
|
||||
{
|
||||
[Fact]
|
||||
public async Task StatusTest()
|
||||
{
|
||||
var response = await Client.GetAsync("/status");
|
||||
var content = await response.Content.ReadAsStringAsync();
|
||||
|
||||
Assert.Contains("Path: /status", content);
|
||||
}
|
||||
}
|
||||
}
|
37
test/Podsync.Tests/Controllers/TestServer.cs
Normal file
37
test/Podsync.Tests/Controllers/TestServer.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Podsync.Tests.Controllers
|
||||
{
|
||||
public abstract class TestServer<TStartup> : TestBase, IDisposable where TStartup : class
|
||||
{
|
||||
private readonly TestServer _server;
|
||||
|
||||
protected TestServer()
|
||||
{
|
||||
var builder = new WebHostBuilder().UseStartup<TStartup>();
|
||||
_server = new TestServer(builder);
|
||||
|
||||
Client = _server.CreateClient();
|
||||
Client.BaseAddress = new Uri("http://localhost:5000");
|
||||
}
|
||||
|
||||
protected HttpClient Client { get; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Client.Dispose();
|
||||
_server.Dispose();
|
||||
}
|
||||
|
||||
public static HttpContent MakeHttpContent(object obj)
|
||||
{
|
||||
var json = JsonConvert.SerializeObject(obj);
|
||||
return new StringContent(json, Encoding.UTF8, "application/json");
|
||||
}
|
||||
}
|
||||
}
|
@@ -4,6 +4,7 @@
|
||||
|
||||
"dependencies": {
|
||||
"dotnet-test-xunit": "2.2.0-preview2-build1029",
|
||||
"Microsoft.AspNetCore.TestHost": "1.0.1",
|
||||
"Microsoft.Extensions.Configuration.UserSecrets": "1.0.0",
|
||||
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0",
|
||||
"Microsoft.NETCore.App": {
|
||||
@@ -23,5 +24,13 @@
|
||||
"portable-net45+win8"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"buildOptions": {
|
||||
"copyToOutput": [
|
||||
"project.json"
|
||||
]
|
||||
},
|
||||
|
||||
"userSecretsId": "aspnet-Podsync-20161004104901"
|
||||
}
|
||||
|
Reference in New Issue
Block a user