diff --git a/.nuget/packages.config b/.nuget/packages.config
index b3d73c344..9e830ed15 100644
--- a/.nuget/packages.config
+++ b/.nuget/packages.config
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/src/NuGet.Indexing/AzureDirectorySynchronizer.cs b/src/NuGet.Indexing/AzureDirectorySynchronizer.cs
index 8f57764ef..ab4d08dfa 100644
--- a/src/NuGet.Indexing/AzureDirectorySynchronizer.cs
+++ b/src/NuGet.Indexing/AzureDirectorySynchronizer.cs
@@ -104,7 +104,7 @@ private static void UnidirectionalSync(AzureDirectory sourceDirectory, Directory
// we'll remove old files from both AzureDirectory's cache directory, as well as our destination directory
// (only when older than 45 minutes - old files may still have active searches on them so we need a margin)
- var referenceTimestamp = LuceneTimestampFromDateTime(DateTimeOffset.UtcNow.AddMinutes(-45));
+ var referenceTimestamp = LuceneTimestampFromDateTime(DateTime.UtcNow.AddMinutes(-45));
// remove old files from AzureDirectory cache directory
RemoveOldFiles(sourceDirectory.CacheDirectory, sourceFiles, referenceTimestamp);
@@ -126,11 +126,10 @@ private static void RemoveOldFiles(Directory directory, string[] skipFiles, long
}
}
- private static long LuceneTimestampFromDateTime(DateTimeOffset date)
+ private static long LuceneTimestampFromDateTime(DateTime date)
{
- var epoch = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
-
- return (date.UtcTicks - epoch.UtcTicks) / TimeSpan.TicksPerSecond * 1000;
+ // Use ToFileTimeUtc here to stay consistent with the returns from AzureDirectory.
+ return date.ToFileTimeUtc();
}
}
}
diff --git a/src/NuGet.Indexing/NuGet.Indexing.csproj b/src/NuGet.Indexing/NuGet.Indexing.csproj
index a47a4a945..56010c62b 100644
--- a/src/NuGet.Indexing/NuGet.Indexing.csproj
+++ b/src/NuGet.Indexing/NuGet.Indexing.csproj
@@ -234,6 +234,7 @@
+
diff --git a/src/NuGet.Indexing/NuGetSearcherManager.cs b/src/NuGet.Indexing/NuGetSearcherManager.cs
index f9eca906c..4d0642ee6 100644
--- a/src/NuGet.Indexing/NuGetSearcherManager.cs
+++ b/src/NuGet.Indexing/NuGetSearcherManager.cs
@@ -121,7 +121,7 @@ public class NuGetSearcherManager : SearcherManager
if (directory == null)
{
var sourceDirectory = new AzureDirectory(storageAccount, indexContainer);
- directory = new RAMDirectory(sourceDirectory); // initial copy from storage to RAM
+ directory = new RAMDirectoryWrapper(sourceDirectory); // initial copy from storage to RAM
azureDirectorySynchronizer = new AzureDirectorySynchronizer(sourceDirectory, directory);
}
diff --git a/src/NuGet.Indexing/RAMDirectoryWrapper.cs b/src/NuGet.Indexing/RAMDirectoryWrapper.cs
new file mode 100644
index 000000000..6a10ebe5d
--- /dev/null
+++ b/src/NuGet.Indexing/RAMDirectoryWrapper.cs
@@ -0,0 +1,36 @@
+using Lucene.Net.Store;
+using System;
+
+namespace NuGet.Indexing
+{
+ ///
+ /// This class wraps the RAMDirectory so we can correct the return of FileModified function
+ ///
+ public class RAMDirectoryWrapper: RAMDirectory
+ {
+ public RAMDirectoryWrapper() : base() { }
+
+ public RAMDirectoryWrapper(Directory seedDirectory) : base(seedDirectory) { }
+
+ ///
+ /// Returns the time (as a long) the named file was last modified in a Windows FileTime in UTC
+ ///
+ /// File Name
+ /// A long that represents a UTC Windows FileTime
+ /// The implementation here is to keep in line with the implementation in AzureDirectory for use in the .
+ /// See https://github.com/azure-contrib/AzureDirectory/blob/master/AzureDirectory/AzureDirectory.cs#L147 for AzureDirectory implementation
+ public override long FileModified(string name)
+ {
+ // The RAMDirectory implementation of FileModified creates a dateTime, converts to localTime, and then uses ticks to get milliseconds.
+ // Undo this conversion here so we can get the file modified time in ticks back (accurate to the millisecond, we lose some precision here)
+ // Then operate on this to get back a "standard" utc windows filetime.
+ // See https://lucenenet.apache.org/docs/3.0.3/d7/df5/_r_a_m_directory_8cs_source.html line 114 for more details.
+
+ var originalTicks = base.FileModified(name) * TimeSpan.TicksPerMillisecond;
+
+ var newTime = new DateTime(originalTicks, DateTimeKind.Local);
+
+ return newTime.ToUniversalTime().ToFileTimeUtc();
+ }
+ }
+}
diff --git a/src/NuGet.Services.BasicSearch/Startup.cs b/src/NuGet.Services.BasicSearch/Startup.cs
index ad99d1f84..8e15bf2bc 100644
--- a/src/NuGet.Services.BasicSearch/Startup.cs
+++ b/src/NuGet.Services.BasicSearch/Startup.cs
@@ -71,6 +71,13 @@ public void Configuration(IAppBuilder app, IConfiguration configuration, Directo
// Add Application Insights
app.Use(typeof(RequestTrackingMiddleware));
+ // Enable HSTS
+ app.Use(async (context, next) =>
+ {
+ context.Response.Headers.Add("Strict-Transport-Security", new string[] { "max-age=31536000; includeSubDomains" });
+ await next.Invoke();
+ });
+
// Enable CORS
var corsPolicy = new CorsPolicy
{
diff --git a/tests/NuGet.Services.BasicSearchTests/TestSupport/LuceneDirectoryInitializer.cs b/tests/NuGet.Services.BasicSearchTests/TestSupport/LuceneDirectoryInitializer.cs
index 8819253f1..33381c5c3 100644
--- a/tests/NuGet.Services.BasicSearchTests/TestSupport/LuceneDirectoryInitializer.cs
+++ b/tests/NuGet.Services.BasicSearchTests/TestSupport/LuceneDirectoryInitializer.cs
@@ -59,7 +59,7 @@ private Lucene.Net.Store.Directory CreateLuceneIndex(IEnumerable
}
else
{
- directory = new RAMDirectory();
+ directory = new RAMDirectoryWrapper();
}
using (var indexWriter = DocumentCreator.CreateIndexWriter(directory, true))