Skip to content

Commit 0f2e2b9

Browse files
authored
Allow tracing of specific uploads on back end. (#6433)
* Allow tracing of specific uploads on back end. * Move key extraction to a new helper. Move guid generation to serverside * Adding null check. Fix tests.
1 parent c3127aa commit 0f2e2b9

9 files changed

Lines changed: 87 additions & 17 deletions

File tree

src/NuGetGallery.Core/CoreConstants.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,7 @@ public static class CoreConstants
3939
public const string SymbolPackagesFolderName = "symbol-packages";
4040
public const string NuGetSymbolPackageFileExtension = ".snupkg";
4141
public const string SymbolPackageBackupsFolderName = "symbol-package-backups";
42+
43+
public const string UploadTracingKeyHeaderName = "upload-id";
4244
}
4345
}

src/NuGetGallery/Authentication/AsyncFileUpload/AsyncFileUploadExtensions.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,27 @@ namespace NuGetGallery.AsyncFileUpload
77
{
88
public static class AsyncFileUploadExtensions
99
{
10-
public static void SetProgress(this ICacheService cacheService, string username, AsyncFileUploadProgress progress)
10+
public static void SetProgress(this ICacheService cacheService, string uploadKey, AsyncFileUploadProgress progress)
1111
{
12-
string cacheKey = GetUpdateCacheKey(username);
12+
string cacheKey = GetUpdateCacheKey(uploadKey);
1313
cacheService.SetItem(cacheKey, progress, TimeSpan.FromHours(1));
1414
}
1515

16-
public static AsyncFileUploadProgress GetProgress(this ICacheService cacheService, string username)
16+
public static AsyncFileUploadProgress GetProgress(this ICacheService cacheService, string uploadKey)
1717
{
18-
string cacheKey = GetUpdateCacheKey(username);
18+
string cacheKey = GetUpdateCacheKey(uploadKey);
1919
return cacheService.GetItem(cacheKey) as AsyncFileUploadProgress;
2020
}
2121

22-
public static void RemoveProgress(this ICacheService cacheService, string username)
22+
public static void RemoveProgress(this ICacheService cacheService, string uploadKey)
2323
{
24-
string cacheKey = GetUpdateCacheKey(username);
24+
string cacheKey = GetUpdateCacheKey(uploadKey);
2525
cacheService.RemoveItem(cacheKey);
2626
}
2727

28-
private static string GetUpdateCacheKey(string username)
28+
private static string GetUpdateCacheKey(string uploadKey)
2929
{
30-
return "upload-" + username;
30+
return "upload-" + uploadKey;
3131
}
3232
}
3333
}

src/NuGetGallery/Authentication/AsyncFileUpload/AsyncFileUploadModule.cs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33
using System;
4+
using System.Collections.Generic;
45
using System.Diagnostics;
56
using System.IO;
67
using System.Web;
78
using Autofac;
89
using Autofac.Integration.Mvc;
10+
using NuGetGallery.Helpers;
911

1012
namespace NuGetGallery.AsyncFileUpload
1113
{
@@ -50,8 +52,12 @@ private void PostAuthorizeRequest(object sender, EventArgs e)
5052
string boundary = "--" + contentType.Substring(boundaryIndex + 9);
5153
var requestParser = new AsyncFileUploadRequestParser(boundary, request.ContentEncoding);
5254

55+
var headers = request.Headers;
56+
string uploadTracingKey = UploadHelper.GetUploadTracingKey(headers);
57+
5358
var progress = new AsyncFileUploadProgress(request.ContentLength);
54-
_cacheService.SetProgress(username, progress);
59+
var uploadKey = username + uploadTracingKey;
60+
_cacheService.SetProgress(uploadKey, progress);
5561

5662
if (request.ReadEntityBodyMode != ReadEntityBodyMode.None)
5763
{
@@ -61,11 +67,11 @@ private void PostAuthorizeRequest(object sender, EventArgs e)
6167
Stream uploadStream = request.GetBufferedInputStream();
6268
Debug.Assert(uploadStream != null);
6369

64-
ReadStream(uploadStream, request, username, progress, requestParser);
70+
ReadStream(uploadStream, request, uploadKey, progress, requestParser);
6571
}
6672

6773
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "request", Justification="'request' parameter is used in debug build.")]
68-
private void ReadStream(Stream stream, HttpRequest request, string username, AsyncFileUploadProgress progress, AsyncFileUploadRequestParser parser)
74+
private void ReadStream(Stream stream, HttpRequest request, string uploadKey, AsyncFileUploadProgress progress, AsyncFileUploadRequestParser parser)
6975
{
7076
const int bufferSize = 1024 * 4; // in bytes
7177

@@ -83,7 +89,7 @@ private void ReadStream(Stream stream, HttpRequest request, string username, Asy
8389
progress.FileName = parser.CurrentFileName;
8490
}
8591

86-
_cacheService.SetProgress(username, progress);
92+
_cacheService.SetProgress(uploadKey, progress);
8793

8894
#if DEBUG
8995
if (request.IsLocal)

src/NuGetGallery/Controllers/PackagesController.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,11 @@ public PackagesController(
138138
public virtual JsonResult UploadPackageProgress()
139139
{
140140
string username = User.Identity.Name;
141+
string uploadTracingKey = UploadHelper.GetUploadTracingKey(Request.Headers);
141142

142-
AsyncFileUploadProgress progress = _cacheService.GetProgress(username);
143+
var uploadKey = username + uploadTracingKey;
144+
145+
AsyncFileUploadProgress progress = _cacheService.GetProgress(uploadKey);
143146
if (progress == null)
144147
{
145148
return Json(HttpStatusCode.NotFound, null, JsonRequestBehavior.AllowGet);
@@ -226,6 +229,8 @@ public virtual async Task<JsonResult> UploadPackage(HttpPostedFileBase uploadFil
226229
{
227230
var currentUser = GetCurrentUser();
228231

232+
string uploadTracingKey = UploadHelper.GetUploadTracingKey(Request.Headers);
233+
229234
using (var existingUploadFile = await _uploadFileService.GetUploadFileAsync(currentUser.Key))
230235
{
231236
if (existingUploadFile != null)
@@ -288,7 +293,9 @@ public virtual async Task<JsonResult> UploadPackage(HttpPostedFileBase uploadFil
288293
}
289294
finally
290295
{
291-
_cacheService.RemoveProgress(currentUser.Username);
296+
var username = currentUser.Username;
297+
var uploadKey = username + uploadTracingKey;
298+
_cacheService.RemoveProgress(uploadKey);
292299
}
293300

294301
NuspecReader nuspec;
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Collections.Specialized;
7+
8+
namespace NuGetGallery.Helpers
9+
{
10+
public static class UploadHelper
11+
{
12+
public static string GetUploadTracingKey(NameValueCollection headers)
13+
{
14+
if (headers == null)
15+
{
16+
return Guid.Empty.ToString();
17+
}
18+
19+
string uploadTracingKey;
20+
try
21+
{
22+
uploadTracingKey = headers[CoreConstants.UploadTracingKeyHeaderName];
23+
Guid.Parse(uploadTracingKey);
24+
}
25+
catch (Exception ex) when (ex is FormatException || ex is KeyNotFoundException)
26+
{
27+
// An upload tracing key was not found
28+
// Simultaneous UI uploads might have strange behaviour.
29+
// Note that we might have this case if an old client sends to new Server.
30+
uploadTracingKey = Guid.Empty.ToString();
31+
}
32+
33+
return uploadTracingKey;
34+
}
35+
}
36+
}

src/NuGetGallery/NuGetGallery.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@
295295
<Compile Include="Helpers\PermissionsHelpers.cs" />
296296
<Compile Include="Helpers\RegexEx.cs" />
297297
<Compile Include="Helpers\RouteUrlTemplate.cs" />
298+
<Compile Include="Helpers\UploadHelper.cs" />
298299
<Compile Include="Helpers\UriExtensions.cs" />
299300
<Compile Include="Infrastructure\Authentication\ApiKeyV3.cs" />
300301
<Compile Include="Infrastructure\Authentication\ApiKeyV4.cs" />

src/NuGetGallery/Scripts/gallery/async-file-upload.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
1414
var _pingUrl;
1515
var _isUploadInProgress;
1616
var _uploadStartTime;
17+
var _uploadId;
1718

18-
this.init = function (pingUrl, formId, jQueryUrl, actionUrl, cancelUrl, submitVerifyUrl) {
19+
this.init = function (pingUrl, formId, jQueryUrl, actionUrl, cancelUrl, submitVerifyUrl, uploadTracingKey) {
20+
_uploadId = uploadTracingKey;
1921
_pingUrl = pingUrl;
2022
_uploadFormId = formId;
2123
_actionUrl = actionUrl;
@@ -104,6 +106,10 @@
104106

105107
data: _uploadFormData,
106108

109+
headers: {
110+
"upload-id": _uploadId
111+
},
112+
107113
cache: false,
108114
contentType: false,
109115
processData: false,
@@ -127,6 +133,10 @@
127133

128134
data: new FormData($('#verify-metadata-form')[0]),
129135

136+
headers: {
137+
"upload-id": _uploadId
138+
},
139+
130140
cache: false,
131141
contentType: false,
132142
processData: false,
@@ -150,6 +160,10 @@
150160

151161
data: new FormData($('#cancel-form')[0]),
152162

163+
headers: {
164+
"upload-id": _uploadId
165+
},
166+
153167
cache: false,
154168
contentType: false,
155169
processData: false,
@@ -305,6 +319,9 @@
305319
type: 'GET',
306320
dataType: 'json',
307321
url: _pingUrl,
322+
headers: {
323+
"upload-id": _uploadId
324+
},
308325
success: onGetProgressSuccess,
309326
error: onGetProgressError
310327
});

src/NuGetGallery/Views/Packages/UploadPackage.cshtml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@
7474
'@Scripts.Url("~/Scripts/jquery")',
7575
'@Url.UploadPackage()',
7676
'@Url.CancelUpload()',
77-
'@Url.VerifyPackage()');
77+
'@Url.VerifyPackage()',
78+
'@Guid.NewGuid()');
7879
});
7980
</script>
8081
}

tests/NuGetGallery.Facts/Controllers/PackagesControllerFacts.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5480,7 +5480,7 @@ public async Task WillApplyReadMeForWrittenReadMeData(EditPackageVersionReadMeRe
54805480

54815481
public class TheUploadProgressAction : TestContainer
54825482
{
5483-
private static readonly string FakeUploadName = "upload-" + TestUtility.FakeUserName;
5483+
private static readonly string FakeUploadName = "upload-" + TestUtility.FakeUserName + Guid.Empty.ToString();
54845484

54855485
[Fact]
54865486
public void WillReturnHttpNotFoundForUnknownUser()

0 commit comments

Comments
 (0)