From ed9f238edade41379e577a713e232a921a1ec130 Mon Sep 17 00:00:00 2001 From: Chris R Date: Wed, 20 May 2015 09:10:28 -0700 Subject: [PATCH 1/3] Add build infrastructure. --- .gitattributes | 50 ++++++++++++++++++++++++++++++++++++++++++++ .gitignore | 26 +++++++++++++++++++++++ NuGet.Config | 7 +++++++ NuGet.master.config | 7 +++++++ NuGet.release.config | 7 +++++++ build.cmd | 28 +++++++++++++++++++++++++ build.sh | 38 +++++++++++++++++++++++++++++++++ makefile.shade | 7 +++++++ 8 files changed, 170 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 NuGet.Config create mode 100644 NuGet.master.config create mode 100644 NuGet.release.config create mode 100644 build.cmd create mode 100644 build.sh create mode 100644 makefile.shade diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..bdaa5ba --- /dev/null +++ b/.gitattributes @@ -0,0 +1,50 @@ +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain + +*.jpg binary +*.png binary +*.gif binary + +*.cs text=auto diff=csharp +*.vb text=auto +*.resx text=auto +*.c text=auto +*.cpp text=auto +*.cxx text=auto +*.h text=auto +*.hxx text=auto +*.py text=auto +*.rb text=auto +*.java text=auto +*.html text=auto +*.htm text=auto +*.css text=auto +*.scss text=auto +*.sass text=auto +*.less text=auto +*.js text=auto +*.lisp text=auto +*.clj text=auto +*.sql text=auto +*.php text=auto +*.lua text=auto +*.m text=auto +*.asm text=auto +*.erl text=auto +*.fs text=auto +*.fsx text=auto +*.hs text=auto + +*.csproj text=auto +*.vbproj text=auto +*.fsproj text=auto +*.dbproj text=auto +*.sln text=auto eol=crlf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..216e8d9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,26 @@ +[Oo]bj/ +[Bb]in/ +TestResults/ +.nuget/ +*.sln.ide/ +_ReSharper.*/ +packages/ +artifacts/ +PublishProfiles/ +*.user +*.suo +*.cache +*.docstates +_ReSharper.* +nuget.exe +*net45.csproj +*net451.csproj +*k10.csproj +*.psess +*.vsp +*.pidb +*.userprefs +*DS_Store +*.ncrunchsolution +*.*sdf +*.ipch \ No newline at end of file diff --git a/NuGet.Config b/NuGet.Config new file mode 100644 index 0000000..46c3b3e --- /dev/null +++ b/NuGet.Config @@ -0,0 +1,7 @@ + + + + + + + diff --git a/NuGet.master.config b/NuGet.master.config new file mode 100644 index 0000000..e2edffc --- /dev/null +++ b/NuGet.master.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/NuGet.release.config b/NuGet.release.config new file mode 100644 index 0000000..1978dc0 --- /dev/null +++ b/NuGet.release.config @@ -0,0 +1,7 @@ + + + + + + + diff --git a/build.cmd b/build.cmd new file mode 100644 index 0000000..41025af --- /dev/null +++ b/build.cmd @@ -0,0 +1,28 @@ +@echo off +cd %~dp0 + +SETLOCAL +SET CACHED_NUGET=%LocalAppData%\NuGet\NuGet.exe + +IF EXIST %CACHED_NUGET% goto copynuget +echo Downloading latest version of NuGet.exe... +IF NOT EXIST %LocalAppData%\NuGet md %LocalAppData%\NuGet +@powershell -NoProfile -ExecutionPolicy unrestricted -Command "$ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest 'https://www.nuget.org/nuget.exe' -OutFile '%CACHED_NUGET%'" + +:copynuget +IF EXIST .nuget\nuget.exe goto restore +md .nuget +copy %CACHED_NUGET% .nuget\nuget.exe > nul + +:restore +IF EXIST packages\KoreBuild goto run +.nuget\NuGet.exe install KoreBuild -ExcludeVersion -o packages -nocache -pre +.nuget\NuGet.exe install Sake -version 0.2 -o packages -ExcludeVersion + +IF "%SKIP_DNX_INSTALL%"=="1" goto run +CALL packages\KoreBuild\build\dnvm upgrade -runtime CLR -arch x86 +CALL packages\KoreBuild\build\dnvm install default -runtime CoreCLR -arch x86 + +:run +CALL packages\KoreBuild\build\dnvm use default -runtime CLR -arch x86 +packages\Sake\tools\Sake.exe -I packages\KoreBuild\build -f makefile.shade %* diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..c8cc2a7 --- /dev/null +++ b/build.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +if test `uname` = Darwin; then + cachedir=~/Library/Caches/KBuild +else + if [ -z $XDG_DATA_HOME ]; then + cachedir=$HOME/.local/share + else + cachedir=$XDG_DATA_HOME; + fi +fi +mkdir -p $cachedir + +url=https://www.nuget.org/nuget.exe + +if test ! -f $cachedir/nuget.exe; then + wget -O $cachedir/nuget.exe $url 2>/dev/null || curl -o $cachedir/nuget.exe --location $url /dev/null +fi + +if test ! -e .nuget; then + mkdir .nuget + cp $cachedir/nuget.exe .nuget/nuget.exe +fi + +if test ! -d packages/KoreBuild; then + mono .nuget/nuget.exe install KoreBuild -ExcludeVersion -o packages -nocache -pre + mono .nuget/nuget.exe install Sake -version 0.2 -o packages -ExcludeVersion +fi + +if ! type dnvm > /dev/null 2>&1; then + source packages/KoreBuild/build/dnvm.sh +fi + +if ! type dnx > /dev/null 2>&1; then + dnvm upgrade +fi + +mono packages/Sake/tools/Sake.exe -I packages/KoreBuild/build -f makefile.shade "$@" diff --git a/makefile.shade b/makefile.shade new file mode 100644 index 0000000..562494d --- /dev/null +++ b/makefile.shade @@ -0,0 +1,7 @@ + +var VERSION='0.1' +var FULL_VERSION='0.1' +var AUTHORS='Microsoft Open Technologies, Inc.' + +use-standard-lifecycle +k-standard-goals From a14bb69d6a5d519b729879715269d768e10e39fc Mon Sep 17 00:00:00 2001 From: Chris R Date: Fri, 22 May 2015 12:53:34 -0700 Subject: [PATCH 2/3] Rough outline of middleware, sample, and test projects. --- .gitignore | 3 +- ResponseCaching.sln | 50 ++++++ global.json | 3 + .../ResponseCachingSample.xproj | 19 +++ samples/ResponseCachingSample/Startup.cs | 33 ++++ samples/ResponseCachingSample/project.json | 33 ++++ .../CachingContext.cs | 143 ++++++++++++++++++ .../Microsoft.AspNet.ResponseCaching.xproj | 20 +++ .../Properties/AssemblyInfo.cs | 8 + .../ResponseCacheEntry.cs | 14 ++ .../ResponseCachingExtensions.cs | 15 ++ .../ResponseCachingMiddleware.cs | 61 ++++++++ .../project.json | 15 ++ .../CachingContextTests.cs | 33 ++++ ...crosoft.AspNet.ResponseCaching.Tests.xproj | 20 +++ .../project.json | 15 ++ 16 files changed, 484 insertions(+), 1 deletion(-) create mode 100644 ResponseCaching.sln create mode 100644 global.json create mode 100644 samples/ResponseCachingSample/ResponseCachingSample.xproj create mode 100644 samples/ResponseCachingSample/Startup.cs create mode 100644 samples/ResponseCachingSample/project.json create mode 100644 src/Microsoft.AspNet.ResponseCaching/CachingContext.cs create mode 100644 src/Microsoft.AspNet.ResponseCaching/Microsoft.AspNet.ResponseCaching.xproj create mode 100644 src/Microsoft.AspNet.ResponseCaching/Properties/AssemblyInfo.cs create mode 100644 src/Microsoft.AspNet.ResponseCaching/ResponseCacheEntry.cs create mode 100644 src/Microsoft.AspNet.ResponseCaching/ResponseCachingExtensions.cs create mode 100644 src/Microsoft.AspNet.ResponseCaching/ResponseCachingMiddleware.cs create mode 100644 src/Microsoft.AspNet.ResponseCaching/project.json create mode 100644 test/Microsoft.AspNet.ResponseCaching.Tests/CachingContextTests.cs create mode 100644 test/Microsoft.AspNet.ResponseCaching.Tests/Microsoft.AspNet.ResponseCaching.Tests.xproj create mode 100644 test/Microsoft.AspNet.ResponseCaching.Tests/project.json diff --git a/.gitignore b/.gitignore index 216e8d9..be311a1 100644 --- a/.gitignore +++ b/.gitignore @@ -23,4 +23,5 @@ nuget.exe *DS_Store *.ncrunchsolution *.*sdf -*.ipch \ No newline at end of file +*.ipch +project.lock.json \ No newline at end of file diff --git a/ResponseCaching.sln b/ResponseCaching.sln new file mode 100644 index 0000000..358a798 --- /dev/null +++ b/ResponseCaching.sln @@ -0,0 +1,50 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.22823.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.ResponseCaching", "src\Microsoft.AspNet.ResponseCaching\Microsoft.AspNet.ResponseCaching.xproj", "{D1031270-DBD3-4F02-A3DC-3E7DADE8EBE6}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{367AABAF-E03C-4491-A9A7-BDDE8903D1B4}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{C51DF5BD-B53D-4795-BC01-A9AB066BF286}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{89A50974-E9D4-4F87-ACF2-6A6005E64931}" +EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ResponseCachingSample", "samples\ResponseCachingSample\ResponseCachingSample.xproj", "{1139BDEE-FA15-474D-8855-0AB91F23CF26}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F787A492-C2FF-4569-A663-F8F24B900657}" + ProjectSection(SolutionItems) = preProject + global.json = global.json + EndProjectSection +EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.ResponseCaching.Tests", "test\Microsoft.AspNet.ResponseCaching.Tests\Microsoft.AspNet.ResponseCaching.Tests.xproj", "{151B2027-3936-44B9-A4A0-E1E5902125AB}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D1031270-DBD3-4F02-A3DC-3E7DADE8EBE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D1031270-DBD3-4F02-A3DC-3E7DADE8EBE6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D1031270-DBD3-4F02-A3DC-3E7DADE8EBE6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D1031270-DBD3-4F02-A3DC-3E7DADE8EBE6}.Release|Any CPU.Build.0 = Release|Any CPU + {1139BDEE-FA15-474D-8855-0AB91F23CF26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1139BDEE-FA15-474D-8855-0AB91F23CF26}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1139BDEE-FA15-474D-8855-0AB91F23CF26}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1139BDEE-FA15-474D-8855-0AB91F23CF26}.Release|Any CPU.Build.0 = Release|Any CPU + {151B2027-3936-44B9-A4A0-E1E5902125AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {151B2027-3936-44B9-A4A0-E1E5902125AB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {151B2027-3936-44B9-A4A0-E1E5902125AB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {151B2027-3936-44B9-A4A0-E1E5902125AB}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {D1031270-DBD3-4F02-A3DC-3E7DADE8EBE6} = {367AABAF-E03C-4491-A9A7-BDDE8903D1B4} + {1139BDEE-FA15-474D-8855-0AB91F23CF26} = {C51DF5BD-B53D-4795-BC01-A9AB066BF286} + {151B2027-3936-44B9-A4A0-E1E5902125AB} = {89A50974-E9D4-4F87-ACF2-6A6005E64931} + EndGlobalSection +EndGlobal diff --git a/global.json b/global.json new file mode 100644 index 0000000..397ac5f --- /dev/null +++ b/global.json @@ -0,0 +1,3 @@ +{ + "projects": ["src"] +} \ No newline at end of file diff --git a/samples/ResponseCachingSample/ResponseCachingSample.xproj b/samples/ResponseCachingSample/ResponseCachingSample.xproj new file mode 100644 index 0000000..2403e53 --- /dev/null +++ b/samples/ResponseCachingSample/ResponseCachingSample.xproj @@ -0,0 +1,19 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 1139bdee-fa15-474d-8855-0ab91f23cf26 + ResponseCachingSample + ..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\artifacts\bin\$(MSBuildProjectName)\ + + + 2.0 + 2931 + + + \ No newline at end of file diff --git a/samples/ResponseCachingSample/Startup.cs b/samples/ResponseCachingSample/Startup.cs new file mode 100644 index 0000000..1ca6d9a --- /dev/null +++ b/samples/ResponseCachingSample/Startup.cs @@ -0,0 +1,33 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Microsoft.AspNet.Builder; +using Microsoft.AspNet.Http; +using Microsoft.Framework.DependencyInjection; +using Microsoft.Net.Http.Headers; + +namespace ResponseCachingSample +{ + public class Startup + { + public void ConfigureServices(IServiceCollection services) + { + services.AddCaching(); + } + + public void Configure(IApplicationBuilder app) + { + app.UseResponseCaching(); + app.Run(async (context) => + { + context.Response.GetTypedHeaders().CacheControl = new CacheControlHeaderValue() + { + Public = true, + MaxAge = TimeSpan.FromSeconds(10) + }; + await context.Response.WriteAsync("Hello World! " + DateTime.UtcNow); + }); + } + } +} diff --git a/samples/ResponseCachingSample/project.json b/samples/ResponseCachingSample/project.json new file mode 100644 index 0000000..ca19e78 --- /dev/null +++ b/samples/ResponseCachingSample/project.json @@ -0,0 +1,33 @@ +{ + "webroot": "wwwroot", + "version": "1.0.0-*", + + "dependencies": { + "Microsoft.AspNet.ResponseCaching": "1.0.0-*", + "Microsoft.AspNet.Server.IIS": "1.0.0-*", + "Microsoft.AspNet.Server.WebListener": "1.0.0-*", + "Microsoft.Framework.Caching.Memory": "1.0.0-*" + }, + + "commands": { + "web": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.WebListener --server.urls http://localhost:5000" + }, + + "frameworks": { + "dnx451": { }, + "dnxcore50": { } + }, + + "publishExclude": [ + "node_modules", + "bower_components", + "**.xproj", + "**.user", + "**.vspscc" + ], + "exclude": [ + "wwwroot", + "node_modules", + "bower_components" + ] +} diff --git a/src/Microsoft.AspNet.ResponseCaching/CachingContext.cs b/src/Microsoft.AspNet.ResponseCaching/CachingContext.cs new file mode 100644 index 0000000..c5586ce --- /dev/null +++ b/src/Microsoft.AspNet.ResponseCaching/CachingContext.cs @@ -0,0 +1,143 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNet.Http; +using Microsoft.Framework.Caching.Memory; + +namespace Microsoft.AspNet.ResponseCaching +{ + internal class CachingContext + { + private string _cacheKey; + + public CachingContext(HttpContext httpContext, IMemoryCache cache) + { + HttpContext = httpContext; + Cache = cache; + } + + private HttpContext HttpContext { get; } + + private IMemoryCache Cache { get; } + + private Stream OriginalResponseStream { get; set; } + + private MemoryStream Buffer { get; set; } + + internal bool ResponseStarted { get; set; } + + private bool CacheResponse { get; set; } + + internal bool CheckRequestAllowsCaching() + { + // Verify the method + // TODO: What other methods should be supported? + if (!string.Equals("GET", HttpContext.Request.Method, StringComparison.OrdinalIgnoreCase)) + { + return false; + } + + // Verify the request headers do not opt-out of caching + // TODO: + return true; + } + + // Only QueryString is treated as case sensitive + // GET;HTTP://MYDOMAIN.COM:80/PATHBASE/PATH?QueryString + private string CreateCacheKey() + { + var request = HttpContext.Request; + return request.Method.ToUpperInvariant() + + ";" + + request.Scheme.ToUpperInvariant() + + "://" + + request.Host.Value.ToUpperInvariant() + + request.PathBase.Value.ToUpperInvariant() + + request.Path.Value.ToUpperInvariant() + + request.QueryString; + } + + internal async Task TryServeFromCacheAsync() + { + _cacheKey = CreateCacheKey(); + ResponseCacheEntry cacheEntry; + if (Cache.TryGetValue(_cacheKey, out cacheEntry)) + { + // TODO: Compare cached request headers + + // TODO: Evaluate Vary-By and select the most appropriate response + + // TODO: Content negotiation if there are multiple cached response formats? + + // TODO: Verify content freshness, or else re-validate the data? + + var response = HttpContext.Response; + // Copy the cached status code and response headers + response.StatusCode = cacheEntry.StatusCode; + foreach (var pair in cacheEntry.Headers) + { + response.Headers.SetValues(pair.Key, pair.Value); + } + + // TODO: Update cache headers (Age) + response.Headers["Served_From_Cache"] = DateTime.Now.ToString(); + + // Copy the cached response body + var body = cacheEntry.Body; + if (body.Length > 0) + { + await response.Body.WriteAsync(body, 0, body.Length); + } + return true; + } + + return false; + } + + internal void HookResponseStream() + { + // TODO: Use a wrapper stream to listen for writes (e.g. the start of the response), + // check the headers, and verify if we should cache the response. + // Then we should stream data out to the client at the same time as we buffer for the cache. + // For now we'll just buffer everything in memory before checking the response headers. + // TODO: Consider caching large responses on disk and serving them from there. + OriginalResponseStream = HttpContext.Response.Body; + Buffer = new MemoryStream(); + HttpContext.Response.Body = Buffer; + } + + internal bool OnResponseStarting() + { + // Evaluate the response headers, see if we should buffer and cache + CacheResponse = true; // TODO: + return CacheResponse; + } + + internal void FinalizeCaching() + { + if (CacheResponse) + { + // Store the buffer to cache + var cacheEntry = new ResponseCacheEntry(); + cacheEntry.StatusCode = HttpContext.Response.StatusCode; + cacheEntry.Headers = HttpContext.Response.Headers.ToList(); + cacheEntry.Body = Buffer.ToArray(); + Cache.Set(_cacheKey, cacheEntry); // TODO: Timeouts + } + + // TODO: TEMP, flush the buffer to the client + Buffer.Seek(0, SeekOrigin.Begin); + Buffer.CopyTo(OriginalResponseStream); + } + + internal void UnhookResponseStream() + { + // Unhook the response stream. + HttpContext.Response.Body = OriginalResponseStream; + } + } +} diff --git a/src/Microsoft.AspNet.ResponseCaching/Microsoft.AspNet.ResponseCaching.xproj b/src/Microsoft.AspNet.ResponseCaching/Microsoft.AspNet.ResponseCaching.xproj new file mode 100644 index 0000000..bb65aad --- /dev/null +++ b/src/Microsoft.AspNet.ResponseCaching/Microsoft.AspNet.ResponseCaching.xproj @@ -0,0 +1,20 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + + d1031270-dbd3-4f02-a3dc-3e7dade8ebe6 + Microsoft.AspNet.ResponseCaching + ..\artifacts\obj\$(MSBuildProjectName) + ..\artifacts\bin\$(MSBuildProjectName)\ + + + + 2.0 + + + diff --git a/src/Microsoft.AspNet.ResponseCaching/Properties/AssemblyInfo.cs b/src/Microsoft.AspNet.ResponseCaching/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..09bbb58 --- /dev/null +++ b/src/Microsoft.AspNet.ResponseCaching/Properties/AssemblyInfo.cs @@ -0,0 +1,8 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Reflection; +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("Microsoft.AspNet.ResponseCaching.Tests")] +[assembly: AssemblyMetadata("Serviceable", "True")] \ No newline at end of file diff --git a/src/Microsoft.AspNet.ResponseCaching/ResponseCacheEntry.cs b/src/Microsoft.AspNet.ResponseCaching/ResponseCacheEntry.cs new file mode 100644 index 0000000..f23685d --- /dev/null +++ b/src/Microsoft.AspNet.ResponseCaching/ResponseCacheEntry.cs @@ -0,0 +1,14 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; + +namespace Microsoft.AspNet.ResponseCaching +{ + internal class ResponseCacheEntry + { + public int StatusCode { get; set; } + internal IEnumerable> Headers { get; set; } + internal byte[] Body { get; set; } + } +} diff --git a/src/Microsoft.AspNet.ResponseCaching/ResponseCachingExtensions.cs b/src/Microsoft.AspNet.ResponseCaching/ResponseCachingExtensions.cs new file mode 100644 index 0000000..6632ad0 --- /dev/null +++ b/src/Microsoft.AspNet.ResponseCaching/ResponseCachingExtensions.cs @@ -0,0 +1,15 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNet.ResponseCaching; + +namespace Microsoft.AspNet.Builder +{ + public static class ResponseCachingExtensions + { + public static IApplicationBuilder UseResponseCaching(this IApplicationBuilder app) + { + return app.UseMiddleware(); + } + } +} diff --git a/src/Microsoft.AspNet.ResponseCaching/ResponseCachingMiddleware.cs b/src/Microsoft.AspNet.ResponseCaching/ResponseCachingMiddleware.cs new file mode 100644 index 0000000..0c0fda4 --- /dev/null +++ b/src/Microsoft.AspNet.ResponseCaching/ResponseCachingMiddleware.cs @@ -0,0 +1,61 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Threading.Tasks; +using Microsoft.AspNet.Builder; +using Microsoft.AspNet.Http; +using Microsoft.Framework.Caching.Memory; + +namespace Microsoft.AspNet.ResponseCaching +{ + // http://tools.ietf.org/html/rfc7234 + public class ResponseCachingMiddleware + { + private readonly RequestDelegate _next; + private readonly IMemoryCache _cache; + + public ResponseCachingMiddleware(RequestDelegate next, IMemoryCache cache) + { + _next = next; + _cache = cache; + } + + public async Task Invoke(HttpContext context) + { + var cachingContext = new CachingContext(context, _cache); + // Should we attempt any caching logic? + if (cachingContext.CheckRequestAllowsCaching()) + { + // Can this request be served from cache? + if (await cachingContext.TryServeFromCacheAsync()) + { + return; + } + + // Hook up to listen to the response stream + cachingContext.HookResponseStream(); + + try + { + await _next(context); + + // If there was no response body, check the response headers now. We can cache things like redirects. + if (!cachingContext.ResponseStarted) + { + cachingContext.OnResponseStarting(); + } + // Finalize the cache entry + cachingContext.FinalizeCaching(); + } + finally + { + cachingContext.UnhookResponseStream(); + } + } + else + { + await _next(context); + } + } + } +} diff --git a/src/Microsoft.AspNet.ResponseCaching/project.json b/src/Microsoft.AspNet.ResponseCaching/project.json new file mode 100644 index 0000000..b7f364b --- /dev/null +++ b/src/Microsoft.AspNet.ResponseCaching/project.json @@ -0,0 +1,15 @@ +{ + "version": "1.0.0-*", + "description": "Middleare that automatically caches HTTP responses on the server.", + "dependencies": { + "Microsoft.AspNet.Http.Abstractions": "1.0.0-*", + "Microsoft.Framework.Caching.Abstractions": "1.0.0-*" + }, + "frameworks" : { + "dnx451": { }, + "dnxcore50" : { + "dependencies": { + } + } + } +} diff --git a/test/Microsoft.AspNet.ResponseCaching.Tests/CachingContextTests.cs b/test/Microsoft.AspNet.ResponseCaching.Tests/CachingContextTests.cs new file mode 100644 index 0000000..d0315b5 --- /dev/null +++ b/test/Microsoft.AspNet.ResponseCaching.Tests/CachingContextTests.cs @@ -0,0 +1,33 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNet.Http.Internal; +using Microsoft.Framework.Caching.Memory; +using Xunit; + +namespace Microsoft.AspNet.ResponseCaching +{ + public class CachingContextTests + { + [Fact] + public void CheckRequestAllowsCaching_Method_GET_Allowed() + { + var httpContext = new DefaultHttpContext(); + httpContext.Request.Method = "GET"; + var context = new CachingContext(httpContext, new MemoryCache(new MemoryCacheOptions())); + + Assert.True(context.CheckRequestAllowsCaching()); + } + + [Theory] + [InlineData("POST")] + public void CheckRequestAllowsCaching_Method_Unsafe_NotAllowed(string method) + { + var httpContext = new DefaultHttpContext(); + httpContext.Request.Method = method; + var context = new CachingContext(httpContext, new MemoryCache(new MemoryCacheOptions())); + + Assert.False(context.CheckRequestAllowsCaching()); + } + } +} diff --git a/test/Microsoft.AspNet.ResponseCaching.Tests/Microsoft.AspNet.ResponseCaching.Tests.xproj b/test/Microsoft.AspNet.ResponseCaching.Tests/Microsoft.AspNet.ResponseCaching.Tests.xproj new file mode 100644 index 0000000..ee98d4b --- /dev/null +++ b/test/Microsoft.AspNet.ResponseCaching.Tests/Microsoft.AspNet.ResponseCaching.Tests.xproj @@ -0,0 +1,20 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + + 151b2027-3936-44b9-a4a0-e1e5902125ab + Microsoft.AspNet.ResponseCaching.Tests + ..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\artifacts\bin\$(MSBuildProjectName)\ + + + + 2.0 + + + diff --git a/test/Microsoft.AspNet.ResponseCaching.Tests/project.json b/test/Microsoft.AspNet.ResponseCaching.Tests/project.json new file mode 100644 index 0000000..5ad3ebb --- /dev/null +++ b/test/Microsoft.AspNet.ResponseCaching.Tests/project.json @@ -0,0 +1,15 @@ +{ + "dependencies": { + "Microsoft.AspNet.ResponseCaching": "1.0.0-*", + "xunit.runner.aspnet": "2.0.0-aspnet-*", + "Microsoft.AspNet.Http": "1.0.0-beta5-11528", + "Microsoft.Framework.Caching.Memory": "1.0.0-beta5-11395" + }, + "commands": { + "test": "xunit.runner.aspnet" + }, + "frameworks": { + "dnx451": { }, + "dnxcore50": { } + } +} From 1628d42b4369572acaaa43d1d7e48926b3b3c619 Mon Sep 17 00:00:00 2001 From: John Luo Date: Wed, 20 Jul 2016 17:03:59 -0700 Subject: [PATCH 3/3] Clean up and update to post RTM --- .gitignore | 7 +- .travis.yml | 28 +++++++ NuGet.Config | 4 +- NuGet.master.config | 7 -- NuGet.release.config | 7 -- NuGetPackageVerifier.json | 15 ++++ README.md | 2 +- ResponseCaching.sln | 18 ++--- appveyor.yml | 13 +++ build.cmd | 30 +------ build.ps1 | 67 ++++++++++++++++ build.sh | 74 ++++++++++-------- global.json | 2 +- makefile.shade | 7 -- .../ResponseCachingSample.xproj | 8 +- samples/ResponseCachingSample/Startup.cs | 22 +++++- samples/ResponseCachingSample/project.json | 53 +++++++------ samples/ResponseCachingSample/web.config | 9 +++ .../Properties/AssemblyInfo.cs | 8 -- .../project.json | 15 ---- ...icrosoft.AspNetCore.ResponseCaching.xproj} | 15 ++-- .../Properties/AssemblyInfo.cs | 11 +++ .../ResponseCachingContext.cs} | 24 +++--- .../ResponseCachingEntry.cs} | 8 +- .../ResponseCachingExtensions.cs | 4 +- .../ResponseCachingMiddleware.cs | 9 +-- .../project.json | 31 ++++++++ .../project.json | 15 ---- ...ft.AspNetCore.ResponseCaching.Tests.xproj} | 12 ++- .../ResponseCachingContextTests.cs} | 12 +-- .../project.json | 25 ++++++ tools/Key.snk | Bin 0 -> 596 bytes 32 files changed, 350 insertions(+), 212 deletions(-) create mode 100644 .travis.yml delete mode 100644 NuGet.master.config delete mode 100644 NuGet.release.config create mode 100644 NuGetPackageVerifier.json create mode 100644 appveyor.yml create mode 100644 build.ps1 mode change 100644 => 100755 build.sh delete mode 100644 makefile.shade create mode 100644 samples/ResponseCachingSample/web.config delete mode 100644 src/Microsoft.AspNet.ResponseCaching/Properties/AssemblyInfo.cs delete mode 100644 src/Microsoft.AspNet.ResponseCaching/project.json rename src/{Microsoft.AspNet.ResponseCaching/Microsoft.AspNet.ResponseCaching.xproj => Microsoft.AspNetCore.ResponseCaching/Microsoft.AspNetCore.ResponseCaching.xproj} (59%) create mode 100644 src/Microsoft.AspNetCore.ResponseCaching/Properties/AssemblyInfo.cs rename src/{Microsoft.AspNet.ResponseCaching/CachingContext.cs => Microsoft.AspNetCore.ResponseCaching/ResponseCachingContext.cs} (87%) rename src/{Microsoft.AspNet.ResponseCaching/ResponseCacheEntry.cs => Microsoft.AspNetCore.ResponseCaching/ResponseCachingEntry.cs} (57%) rename src/{Microsoft.AspNet.ResponseCaching => Microsoft.AspNetCore.ResponseCaching}/ResponseCachingExtensions.cs (83%) rename src/{Microsoft.AspNet.ResponseCaching => Microsoft.AspNetCore.ResponseCaching}/ResponseCachingMiddleware.cs (89%) create mode 100644 src/Microsoft.AspNetCore.ResponseCaching/project.json delete mode 100644 test/Microsoft.AspNet.ResponseCaching.Tests/project.json rename test/{Microsoft.AspNet.ResponseCaching.Tests/Microsoft.AspNet.ResponseCaching.Tests.xproj => Microsoft.AspNetCore.ResponseCaching.Tests/Microsoft.AspNetCore.ResponseCaching.Tests.xproj} (65%) rename test/{Microsoft.AspNet.ResponseCaching.Tests/CachingContextTests.cs => Microsoft.AspNetCore.ResponseCaching.Tests/ResponseCachingContextTests.cs} (67%) create mode 100644 test/Microsoft.AspNetCore.ResponseCaching.Tests/project.json create mode 100644 tools/Key.snk diff --git a/.gitignore b/.gitignore index be311a1..718941c 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,6 @@ [Bb]in/ TestResults/ .nuget/ -*.sln.ide/ _ReSharper.*/ packages/ artifacts/ @@ -24,4 +23,8 @@ nuget.exe *.ncrunchsolution *.*sdf *.ipch -project.lock.json \ No newline at end of file +*.sln.ide +project.lock.json +/.vs/ +.build/ +.testPublish/ \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..ceb3c7b --- /dev/null +++ b/.travis.yml @@ -0,0 +1,28 @@ +language: csharp +sudo: required +dist: trusty +addons: + apt: + packages: + - gettext + - libcurl4-openssl-dev + - libicu-dev + - libssl-dev + - libunwind8 + - zlib1g +mono: + - 4.0.5 +os: + - linux + - osx +osx_image: xcode7.1 +branches: + only: + - master + - release + - dev + - /^(.*\/)?ci-.*$/ +before_install: + - if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; brew link --force openssl; fi +script: + - ./build.sh verify \ No newline at end of file diff --git a/NuGet.Config b/NuGet.Config index 46c3b3e..5500f6d 100644 --- a/NuGet.Config +++ b/NuGet.Config @@ -1,7 +1,7 @@  - - + + diff --git a/NuGet.master.config b/NuGet.master.config deleted file mode 100644 index e2edffc..0000000 --- a/NuGet.master.config +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/NuGet.release.config b/NuGet.release.config deleted file mode 100644 index 1978dc0..0000000 --- a/NuGet.release.config +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/NuGetPackageVerifier.json b/NuGetPackageVerifier.json new file mode 100644 index 0000000..27720e2 --- /dev/null +++ b/NuGetPackageVerifier.json @@ -0,0 +1,15 @@ +{ + "adx": { // Packages written by the ADX team and that ship on NuGet.org + "rules": [ + "AdxVerificationCompositeRule" + ], + "packages": { + "Microsoft.AspNetCore.ResponseCaching": { }, + } + }, + "Default": { // Rules to run for packages not listed in any other set. + "rules": [ + "DefaultCompositeRule" + ] + } +} \ No newline at end of file diff --git a/README.md b/README.md index 4a181c9..cf7ba9f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -ASP.NET Response Caching +ASP.NET Core Response Caching ======== This repo hosts the ASP.NET Core middleware for response caching. diff --git a/ResponseCaching.sln b/ResponseCaching.sln index 358a798..c052708 100644 --- a/ResponseCaching.sln +++ b/ResponseCaching.sln @@ -1,10 +1,8 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 -VisualStudioVersion = 14.0.22823.1 +VisualStudioVersion = 14.0.25420.1 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.ResponseCaching", "src\Microsoft.AspNet.ResponseCaching\Microsoft.AspNet.ResponseCaching.xproj", "{D1031270-DBD3-4F02-A3DC-3E7DADE8EBE6}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{367AABAF-E03C-4491-A9A7-BDDE8903D1B4}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{C51DF5BD-B53D-4795-BC01-A9AB066BF286}" @@ -18,7 +16,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution global.json = global.json EndProjectSection EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.ResponseCaching.Tests", "test\Microsoft.AspNet.ResponseCaching.Tests\Microsoft.AspNet.ResponseCaching.Tests.xproj", "{151B2027-3936-44B9-A4A0-E1E5902125AB}" +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.ResponseCaching.Tests", "test\Microsoft.AspNetCore.ResponseCaching.Tests\Microsoft.AspNetCore.ResponseCaching.Tests.xproj", "{151B2027-3936-44B9-A4A0-E1E5902125AB}" +EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNetCore.ResponseCaching", "src\Microsoft.AspNetCore.ResponseCaching\Microsoft.AspNetCore.ResponseCaching.xproj", "{D1031270-DBD3-4F02-A3DC-3E7DADE8EBE6}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -26,10 +26,6 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {D1031270-DBD3-4F02-A3DC-3E7DADE8EBE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D1031270-DBD3-4F02-A3DC-3E7DADE8EBE6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D1031270-DBD3-4F02-A3DC-3E7DADE8EBE6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D1031270-DBD3-4F02-A3DC-3E7DADE8EBE6}.Release|Any CPU.Build.0 = Release|Any CPU {1139BDEE-FA15-474D-8855-0AB91F23CF26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1139BDEE-FA15-474D-8855-0AB91F23CF26}.Debug|Any CPU.Build.0 = Debug|Any CPU {1139BDEE-FA15-474D-8855-0AB91F23CF26}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -38,13 +34,17 @@ Global {151B2027-3936-44B9-A4A0-E1E5902125AB}.Debug|Any CPU.Build.0 = Debug|Any CPU {151B2027-3936-44B9-A4A0-E1E5902125AB}.Release|Any CPU.ActiveCfg = Release|Any CPU {151B2027-3936-44B9-A4A0-E1E5902125AB}.Release|Any CPU.Build.0 = Release|Any CPU + {D1031270-DBD3-4F02-A3DC-3E7DADE8EBE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D1031270-DBD3-4F02-A3DC-3E7DADE8EBE6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D1031270-DBD3-4F02-A3DC-3E7DADE8EBE6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D1031270-DBD3-4F02-A3DC-3E7DADE8EBE6}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {D1031270-DBD3-4F02-A3DC-3E7DADE8EBE6} = {367AABAF-E03C-4491-A9A7-BDDE8903D1B4} {1139BDEE-FA15-474D-8855-0AB91F23CF26} = {C51DF5BD-B53D-4795-BC01-A9AB066BF286} {151B2027-3936-44B9-A4A0-E1E5902125AB} = {89A50974-E9D4-4F87-ACF2-6A6005E64931} + {D1031270-DBD3-4F02-A3DC-3E7DADE8EBE6} = {367AABAF-E03C-4491-A9A7-BDDE8903D1B4} EndGlobalSection EndGlobal diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..b9a9bcd --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,13 @@ +init: + - git config --global core.autocrlf true +branches: + only: + - master + - release + - dev + - /^(.*\/)?ci-.*$/ +build_script: + - build.cmd verify +clone_depth: 1 +test: off +deploy: off \ No newline at end of file diff --git a/build.cmd b/build.cmd index 41025af..7d4894c 100644 --- a/build.cmd +++ b/build.cmd @@ -1,28 +1,2 @@ -@echo off -cd %~dp0 - -SETLOCAL -SET CACHED_NUGET=%LocalAppData%\NuGet\NuGet.exe - -IF EXIST %CACHED_NUGET% goto copynuget -echo Downloading latest version of NuGet.exe... -IF NOT EXIST %LocalAppData%\NuGet md %LocalAppData%\NuGet -@powershell -NoProfile -ExecutionPolicy unrestricted -Command "$ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest 'https://www.nuget.org/nuget.exe' -OutFile '%CACHED_NUGET%'" - -:copynuget -IF EXIST .nuget\nuget.exe goto restore -md .nuget -copy %CACHED_NUGET% .nuget\nuget.exe > nul - -:restore -IF EXIST packages\KoreBuild goto run -.nuget\NuGet.exe install KoreBuild -ExcludeVersion -o packages -nocache -pre -.nuget\NuGet.exe install Sake -version 0.2 -o packages -ExcludeVersion - -IF "%SKIP_DNX_INSTALL%"=="1" goto run -CALL packages\KoreBuild\build\dnvm upgrade -runtime CLR -arch x86 -CALL packages\KoreBuild\build\dnvm install default -runtime CoreCLR -arch x86 - -:run -CALL packages\KoreBuild\build\dnvm use default -runtime CLR -arch x86 -packages\Sake\tools\Sake.exe -I packages\KoreBuild\build -f makefile.shade %* +@ECHO OFF +PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0build.ps1' %*; exit $LASTEXITCODE" \ No newline at end of file diff --git a/build.ps1 b/build.ps1 new file mode 100644 index 0000000..8f2f996 --- /dev/null +++ b/build.ps1 @@ -0,0 +1,67 @@ +$ErrorActionPreference = "Stop" + +function DownloadWithRetry([string] $url, [string] $downloadLocation, [int] $retries) +{ + while($true) + { + try + { + Invoke-WebRequest $url -OutFile $downloadLocation + break + } + catch + { + $exceptionMessage = $_.Exception.Message + Write-Host "Failed to download '$url': $exceptionMessage" + if ($retries -gt 0) { + $retries-- + Write-Host "Waiting 10 seconds before retrying. Retries left: $retries" + Start-Sleep -Seconds 10 + + } + else + { + $exception = $_.Exception + throw $exception + } + } + } +} + +cd $PSScriptRoot + +$repoFolder = $PSScriptRoot +$env:REPO_FOLDER = $repoFolder + +$koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +if ($env:KOREBUILD_ZIP) +{ + $koreBuildZip=$env:KOREBUILD_ZIP +} + +$buildFolder = ".build" +$buildFile="$buildFolder\KoreBuild.ps1" + +if (!(Test-Path $buildFolder)) { + Write-Host "Downloading KoreBuild from $koreBuildZip" + + $tempFolder=$env:TEMP + "\KoreBuild-" + [guid]::NewGuid() + New-Item -Path "$tempFolder" -Type directory | Out-Null + + $localZipFile="$tempFolder\korebuild.zip" + + DownloadWithRetry -url $koreBuildZip -downloadLocation $localZipFile -retries 6 + + Add-Type -AssemblyName System.IO.Compression.FileSystem + [System.IO.Compression.ZipFile]::ExtractToDirectory($localZipFile, $tempFolder) + + New-Item -Path "$buildFolder" -Type directory | Out-Null + copy-item "$tempFolder\**\build\*" $buildFolder -Recurse + + # Cleanup + if (Test-Path $tempFolder) { + Remove-Item -Recurse -Force $tempFolder + } +} + +&"$buildFile" $args \ No newline at end of file diff --git a/build.sh b/build.sh old mode 100644 new mode 100755 index c8cc2a7..f420810 --- a/build.sh +++ b/build.sh @@ -1,38 +1,46 @@ -#!/bin/bash +#!/usr/bin/env bash +repoFolder="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +cd $repoFolder -if test `uname` = Darwin; then - cachedir=~/Library/Caches/KBuild -else - if [ -z $XDG_DATA_HOME ]; then - cachedir=$HOME/.local/share - else - cachedir=$XDG_DATA_HOME; - fi -fi -mkdir -p $cachedir - -url=https://www.nuget.org/nuget.exe - -if test ! -f $cachedir/nuget.exe; then - wget -O $cachedir/nuget.exe $url 2>/dev/null || curl -o $cachedir/nuget.exe --location $url /dev/null -fi - -if test ! -e .nuget; then - mkdir .nuget - cp $cachedir/nuget.exe .nuget/nuget.exe +koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip" +if [ ! -z $KOREBUILD_ZIP ]; then + koreBuildZip=$KOREBUILD_ZIP fi -if test ! -d packages/KoreBuild; then - mono .nuget/nuget.exe install KoreBuild -ExcludeVersion -o packages -nocache -pre - mono .nuget/nuget.exe install Sake -version 0.2 -o packages -ExcludeVersion -fi - -if ! type dnvm > /dev/null 2>&1; then - source packages/KoreBuild/build/dnvm.sh -fi - -if ! type dnx > /dev/null 2>&1; then - dnvm upgrade +buildFolder=".build" +buildFile="$buildFolder/KoreBuild.sh" + +if test ! -d $buildFolder; then + echo "Downloading KoreBuild from $koreBuildZip" + + tempFolder="/tmp/KoreBuild-$(uuidgen)" + mkdir $tempFolder + + localZipFile="$tempFolder/korebuild.zip" + + retries=6 + until (wget -O $localZipFile $koreBuildZip 2>/dev/null || curl -o $localZipFile --location $koreBuildZip 2>/dev/null) + do + echo "Failed to download '$koreBuildZip'" + if [ "$retries" -le 0 ]; then + exit 1 + fi + retries=$((retries - 1)) + echo "Waiting 10 seconds before retrying. Retries left: $retries" + sleep 10s + done + + unzip -q -d $tempFolder $localZipFile + + mkdir $buildFolder + cp -r $tempFolder/**/build/** $buildFolder + + chmod +x $buildFile + + # Cleanup + if test ! -d $tempFolder; then + rm -rf $tempFolder + fi fi -mono packages/Sake/tools/Sake.exe -I packages/KoreBuild/build -f makefile.shade "$@" +$buildFile -r $repoFolder "$@" \ No newline at end of file diff --git a/global.json b/global.json index 397ac5f..829daad 100644 --- a/global.json +++ b/global.json @@ -1,3 +1,3 @@ { - "projects": ["src"] + "projects": ["src"] } \ No newline at end of file diff --git a/makefile.shade b/makefile.shade deleted file mode 100644 index 562494d..0000000 --- a/makefile.shade +++ /dev/null @@ -1,7 +0,0 @@ - -var VERSION='0.1' -var FULL_VERSION='0.1' -var AUTHORS='Microsoft Open Technologies, Inc.' - -use-standard-lifecycle -k-standard-goals diff --git a/samples/ResponseCachingSample/ResponseCachingSample.xproj b/samples/ResponseCachingSample/ResponseCachingSample.xproj index 2403e53..43167a3 100644 --- a/samples/ResponseCachingSample/ResponseCachingSample.xproj +++ b/samples/ResponseCachingSample/ResponseCachingSample.xproj @@ -4,16 +4,16 @@ 14.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - + 1139bdee-fa15-474d-8855-0ab91f23cf26 ResponseCachingSample - ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + .\obj + .\bin\ 2.0 2931 - + \ No newline at end of file diff --git a/samples/ResponseCachingSample/Startup.cs b/samples/ResponseCachingSample/Startup.cs index 1ca6d9a..eca8af2 100644 --- a/samples/ResponseCachingSample/Startup.cs +++ b/samples/ResponseCachingSample/Startup.cs @@ -2,9 +2,11 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using Microsoft.AspNet.Builder; -using Microsoft.AspNet.Http; -using Microsoft.Framework.DependencyInjection; +using System.IO; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Net.Http.Headers; namespace ResponseCachingSample @@ -13,7 +15,7 @@ public class Startup { public void ConfigureServices(IServiceCollection services) { - services.AddCaching(); + services.AddMemoryCache(); } public void Configure(IApplicationBuilder app) @@ -29,5 +31,17 @@ public void Configure(IApplicationBuilder app) await context.Response.WriteAsync("Hello World! " + DateTime.UtcNow); }); } + + public static void Main(string[] args) + { + var host = new WebHostBuilder() + .UseKestrel() + .UseContentRoot(Directory.GetCurrentDirectory()) + .UseIISIntegration() + .UseStartup() + .Build(); + + host.Run(); + } } } diff --git a/samples/ResponseCachingSample/project.json b/samples/ResponseCachingSample/project.json index ca19e78..a32ead3 100644 --- a/samples/ResponseCachingSample/project.json +++ b/samples/ResponseCachingSample/project.json @@ -1,33 +1,34 @@ { - "webroot": "wwwroot", - "version": "1.0.0-*", - + "version": "1.1.0-*", "dependencies": { - "Microsoft.AspNet.ResponseCaching": "1.0.0-*", - "Microsoft.AspNet.Server.IIS": "1.0.0-*", - "Microsoft.AspNet.Server.WebListener": "1.0.0-*", - "Microsoft.Framework.Caching.Memory": "1.0.0-*" + "Microsoft.AspNetCore.ResponseCaching": "0.1.0-*", + "Microsoft.AspNetCore.Server.IISIntegration": "1.1.0-*", + "Microsoft.AspNetCore.Server.Kestrel": "1.1.0-*", + "Microsoft.Extensions.Caching.Memory": "1.1.0-*" }, - - "commands": { - "web": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.WebListener --server.urls http://localhost:5000" + "buildOptions": { + "emitEntryPoint": true }, - "frameworks": { - "dnx451": { }, - "dnxcore50": { } + "net451": {}, + "netcoreapp1.0": { + "dependencies": { + "Microsoft.NETCore.App": { + "version": "1.0.0-*", + "type": "platform" + } + } + } }, - - "publishExclude": [ - "node_modules", - "bower_components", - "**.xproj", - "**.user", - "**.vspscc" - ], - "exclude": [ - "wwwroot", - "node_modules", - "bower_components" - ] + "publishOptions": { + "include": [ + "web.config" + ] + }, + "tools": { + "Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-*" + }, + "scripts": { + "postpublish": "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" + } } diff --git a/samples/ResponseCachingSample/web.config b/samples/ResponseCachingSample/web.config new file mode 100644 index 0000000..f7ac679 --- /dev/null +++ b/samples/ResponseCachingSample/web.config @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/Microsoft.AspNet.ResponseCaching/Properties/AssemblyInfo.cs b/src/Microsoft.AspNet.ResponseCaching/Properties/AssemblyInfo.cs deleted file mode 100644 index 09bbb58..0000000 --- a/src/Microsoft.AspNet.ResponseCaching/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Reflection; -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo("Microsoft.AspNet.ResponseCaching.Tests")] -[assembly: AssemblyMetadata("Serviceable", "True")] \ No newline at end of file diff --git a/src/Microsoft.AspNet.ResponseCaching/project.json b/src/Microsoft.AspNet.ResponseCaching/project.json deleted file mode 100644 index b7f364b..0000000 --- a/src/Microsoft.AspNet.ResponseCaching/project.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "version": "1.0.0-*", - "description": "Middleare that automatically caches HTTP responses on the server.", - "dependencies": { - "Microsoft.AspNet.Http.Abstractions": "1.0.0-*", - "Microsoft.Framework.Caching.Abstractions": "1.0.0-*" - }, - "frameworks" : { - "dnx451": { }, - "dnxcore50" : { - "dependencies": { - } - } - } -} diff --git a/src/Microsoft.AspNet.ResponseCaching/Microsoft.AspNet.ResponseCaching.xproj b/src/Microsoft.AspNetCore.ResponseCaching/Microsoft.AspNetCore.ResponseCaching.xproj similarity index 59% rename from src/Microsoft.AspNet.ResponseCaching/Microsoft.AspNet.ResponseCaching.xproj rename to src/Microsoft.AspNetCore.ResponseCaching/Microsoft.AspNetCore.ResponseCaching.xproj index bb65aad..a4d4533 100644 --- a/src/Microsoft.AspNet.ResponseCaching/Microsoft.AspNet.ResponseCaching.xproj +++ b/src/Microsoft.AspNetCore.ResponseCaching/Microsoft.AspNetCore.ResponseCaching.xproj @@ -4,17 +4,16 @@ 14.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - + d1031270-dbd3-4f02-a3dc-3e7dade8ebe6 - Microsoft.AspNet.ResponseCaching - ..\artifacts\obj\$(MSBuildProjectName) - ..\artifacts\bin\$(MSBuildProjectName)\ + + + .\obj + .\bin\ - 2.0 - - + + \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.ResponseCaching/Properties/AssemblyInfo.cs b/src/Microsoft.AspNetCore.ResponseCaching/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..32dcddf --- /dev/null +++ b/src/Microsoft.AspNetCore.ResponseCaching/Properties/AssemblyInfo.cs @@ -0,0 +1,11 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Reflection; +using System.Resources; + +[assembly: AssemblyMetadata("Serviceable", "True")] +[assembly: NeutralResourcesLanguage("en-us")] +[assembly: AssemblyCompany("Microsoft Corporation.")] +[assembly: AssemblyCopyright("© Microsoft Corporation. All rights reserved.")] +[assembly: AssemblyProduct("Microsoft ASP.NET Core")] \ No newline at end of file diff --git a/src/Microsoft.AspNet.ResponseCaching/CachingContext.cs b/src/Microsoft.AspNetCore.ResponseCaching/ResponseCachingContext.cs similarity index 87% rename from src/Microsoft.AspNet.ResponseCaching/CachingContext.cs rename to src/Microsoft.AspNetCore.ResponseCaching/ResponseCachingContext.cs index c5586ce..89927a1 100644 --- a/src/Microsoft.AspNet.ResponseCaching/CachingContext.cs +++ b/src/Microsoft.AspNetCore.ResponseCaching/ResponseCachingContext.cs @@ -3,18 +3,17 @@ using System; using System.IO; -using System.Linq; using System.Threading.Tasks; -using Microsoft.AspNet.Http; -using Microsoft.Framework.Caching.Memory; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Caching.Memory; -namespace Microsoft.AspNet.ResponseCaching +namespace Microsoft.AspNetCore.ResponseCaching { - internal class CachingContext + public class ResponseCachingContext { private string _cacheKey; - public CachingContext(HttpContext httpContext, IMemoryCache cache) + public ResponseCachingContext(HttpContext httpContext, IMemoryCache cache) { HttpContext = httpContext; Cache = cache; @@ -32,7 +31,7 @@ public CachingContext(HttpContext httpContext, IMemoryCache cache) private bool CacheResponse { get; set; } - internal bool CheckRequestAllowsCaching() + public bool CheckRequestAllowsCaching() { // Verify the method // TODO: What other methods should be supported? @@ -64,7 +63,7 @@ private string CreateCacheKey() internal async Task TryServeFromCacheAsync() { _cacheKey = CreateCacheKey(); - ResponseCacheEntry cacheEntry; + ResponseCachingEntry cacheEntry; if (Cache.TryGetValue(_cacheKey, out cacheEntry)) { // TODO: Compare cached request headers @@ -80,7 +79,7 @@ internal async Task TryServeFromCacheAsync() response.StatusCode = cacheEntry.StatusCode; foreach (var pair in cacheEntry.Headers) { - response.Headers.SetValues(pair.Key, pair.Value); + response.Headers[pair.Key] = pair.Value; } // TODO: Update cache headers (Age) @@ -122,9 +121,12 @@ internal void FinalizeCaching() if (CacheResponse) { // Store the buffer to cache - var cacheEntry = new ResponseCacheEntry(); + var cacheEntry = new ResponseCachingEntry(); cacheEntry.StatusCode = HttpContext.Response.StatusCode; - cacheEntry.Headers = HttpContext.Response.Headers.ToList(); + foreach (var pair in HttpContext.Response.Headers) + { + cacheEntry.Headers[pair.Key] = pair.Value; + } cacheEntry.Body = Buffer.ToArray(); Cache.Set(_cacheKey, cacheEntry); // TODO: Timeouts } diff --git a/src/Microsoft.AspNet.ResponseCaching/ResponseCacheEntry.cs b/src/Microsoft.AspNetCore.ResponseCaching/ResponseCachingEntry.cs similarity index 57% rename from src/Microsoft.AspNet.ResponseCaching/ResponseCacheEntry.cs rename to src/Microsoft.AspNetCore.ResponseCaching/ResponseCachingEntry.cs index f23685d..c372e9a 100644 --- a/src/Microsoft.AspNet.ResponseCaching/ResponseCacheEntry.cs +++ b/src/Microsoft.AspNetCore.ResponseCaching/ResponseCachingEntry.cs @@ -1,14 +1,14 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System.Collections.Generic; +using Microsoft.AspNetCore.Http; -namespace Microsoft.AspNet.ResponseCaching +namespace Microsoft.AspNetCore.ResponseCaching { - internal class ResponseCacheEntry + internal class ResponseCachingEntry { public int StatusCode { get; set; } - internal IEnumerable> Headers { get; set; } + internal IHeaderDictionary Headers { get; set; } = new HeaderDictionary(); internal byte[] Body { get; set; } } } diff --git a/src/Microsoft.AspNet.ResponseCaching/ResponseCachingExtensions.cs b/src/Microsoft.AspNetCore.ResponseCaching/ResponseCachingExtensions.cs similarity index 83% rename from src/Microsoft.AspNet.ResponseCaching/ResponseCachingExtensions.cs rename to src/Microsoft.AspNetCore.ResponseCaching/ResponseCachingExtensions.cs index 6632ad0..60817a6 100644 --- a/src/Microsoft.AspNet.ResponseCaching/ResponseCachingExtensions.cs +++ b/src/Microsoft.AspNetCore.ResponseCaching/ResponseCachingExtensions.cs @@ -1,9 +1,9 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using Microsoft.AspNet.ResponseCaching; +using Microsoft.AspNetCore.ResponseCaching; -namespace Microsoft.AspNet.Builder +namespace Microsoft.AspNetCore.Builder { public static class ResponseCachingExtensions { diff --git a/src/Microsoft.AspNet.ResponseCaching/ResponseCachingMiddleware.cs b/src/Microsoft.AspNetCore.ResponseCaching/ResponseCachingMiddleware.cs similarity index 89% rename from src/Microsoft.AspNet.ResponseCaching/ResponseCachingMiddleware.cs rename to src/Microsoft.AspNetCore.ResponseCaching/ResponseCachingMiddleware.cs index 0c0fda4..6e64205 100644 --- a/src/Microsoft.AspNet.ResponseCaching/ResponseCachingMiddleware.cs +++ b/src/Microsoft.AspNetCore.ResponseCaching/ResponseCachingMiddleware.cs @@ -2,11 +2,10 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Threading.Tasks; -using Microsoft.AspNet.Builder; -using Microsoft.AspNet.Http; -using Microsoft.Framework.Caching.Memory; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Caching.Memory; -namespace Microsoft.AspNet.ResponseCaching +namespace Microsoft.AspNetCore.ResponseCaching { // http://tools.ietf.org/html/rfc7234 public class ResponseCachingMiddleware @@ -22,7 +21,7 @@ public ResponseCachingMiddleware(RequestDelegate next, IMemoryCache cache) public async Task Invoke(HttpContext context) { - var cachingContext = new CachingContext(context, _cache); + var cachingContext = new ResponseCachingContext(context, _cache); // Should we attempt any caching logic? if (cachingContext.CheckRequestAllowsCaching()) { diff --git a/src/Microsoft.AspNetCore.ResponseCaching/project.json b/src/Microsoft.AspNetCore.ResponseCaching/project.json new file mode 100644 index 0000000..8023c1b --- /dev/null +++ b/src/Microsoft.AspNetCore.ResponseCaching/project.json @@ -0,0 +1,31 @@ +{ + "version": "0.1.0-*", + "buildOptions": { + "warningsAsErrors": true, + "keyFile": "../../tools/Key.snk", + "nowarn": [ + "CS1591" + ], + "xmlDoc": true + }, + "description": "ASP.NET Core middleware for caching HTTP responses on the server.", + "packOptions": { + "repository": { + "type": "git", + "url": "git://github.com/aspnet/ResponseCaching" + }, + "tags": [ + "aspnetcore", + "cache", + "caching" + ] + }, + "dependencies": { + "Microsoft.AspNetCore.Http": "1.1.0-*", + "Microsoft.Extensions.Caching.Abstractions": "1.1.0-*" + }, + "frameworks": { + "net451": {}, + "netstandard1.3": {} + } +} diff --git a/test/Microsoft.AspNet.ResponseCaching.Tests/project.json b/test/Microsoft.AspNet.ResponseCaching.Tests/project.json deleted file mode 100644 index 5ad3ebb..0000000 --- a/test/Microsoft.AspNet.ResponseCaching.Tests/project.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "dependencies": { - "Microsoft.AspNet.ResponseCaching": "1.0.0-*", - "xunit.runner.aspnet": "2.0.0-aspnet-*", - "Microsoft.AspNet.Http": "1.0.0-beta5-11528", - "Microsoft.Framework.Caching.Memory": "1.0.0-beta5-11395" - }, - "commands": { - "test": "xunit.runner.aspnet" - }, - "frameworks": { - "dnx451": { }, - "dnxcore50": { } - } -} diff --git a/test/Microsoft.AspNet.ResponseCaching.Tests/Microsoft.AspNet.ResponseCaching.Tests.xproj b/test/Microsoft.AspNetCore.ResponseCaching.Tests/Microsoft.AspNetCore.ResponseCaching.Tests.xproj similarity index 65% rename from test/Microsoft.AspNet.ResponseCaching.Tests/Microsoft.AspNet.ResponseCaching.Tests.xproj rename to test/Microsoft.AspNetCore.ResponseCaching.Tests/Microsoft.AspNetCore.ResponseCaching.Tests.xproj index ee98d4b..fce0536 100644 --- a/test/Microsoft.AspNet.ResponseCaching.Tests/Microsoft.AspNet.ResponseCaching.Tests.xproj +++ b/test/Microsoft.AspNetCore.ResponseCaching.Tests/Microsoft.AspNetCore.ResponseCaching.Tests.xproj @@ -4,17 +4,15 @@ 14.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - + 151b2027-3936-44b9-a4a0-e1e5902125ab Microsoft.AspNet.ResponseCaching.Tests - ..\..\artifacts\obj\$(MSBuildProjectName) - ..\..\artifacts\bin\$(MSBuildProjectName)\ + .\obj + .\bin\ - 2.0 - - + + \ No newline at end of file diff --git a/test/Microsoft.AspNet.ResponseCaching.Tests/CachingContextTests.cs b/test/Microsoft.AspNetCore.ResponseCaching.Tests/ResponseCachingContextTests.cs similarity index 67% rename from test/Microsoft.AspNet.ResponseCaching.Tests/CachingContextTests.cs rename to test/Microsoft.AspNetCore.ResponseCaching.Tests/ResponseCachingContextTests.cs index d0315b5..dc9462d 100644 --- a/test/Microsoft.AspNet.ResponseCaching.Tests/CachingContextTests.cs +++ b/test/Microsoft.AspNetCore.ResponseCaching.Tests/ResponseCachingContextTests.cs @@ -1,20 +1,20 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using Microsoft.AspNet.Http.Internal; -using Microsoft.Framework.Caching.Memory; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Caching.Memory; using Xunit; -namespace Microsoft.AspNet.ResponseCaching +namespace Microsoft.AspNetCore.ResponseCaching { - public class CachingContextTests + public class ResponseCachingContextTests { [Fact] public void CheckRequestAllowsCaching_Method_GET_Allowed() { var httpContext = new DefaultHttpContext(); httpContext.Request.Method = "GET"; - var context = new CachingContext(httpContext, new MemoryCache(new MemoryCacheOptions())); + var context = new ResponseCachingContext(httpContext, new MemoryCache(new MemoryCacheOptions())); Assert.True(context.CheckRequestAllowsCaching()); } @@ -25,7 +25,7 @@ public void CheckRequestAllowsCaching_Method_Unsafe_NotAllowed(string method) { var httpContext = new DefaultHttpContext(); httpContext.Request.Method = method; - var context = new CachingContext(httpContext, new MemoryCache(new MemoryCacheOptions())); + var context = new ResponseCachingContext(httpContext, new MemoryCache(new MemoryCacheOptions())); Assert.False(context.CheckRequestAllowsCaching()); } diff --git a/test/Microsoft.AspNetCore.ResponseCaching.Tests/project.json b/test/Microsoft.AspNetCore.ResponseCaching.Tests/project.json new file mode 100644 index 0000000..be74f33 --- /dev/null +++ b/test/Microsoft.AspNetCore.ResponseCaching.Tests/project.json @@ -0,0 +1,25 @@ +{ + "buildOptions": { + "warningsAsErrors": true, + "keyFile": "../../tools/Key.snk" + }, + "dependencies": { + "dotnet-test-xunit": "2.2.0-*", + "Microsoft.AspNetCore.Http": "1.1.0-*", + "Microsoft.AspNetCore.ResponseCaching": "0.1.0-*", + "Microsoft.Extensions.Caching.Memory": "1.1.0-*", + "xunit": "2.2.0-*" + }, + "frameworks": { + "netcoreapp1.0": { + "dependencies": { + "Microsoft.NETCore.App": { + "version": "1.0.0-*", + "type": "platform" + } + } + }, + "net451": {} + }, + "testRunner": "xunit" +} diff --git a/tools/Key.snk b/tools/Key.snk new file mode 100644 index 0000000000000000000000000000000000000000..e10e4889c125d3120cd9e81582243d70f7cbb806 GIT binary patch literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50098=Iw=HCsnz~#iVhm& zj%TU(_THUee?3yHBjk$37ysB?i5#7WD$={H zV4B!OxRPrb|8)HPg~A}8P>^=#y<)56#=E&NzcjOtPK~<4n6GHt=K$ro*T(lhby_@U zEk(hLzk1H)0yXj{A_5>fk-TgNoP|q6(tP2xo8zt8i%212CWM#AeCd?`hS|4~L({h~Moo(~vy&3Z z1uI}`fd^*>o=rwbAGymj6RM^pZm(*Kfhs+Y1#`-2JPWZMK8@;ZWCk2+9bX4YP);~fj-BU*R zQPvWv$89!{Rl9wM+zR>_TSkn^voYxA?2G iKnV#iZ6Ah`K>b=@=IjYJXrxL124zR(38)nxe+&q_$QXwJ literal 0 HcmV?d00001