1
0
mirror of https://github.com/Sonarr/Sonarr.git synced 2024-12-16 11:37:58 +02:00

New: CORS support on the API (for developing against the API)

This commit is contained in:
Mark McDowall 2014-11-05 16:20:00 -08:00
parent 4665682ea6
commit 3ee58979ec
7 changed files with 121 additions and 4 deletions

View File

@ -0,0 +1,12 @@
namespace NzbDrone.Api.Extensions
{
public static class AccessControlHeaders
{
public const string RequestMethod = "Access-Control-Request-Method";
public const string RequestHeaders = "Access-Control-Request-Headers";
public const string AllowOrigin = "Access-Control-Allow-Origin";
public const string AllowMethods = "Access-Control-Allow-Methods";
public const string AllowHeaders = "Access-Control-Allow-Headers";
}
}

View File

@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Nancy;
using Nancy.Bootstrapper;
namespace NzbDrone.Api.Extensions.Pipelines
{
public class CorsPipeline : IRegisterNancyPipeline
{
public void Register(IPipelines pipelines)
{
pipelines.AfterRequest.AddItemToEndOfPipeline(Handle);
}
private void Handle(NancyContext context)
{
if (context == null || context.Response.Headers.ContainsKey(AccessControlHeaders.AllowOrigin))
{
return;
}
ApplyResponseHeaders(context.Response, context.Request);
}
private static void ApplyResponseHeaders(Response response, Request request)
{
var allowedMethods = "GET, OPTIONS, PATCH, POST, PUT, DELETE";
if (response.Headers.ContainsKey("Allow"))
{
allowedMethods = response.Headers["Allow"];
}
var requestedHeaders = String.Join(", ", request.Headers[AccessControlHeaders.RequestHeaders]);
response.Headers.Add(AccessControlHeaders.AllowOrigin, "*");
response.Headers.Add(AccessControlHeaders.AllowMethods, allowedMethods);
if (request.Headers[AccessControlHeaders.RequestHeaders].Any())
{
response.Headers.Add(AccessControlHeaders.AllowHeaders, requestedHeaders);
}
}
}
}

View File

@ -96,6 +96,8 @@
<Compile Include="ClientSchema\SelectOption.cs" />
<Compile Include="Commands\CommandModule.cs" />
<Compile Include="Commands\CommandResource.cs" />
<Compile Include="Extensions\AccessControlHeaders.cs" />
<Compile Include="Extensions\Pipelines\CorsPipeline.cs" />
<Compile Include="RemotePathMappings\RemotePathMappingModule.cs" />
<Compile Include="RemotePathMappings\RemotePathMappingResource.cs" />
<Compile Include="Config\UiConfigModule.cs" />

View File

@ -45,7 +45,6 @@ public PagingResource<TResource> GetPaged(int pageNumber, int pageSize, string s
request.AddParameter("sortKey", sortKey);
request.AddParameter("sortDir", sortDir);
return Get<PagingResource<TResource>>(request);
}
public TResource Post(TResource body, HttpStatusCode statusCode = HttpStatusCode.Created)

View File

@ -0,0 +1,57 @@
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Api.Extensions;
using RestSharp;
namespace NzbDrone.Integration.Test
{
[TestFixture]
public class CorsFixture : IntegrationTest
{
private RestRequest BuildRequest()
{
var request = new RestRequest("series");
request.AddHeader(AccessControlHeaders.RequestMethod, "POST");
return request;
}
[Test]
public void should_not_have_allow_headers_in_response_when_not_included_in_the_request()
{
var request = BuildRequest();
var response = RestClient.Get(request);
response.Headers.Should().NotContain(h => h.Name == AccessControlHeaders.AllowHeaders);
}
[Test]
public void should_have_allow_headers_in_response_when_included_in_the_request()
{
var request = BuildRequest();
request.AddHeader(AccessControlHeaders.RequestHeaders, "X-Test");
var response = RestClient.Get(request);
response.Headers.Should().Contain(h => h.Name == AccessControlHeaders.AllowHeaders);
}
[Test]
public void should_have_allow_origin_in_response()
{
var request = BuildRequest();
var response = RestClient.Get(request);
response.Headers.Should().Contain(h => h.Name == AccessControlHeaders.AllowOrigin);
}
[Test]
public void should_have_allow_methods_in_response()
{
var request = BuildRequest();
var response = RestClient.Get(request);
response.Headers.Should().Contain(h => h.Name == AccessControlHeaders.AllowMethods);
}
}
}

View File

@ -63,7 +63,6 @@ public IntegrationTest()
}
[TestFixtureSetUp]
//[SetUp]
public void SmokeTestSetup()
{
_runner = new NzbDroneRunner();
@ -87,6 +86,8 @@ public void SmokeTestSetup()
private void InitRestClients()
{
RestClient = new RestClient(RootUrl + "api/");
RestClient.AddDefaultHeader("Authentication", _runner.ApiKey);
Series = new SeriesClient(RestClient, _runner.ApiKey);
Releases = new ReleaseClient(RestClient, _runner.ApiKey);
RootFolders = new ClientBase<RootFolderResource>(RestClient, _runner.ApiKey);
@ -99,7 +100,6 @@ private void InitRestClients()
}
[TestFixtureTearDown]
//[TearDown]
public void SmokeTestTearDown()
{
_runner.KillAll();
@ -153,6 +153,5 @@ protected void ConnectSignalR()
_signalrConnection.Received += json => _signalRReceived.Add(Json.Deserialize<SignalRMessage>(json)); ;
}
}
}

View File

@ -109,6 +109,7 @@
<Compile Include="Client\ReleaseClient.cs" />
<Compile Include="Client\SeriesClient.cs" />
<Compile Include="CommandIntegerationTests.cs" />
<Compile Include="CorsFixture.cs" />
<Compile Include="EpisodeIntegrationTests.cs" />
<Compile Include="HistoryIntegrationTest.cs" />
<Compile Include="IndexerIntegrationFixture.cs" />